從根本上來說,JSX語法提供了一種創建React元素的語法糖,JSX語句可以編譯成:
React.createElement(component, props, …children)的形式,比如:
<MyButton color="blue" shadowSize={2}> Click Me </MyButton>
編譯結果:
React.createElement( MyButton, {color: 'blue', shadowSize: 2}, 'Click Me' )
當然,你也可以使用自閉和的形式:
<div className="sidebar" />
可以得到相同的編譯結果。
1.指定React元素的類型
JSX標簽的頭部,決定了React元素的類型,大寫的標簽,意味着JSX的標簽與React的組件一一對應,比如
<Foo/>標簽就對應了Foo組件
(1)必須包裹在一定的范圍內
import React from 'react'; import CustomButton from './CustomButton'; function WarningButton() { // return React.createElement(CustomButton, {color: 'red'}, null); return <CustomButton color="red" />; }
比如這樣,引入了2個組件,構成了一個新的組件WarningButton,組件的返回值的元素,必須包含在一定范圍內,這里通過函數的’{ ‘, ’ } ‘實現包裹的效果。
(2)用戶定義的組件必須大寫
我們前面已經說過,JSX的標簽與組件是一一對應的,當我們使用JSX語法,引用組件的時候,標簽必須要大寫(同時定義組件的函數名也必須是大寫的)。
function Hello(){ return <h2>Hello,World</h2> } //定義過程 <Hello/> //使用過程
(3)不能在運行期間,動態的選擇類型
我們不能在JSX中,動態的規定組件的類型,舉例來說:
import React from 'react'; import { PhotoStory, VideoStory } from './stories'; const components = { photo: PhotoStory, video: VideoStory }; function Story(props) { return <components[props.storyType] story={props.story} />; //這樣寫是不對的,我們在返回的組件中,動態定義了組件,這種動態的定義是無效的 }
應該改寫為:
import React from 'react'; import { PhotoStory, VideoStory } from './stories'; const components = { photo: PhotoStory, video: VideoStory }; function Story(props) { const SpecificStory = components[props.storyType]; return < SpecificStory story={props.story} />; //這樣就是正確的,我們不要在JSX的標簽中使用動態定義 }
2.JSX中的Props屬性
(1)JS表達式
可以通過{},包裹js的語法來使用。比如:
<MyComponent foo={1 + 2 + 3 + 4} />
等價於:
<MyComponent foo={10} />
如果不是js表達式,則不能包裹在{}中使用。
(2)Props屬性的默認值
Props上的屬性可以有默認值,並且默認值為true,比如:
<MyTextBox autocomplete /> <MyTextBox autocomplete={true} />
上面這兩個式子是等價的,但是不推薦使用默認值,因為在ES6的語法中{foo}代表的意思是:{foo:foo}的意思,並不是{foo:true}。
(3)擴展屬性
可以通過ES6的…方法,給組件賦屬性值,例如:
function App1() { return <Greeting firstName="Ben" lastName="Hector" />; } function App2() { const props = {firstName: 'Ben', lastName: 'Hector'}; return <Greeting {...props} />; }
上面的這兩種方式是等價的。
3.JSX中的children
(1)children中的function
我們來考慮自定義組件中包含函數的情況:
function ListOfTenThings() { return ( <Repeat numTimes={10}> {(index) => <div key={index}>This is item {index} in the list</div>} </Repeat> ); }
那么何時調用這個children中的方法呢?
function Repeat(props) { let items = []; for (let i = 0; i < props.numTimes; i++) { items.push(props.children(i)); } return <div>{items}</div>; }
我們從上述的Repeat組件的定義中可以看出來,children中的方法按此定義會一直執行10次。
(2)忽略Boolean,Null以及Undefined
false,null,undefined以及true是不能通過render()方法,呈現在頁面上的,下面的這些div塊的樣式
相同,都是空白塊:
<div /> <div></div> <div>{false}</div> <div>{null}</div> <div>{true}</div>
這種屬性,在通過render呈現元素的時候,是十分有用的,比如我們只想在div元素中展現Head組件,
例子如下:
<div> {showHeader && <Header />} <Content /> </div>
這里的邏輯是,只有showHeader==true,在會在頁面呈現Header組件,否則為null,即為不顯示任何東西,這相當於一個if的判斷了。
再舉一個例子:
<div> {props.messages.length && <MessageList messages={props.messages} /> } </div>
在這個div中,我們需要知道的是即使元素為0,0是能夠呈現在頁面中的。也就是說上述代碼中,只要
props.messages數組存在,不管長度是否為0都是存在的。(這里不同於js,js中的語法認為0==false)
(3)如何顯示Null,Undefined和Boolean
如果我們一定要再頁面上顯示Null等,可以將其先轉化為字符串之后再顯示。
<div> My JavaScript variable is {String(myVariable)}. </div>
通過String的轉化后就能在頁面上顯示了。