?
This document uses PHP Chinese website manual Release
基本上,JSX只是為React.createElement(component, props, ...children)
函數(shù)提供語(yǔ)法糖。JSX代碼:
<MyButton color="blue" shadowSize={2}> Click Me</MyButton>
編譯成:
React.createElement( MyButton, {color: 'blue', shadowSize: 2}, 'Click Me')
如果沒(méi)有子,您也可以使用標(biāo)簽的自閉形式。所以:
<div className="sidebar" />
編譯成:
React.createElement( 'div', {className: 'sidebar'}, null)
如果你想測(cè)試一些特定的JSX如何轉(zhuǎn)換成JavaScript,你可以嘗試在線的Babel編譯器。
JSX標(biāo)簽的第一部分決定了React元素的類型。
大寫(xiě)字母表示JSX標(biāo)記引用了React組件。這些標(biāo)記會(huì)被編譯為對(duì)指定變量的直接引用,因此如果使用JSX <Foo />
表達(dá)式,則Foo
必須在范圍內(nèi)。
由于JSX編譯為調(diào)用React.createElement
,React
庫(kù)必須始終處于JSX代碼的范圍內(nèi)。
例如,這個(gè)代碼中的兩個(gè)導(dǎo)入都是必需的,盡管React
并CustomButton
沒(méi)有直接引用JavaScript:
import React from 'react';import CustomButton from './CustomButton'; function WarningButton() { // return React.createElement(CustomButton, {color: 'red'}, null); return <CustomButton color="red" />;}
如果您不使用JavaScript捆綁程序并從<script>
代碼加載React ,則它已經(jīng)在React
全局范圍內(nèi)。
您也可以在JSX中使用點(diǎn)符號(hào)來(lái)引用React組件。如果您有一個(gè)導(dǎo)出許多React組件的單個(gè)模塊,這很方便。例如,如果MyComponents.DatePicker
是組件,則可以直接從JSX使用它:
import React from 'react';const MyComponents = { DatePicker: function DatePicker(props) { return <div>Imagine a {props.color} datepicker here.</div>; }} function BlueDatePicker() { return <MyComponents.DatePicker color="blue" />;}
當(dāng)元素類型以小寫(xiě)字母開(kāi)頭時(shí),它指的是像<div>
or 這樣的內(nèi)置組件,<span>
并生成一個(gè)字符串'div'
或'span'
傳遞給它React.createElement
。以大寫(xiě)字母開(kāi)頭的類型,例如<Foo />
編譯React.createElement(Foo)
并對(duì)應(yīng)于JavaScript文件中定義或?qū)氲慕M件。
我們建議用大寫(xiě)字母命名組件。如果您確實(shí)有一個(gè)以小寫(xiě)字母開(kāi)頭的組件,請(qǐng)?jiān)趯⑺糜贘SX之前將其分配給大寫(xiě)變量。
例如,這段代碼不會(huì)按預(yù)期運(yùn)行:
import React from 'react'; // Wrong! This is a component and should have been capitalized: function hello(props) { // Correct! This use of <div> is legitimate because div is a valid HTML tag: return <div>Hello {props.toWhat}</div>;} function HelloWorld() { // Wrong! React thinks <hello /> is an HTML tag because it's not capitalized: return <hello toWhat="World" />;}
為了解決這個(gè)問(wèn)題,我們將重新命名hello
,以Hello
和使用<Hello />
提到它的時(shí)候:
import React from 'react';// Correct! This is a component and should be capitalized: function Hello(props) { // Correct! This use of <div> is legitimate because div is a valid HTML tag: return <div>Hello {props.toWhat}</div>;} function HelloWorld() { // Correct! React knows <Hello /> is a component because it's capitalized. return <Hello toWhat="World" />;}
您不能使用通用表達(dá)式作為React元素類型。如果您確實(shí)想使用通用表達(dá)式來(lái)指示元素的類型,請(qǐng)將其首先分配給大寫(xiě)變量。當(dāng)你想渲染一個(gè)基于道具的不同組件時(shí),通常會(huì)出現(xiàn)這種情況:
import React from 'react';import { PhotoStory, VideoStory } from './stories';const components = { photo: PhotoStory, video: VideoStory};function Story(props) { // Wrong! JSX type can't be an expression. return <components[props.storyType] story={props.story} />;}
為了解決這個(gè)問(wèn)題,我們首先將類型賦值給一個(gè)大寫(xiě)的變量:
import React from 'react';import { PhotoStory, VideoStory } from './stories';const components = { photo: PhotoStory, video: VideoStory};function Story(props) { // Correct! JSX type can be a capitalized variable. const SpecificStory = components[props.storyType]; return <SpecificStory story={props.story} />; }
有幾種不同的方式可以在JSX中指定道具。
您可以將任何JavaScript表達(dá)式作為道具傳遞,通過(guò)將其包圍{}
。例如,在這個(gè)JSX中:
<MyComponent foo={1 + 2 + 3 + 4} />
因?yàn)?code>MyComponent,值的props.foo
將是10
因?yàn)楸磉_(dá)式1 + 2 + 3 + 4
被評(píng)估。
if
語(yǔ)句和for
循環(huán)在JavaScript中不是表達(dá)式,所以它們不能直接在JSX中使用。相反,你可以把它們放在周圍的代碼中。例如:
function NumberDescriber(props) { let description; if (props.number % 2 == 0) { description = <strong>even</strong>; } else { description = <i>odd</i>; } return <div>{props.number} is an {description} number</div>;}
您可以在相應(yīng)章節(jié)中了解有關(guān)條件渲染和循環(huán)的更多信息。
你可以傳遞一個(gè)字符串作為道具。這兩個(gè)JSX表達(dá)式是等價(jià)的:
<MyComponent message="hello world" /><MyComponent message={'hello world'} />
當(dāng)你傳遞一個(gè)字符串時(shí),它的值是HTML-unescaped。所以這兩個(gè)JSX表達(dá)式是等價(jià)的:
<MyComponent message="<3" /><MyComponent message={'<3'} />
這種行為通常不相關(guān)。這里只提到完整性。
如果您沒(méi)有為道具傳遞值,則默認(rèn)為true
。這兩個(gè)JSX表達(dá)式是等價(jià)的:
<MyTextBox autocomplete /><MyTextBox autocomplete={true} />
一般來(lái)說(shuō),我們不建議使用它,因?yàn)樗赡芘cES6對(duì)象速記 相混淆,而速記{foo}
是簡(jiǎn)短的,{foo: foo}
而不是{foo: true}
。這種行為就在那里,以便它符合HTML的行為。
如果你已經(jīng)有了props
一個(gè)對(duì)象,并且你想通過(guò)JSX傳遞它,你可以使用...
“spread”運(yùn)算符來(lái)傳遞整個(gè)道具對(duì)象。這兩個(gè)組件是等價(jià)的:
function App1() { return <Greeting firstName="Ben" lastName="Hector" />;} function App2() { const props = {firstName: 'Ben', lastName: 'Hector'}; return <Greeting {...props} />;}
你也可以選擇你的組件將使用的特定道具,同時(shí)使用傳播運(yùn)算符傳遞所有其他道具。
const Button = props => { const { kind, ...other } = props; const className = kind === "primary" ? "PrimaryButton" : "SecondaryButton"; return <button className={className} {...other} />;}; const App = () => { return ( <div> <Button kind="primary" onClick={() => console.log("clicked!")}> Hello World! </Button> </div> );};
在上面的例子中,kind
道具被安全地消費(fèi),并且不會(huì)傳遞給<button>
DOM中的元素。所有其他道具都通過(guò)...other
對(duì)象傳遞,使得這個(gè)組件非常靈活。你可以看到,它傳遞一個(gè)onClick
和children
道具。
擴(kuò)展屬性可能很有用,但它們還可以輕松地將不必要的道具傳遞給不關(guān)心它們的組件或?qū)o(wú)效的HTML屬性傳遞給DOM。我們建議謹(jǐn)慎使用這種語(yǔ)法。
在同時(shí)包含開(kāi)始標(biāo)記和結(jié)束標(biāo)記的JSX表達(dá)式中,這些標(biāo)記之間的內(nèi)容作為特殊的道具傳遞:props.children
。有幾種不同的方式來(lái)傳遞孩子:
您可以在開(kāi)始標(biāo)簽和結(jié)束標(biāo)簽之間放置一個(gè)字符串,并且props.children
只是該字符串。這對(duì)于許多內(nèi)置的HTML元素很有用。例如:
<MyComponent>Hello world!</MyComponent>
這是有效的JSX,并props.children
在MyComponent
將簡(jiǎn)單地字符串"Hello world!"
。HTML是非轉(zhuǎn)義的,所以通常可以編寫(xiě)JSX,就像您以這種方式編寫(xiě)HTML一樣:
<div>This is valid HTML & JSX at the same time.</div>
JSX在行的開(kāi)頭和結(jié)尾刪除空格。它也刪除空行。與標(biāo)簽相鄰的新行被刪除; 發(fā)生在字符串文字中間的新行會(huì)壓縮為一個(gè)空格。所以這些都呈現(xiàn)相同的事物:
<div>Hello World</div><div> Hello World</div><div> Hello World</div><div> Hello World</div>
您可以提供更多的JSX元素作為孩子。這對(duì)于顯示嵌套組件很有用:
<MyContainer> <MyFirstComponent /> <MySecondComponent /></MyContainer>
您可以將不同類型的子項(xiàng)混合在一起,以便您可以將字符串文字與JSX子項(xiàng)一起使用。這是JSX與HTML相似的另一種方式,因此這是有效的JSX和有效的HTML:
<div> Here is a list: <ul> <li>Item 1</li> <li>Item 2</li> </ul></div>
React組件也可以返回一組元素:
render() { // No need to wrap list items in an extra element! return [ // Don't forget the keys :) <li key="A">First item</li>, <li key="B">Second item</li>, <li key="C">Third item</li>, ];}
您可以將任何JavaScript表達(dá)式作為子項(xiàng)傳遞,方法是將其放入其中{}
。例如,這些表達(dá)式是等價(jià)的:
<MyComponent>foo</MyComponent><MyComponent>{'foo'}</MyComponent>
這通常用于呈現(xiàn)任意長(zhǎng)度的JSX表達(dá)式列表。例如,這呈現(xiàn)一個(gè)HTML列表:
function Item(props) { return <li>{props.message}</li>;} function TodoList() { const todos = ['finish doc', 'submit pr', 'nag dan to review']; return ( <ul> {todos.map((message) => <Item key={message} message={message} />)} </ul> );}
JavaScript表達(dá)式可以與其他類型的孩子混合使用。這通常用于替代字符串模板:
function Hello(props) { return <div>Hello {props.addressee}!</div>;}
通常,插入到JSX中的JavaScript表達(dá)式將評(píng)估為一個(gè)字符串,一個(gè)React元素或這些東西的列表。然而,props.children
就像任何其他道具一樣,它可以傳遞任何類型的數(shù)據(jù),而不僅僅是React知道如何渲染的種類。例如,如果你有一個(gè)自定義組件,你可以讓它回調(diào)為props.children
:
// Calls the children callback numTimes to produce a repeated component function Repeat(props) { let items = []; for (let i = 0; i < props.numTimes; i++) { items.push(props.children(i)); } return <div>{items}</div>;}function ListOfTenThings() { return ( <Repeat numTimes={10}> {(index) => <div key={index}>This is item {index} in the list</div>} </Repeat> ); }
傳遞給自定義組件的子項(xiàng)可以是任何東西,只要該組件將它們轉(zhuǎn)換為React在呈現(xiàn)之前可以理解的內(nèi)容即可。這種用法并不常見(jiàn),但如果您想要擴(kuò)展JSX的功能,它就可以工作。
false
,null
,undefined
,和true
有效的兒童。他們根本不渲染。這些JSX表達(dá)式都將呈現(xiàn)相同的事物:
<div /><div></div><div>{false}</div><div>{null}</div><div>{undefined}</div><div>{true}</div>
這有助于有條件地呈現(xiàn)React元素。這JSX只呈現(xiàn)一個(gè)<Header />
,如果showHeader
是true
:
<div> {showHeader && <Header />} <Content /></div>
有一點(diǎn)需要注意的是,一些“虛假”的價(jià)值觀,如0
數(shù)字,仍然由React渲染。例如,這段代碼不會(huì)像你所期望的那樣工作,因?yàn)?code>0當(dāng)它props.messages
是一個(gè)空數(shù)組的時(shí)候會(huì)被打印出來(lái):
<div> {props.messages.length && <MessageList messages={props.messages} /> }</div>
要解決這個(gè)問(wèn)題,請(qǐng)確保前面的表達(dá)式&&
始終是布爾值:
<div> {props.messages.length > 0 && <MessageList messages={props.messages} /> }</div>
相反,如果你想有一個(gè)類似的值false
,true
,null
,或undefined
出現(xiàn)在輸出中,你必須把它轉(zhuǎn)換為字符串第一:
<div> My JavaScript variable is {String(myVariable)}.</div>