JavaScript的React框架中的JSX語(yǔ)法學(xué)習(xí)入門教程
什么是JSX?
在用React寫組件的時(shí)候,通常會(huì)用到JSX語(yǔ)法,粗看上去,像是在Javascript代碼里直接寫起了XML標(biāo)簽,實(shí)質(zhì)上這只是一個(gè)語(yǔ)法糖,每一個(gè)XML標(biāo)簽都會(huì)被JSX轉(zhuǎn)換工具轉(zhuǎn)換成純Javascript代碼,當(dāng)然你想直接使用純Javascript代碼寫也是可以的,只是利用JSX,組件的結(jié)構(gòu)和組件之間的關(guān)系看上去更加清晰。
var MyComponent = React.createClass({/*...*/}); var myElement = <MyComponent someProperty={true} />; React.render(myElement, document.body);
一個(gè)XML標(biāo)簽,比如<MyComponent someProperty={true} />會(huì)被JSX轉(zhuǎn)換工具轉(zhuǎn)換成什么呢?
比如:
var Nav = React.createClass({/*...*/}); var app = <Nav color="blue"><Profile>click</Profile></Nav>;
會(huì)被轉(zhuǎn)化為:
var Nav = React.createClass({/*...*/}); var app = React.createElement( Nav, {color:"blue"}, React.createElement(Profile, null, "click") );
那么也就是說(shuō),我們寫一個(gè)XML標(biāo)簽,實(shí)質(zhì)上就是在調(diào)用React.createElement這個(gè)方法,并返回一個(gè)ReactElement對(duì)象。
ReactElement createElement( string/ReactClass type, [object props], [children ...] )
這個(gè)方法的第一個(gè)參數(shù)可以是一個(gè)字符串,表示是一個(gè)HTML標(biāo)準(zhǔn)內(nèi)的元素,或者是一個(gè)ReactClass類型的對(duì)象,表示我們之前封裝好的自定義組件。第二個(gè)參數(shù)是一個(gè)對(duì)象,或者說(shuō)是字典也可以,它保存了這個(gè)元素的所有固有屬性(即傳入后基本不會(huì)改變的值)。從第三個(gè)參數(shù)開(kāi)始,之后的參數(shù)都被認(rèn)作是元素的子元素。
JSX轉(zhuǎn)化器
要把帶有JSX語(yǔ)法的代碼轉(zhuǎn)化為純Javascript代碼,有多種方式,對(duì)于內(nèi)聯(lián)與HTML中的代碼或者是未經(jīng)過(guò)轉(zhuǎn)化的外部文件,在script標(biāo)簽中要加上type="text/jsx",并引入JSXTransformer.js文件即可,不過(guò)這種方式并不建議在生產(chǎn)環(huán)境使用,建議的方法是在代碼上線前就將代碼轉(zhuǎn)換好,可以使用npm全局安裝react-tools:
npm install -g react-tools
并使用命令行工具轉(zhuǎn)化即可(具體用法可以參考jsx -h):
jsx src/ build/
如果使用自動(dòng)化工具,比如gulp的話,可以使用相應(yīng)插件gulp-react。
HTML模板中使用JS
在HTML模板中使用JS非常方便,只需要用大括號(hào)把JS代碼括起來(lái)即可。
var names = ['Alice', 'Emily', 'Kate']; React.render( <div> { names.map(function (name) { return <div>Hello, {name}!</div> }) } </div>, document.getElementById('example') );
編譯出來(lái)就變成了這樣:
var names = ['Alice', 'Emily', 'Kate']; React.render( React.createElement("div", null, names.map(function (name) { return React.createElement("div", null, "Hello, ", name, "!") }) ), document.getElementById('example') );
要注意的是,大括號(hào)實(shí)際就是一個(gè)變量輸出表達(dá)式,JSX最終就是直接把花括號(hào)中的內(nèi)容作為 React.createElement 的第三個(gè)參數(shù)直接傳入了(沒(méi)有任何修改直接傳入),所以其中只能放一行表達(dá)式,并且任何不能直接作為第三個(gè)參數(shù)的寫法都是錯(cuò)的,那么你這樣寫就是錯(cuò)的:
React.render( <div> { var a = 1; names.map(function (name) { return <div>Hello, {name}!</div> }) } </div>, document.getElementById('example') );
因?yàn)楹苊黠@其中花括號(hào)內(nèi)的內(nèi)容直接放在第三個(gè)參數(shù)上,語(yǔ)法不對(duì)。
這么寫也是錯(cuò)的:
React.render( <div> { var a = 1; } </div>, document.getElementById('example') );
因?yàn)?React.createElement(“div”, null, var a = 1;) 是語(yǔ)法錯(cuò)誤。
那么你也可以理解為什么大括號(hào)中的js表達(dá)式不能有分號(hào)結(jié)尾了吧。
需要注意的是,如果你在屬性中輸出JS變量,是不能加引號(hào)的,不然會(huì)被當(dāng)做字符串而不被解析。
應(yīng)該是這樣:
<a title={title}>鏈接</a>
使用HTML標(biāo)簽
要?jiǎng)?chuàng)建一個(gè)HTML標(biāo)準(zhǔn)中存在的元素,直接像寫HTML代碼一樣即可:
var myDivElement = <div className="foo" />; React.render(myDivElement, document.body);
不過(guò)需要注意的是class和for這兩個(gè)屬性,JSX語(yǔ)法最終是要被轉(zhuǎn)換為純Javascript的,所以要和在Javascript DOM中一樣,用className和htmlFor。
還有一點(diǎn)是,在創(chuàng)建HTML標(biāo)準(zhǔn)內(nèi)的元素時(shí),JSX轉(zhuǎn)化器會(huì)丟棄那些非標(biāo)準(zhǔn)的屬性,如果一定要添加自定義屬性,那么需要在這些自定義屬性之前添加data-前綴。
<div data-custom-attribute="foo" />
命名空間式組件
比如開(kāi)發(fā)組件的時(shí)候,一個(gè)組件有多個(gè)子組件,你希望這些子組件可以作為其父組件的屬性,那么可以像這樣用:
var Form = MyFormComponent; var App = ( <Form> <Form.Row> <Form.Label /> <Form.Input /> </Form.Row> </Form> );
這樣你只需將子組件的ReactClass作為其父組件的屬性:
var MyFormComponent = React.createClass({ ... }); MyFormComponent.Row = React.createClass({ ... }); MyFormComponent.Label = React.createClass({ ... }); MyFormComponent.Input = React.createClass({ ... });
而創(chuàng)建子元素可以直接交給JSX轉(zhuǎn)化器:
var App = ( React.createElement(Form, null, React.createElement(Form.Row, null, React.createElement(Form.Label, null), React.createElement(Form.Input, null) ) ) );
該功能需要0.11及以上版本
Javascript表達(dá)式
在JSX語(yǔ)法中寫Javascript表達(dá)式只需要用{}即可,比如下面這個(gè)使用三目運(yùn)算符的例子:
// Input (JSX): var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>; // Output (JS): var content = React.createElement( Container, null, window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login) );
不過(guò)要注意的是,JSX語(yǔ)法只是語(yǔ)法糖,它的背后是調(diào)用ReactElement的構(gòu)造方法React.createElement的,所以類似這樣的寫法是不可以的:
// This JSX: <div id={if (condition) { 'msg' }}>Hello World!</div> // Is transformed to this JS: React.createElement("div", {id: if (condition) { 'msg' }}, "Hello World!");
可以從轉(zhuǎn)化后的Javascript代碼中看出明顯的語(yǔ)法錯(cuò)誤,所以要不用三目運(yùn)算符,要不就這樣寫:
if (condition) <div id='msg'>Hello World!</div> else <div>Hello World!</div>
傳播屬性(Spread Attributes)
在JSX中,可以使用...運(yùn)算符,表示將一個(gè)對(duì)象的鍵值對(duì)與ReactElement的props屬性合并,這個(gè)...運(yùn)算符的實(shí)現(xiàn)類似于ES6 Array中的...運(yùn)算符的特性。
var props = { foo: x, bar: y }; var component = <Component { ...props } />;
這樣就相當(dāng)于:
var component = <Component foo={x} bar={y} />
它也可以和普通的XML屬性混合使用,需要同名屬性,后者將覆蓋前者:
var props = { foo: 'default' }; var component = <Component {...props} foo={'override'} />; console.log(component.props.foo); // 'override'
相關(guān)文章
react項(xiàng)目如何使用iconfont的方法步驟
這篇文章主要介紹了react項(xiàng)目如何使用iconfont的方法步驟,這里介紹下如何在項(xiàng)目中配置。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-03-03解決React報(bào)錯(cuò)Style prop value must be a
這篇文章主要為大家介紹了React報(bào)錯(cuò)Style prop value must be an object解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12利用React-router+Webpack快速構(gòu)建react程序
目前 React、Webpack 等技術(shù)如火如荼,你是不是還在愁苦如何把這些雜亂的知識(shí)怎么學(xué)習(xí)一下,開(kāi)啟一段新的前端開(kāi)發(fā)之路呢?那么這篇將給大家運(yùn)用示例代碼詳細(xì)的介紹使用React-router和Webpack如何快速構(gòu)建一個(gè)react程序,感興趣的朋友們下面來(lái)一起看看吧。2016-10-10react?實(shí)現(xiàn)表格列表拖拽排序的示例
本文主要介紹了react?實(shí)現(xiàn)表格列表拖拽排序,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02從零搭建react+ts組件庫(kù)(封裝antd)的詳細(xì)過(guò)程
這篇文章主要介紹了從零搭建react+ts組件庫(kù)(封裝antd),實(shí)際上,代碼開(kāi)發(fā)過(guò)程中,還有很多可以輔助開(kāi)發(fā)的模塊、流程,本文所搭建的整個(gè)項(xiàng)目,我都按照文章一步一步進(jìn)行了git提交,開(kāi)發(fā)小伙伴可以邊閱讀文章邊對(duì)照git提交一步一步來(lái)看2022-05-05