React進(jìn)階筆記1(jsx深入理解)

深入jsx

從本質(zhì)上來說肩杈,jsx只是為React.creatElement(component,props)提供的語法糖杏愤。例如:

<Mybutton color="blue" shadowsize={2}>
    click me
</Mybutton>

編譯后得到(也就是React底層實(shí)現(xiàn)的過程):

React.createElement(
    Mybutton,//組件名
    {color:"blue",shadowsize:2},//相關(guān)屬性
    "click me" //文本內(nèi)容
)

如果節(jié)點(diǎn)中沒有子代。子節(jié)點(diǎn)推掸,還可以直接使用自閉和標(biāo)簽桶蝎。如:

<div className="sidebar" />

然后編譯為:

React.createElement(
    'div',
    {className:"sidebar"},
    null
)

如果你想徹底驗(yàn)證 JSX 是如何轉(zhuǎn)換為 JavaScript 的,你可以嘗試 在線 Babel 編譯器.

指定React元素類型

jsx的標(biāo)簽名決定了React的元素類型谅畅。

大寫開頭的jsx標(biāo)簽表示一個(gè)React組件登渣。這些標(biāo)簽會(huì)被編譯成同名的變量然后引用。如果你使用<Kolento />毡泻,就必須在作用域中生命Kolento變量胜茧。

React必須聲明

由于jsx在編譯后會(huì)調(diào)用React.createElement()方法,所以你的jsx中必須首先聲明React變量仇味,否則就找不到React了呻顽。

例如:下面的聲明都是必須的。
盡管React和CustomButton都沒有被直接調(diào)用丹墨。

import React from 'react';
import CustomButton from './CustomButton';
function WarningButton(){
// 返回 React.createElement(CustomButton, {color: 'blue'}, null);
    return <CustomButton color="blue" />
}

如果使用script加載React廊遍,他會(huì)作用于全局

點(diǎn)表示法

我們還可以使用React中的點(diǎn)表示法來引用React組件。你可以方便的從一個(gè)模塊中贩挣,導(dǎo)出許多React組件喉前,有一個(gè)叫Components.DatePicker的組件⊥醪疲可以直接在jsx中使用它卵迂。
調(diào)用的時(shí)候只要Components.DatePicker 即可

const MyComponents = {
    DatePicker:function Date(props){
        return <div>Imagine a {props.color} datepicker here</div>    
    }
}

function BlueDatePicker(){
    return <MyComponents.DatePicker color="blue" />
}

首字母大寫

當(dāng)元素的首字母以小寫開頭,則表示他是一個(gè)內(nèi)置的組件绒净,如div span见咒,并將字符串 ‘div’ 或 ‘span’ 傳 遞給 React.createElement。 以大寫字母開頭的類型挂疆,如 <Foo /> 編譯為 React.createElement(Foo)改览,并它正對(duì)應(yīng)于你在 JavaScript 文件中定義或?qū)氲慕M件。

我們建議用大寫開頭命名組件缤言。如果你的組件以小寫字母開頭宝当,請(qǐng)?jiān)?JSX 中使用之前其賦值給大寫開頭的變量。

錯(cuò)誤demo
import React from 'react';

// 錯(cuò)誤墨闲!組件名應(yīng)該首字母大寫:
function hello(props) {
  // 正確今妄!div 是有效的 HTML 標(biāo)簽:
  return <div>Hello {props.toWhat}</div>;
}

function HelloWorld() {
  // 錯(cuò)誤郑口!React 會(huì)將小寫開頭的標(biāo)簽名認(rèn)為是 HTML 原生標(biāo)簽:
  return <hello toWhat="World" />;
}

為了解決這個(gè)問題鸳碧,我們將 hello 重命名為 Hello盾鳞,然后使用 <Hello /> 引用:

import React from 'react';

// 正確!組件名應(yīng)該首字母大寫:
function Hello(props) {
  // 正確瞻离!div 是有效的 HTML 標(biāo)簽:
  return <div>Hello {props.toWhat}</div>;
}

function HelloWorld() {
  // 正確腾仅!React 能夠?qū)⒋髮戦_頭的標(biāo)簽名認(rèn)為是 React 組件。
  return <Hello toWhat="World" />;
}

在運(yùn)行時(shí)選擇類型

我們不能使用表達(dá)式來作為React的標(biāo)簽套利,如果想用表達(dá)式的方式確定React的元素類型推励,要將表達(dá)式賦值給一個(gè)大寫開頭的標(biāo)量,這種情況一般會(huì)在條件渲染的時(shí)候出現(xiàn)肉迫。

import React from 'react';
import { PhotoStory, VideoStory } from './stories';

const components = {
  photo: PhotoStory,
  video: VideoStory
};

function Story(props) {
  // 錯(cuò)誤验辞!JSX 標(biāo)簽名不能為一個(gè)表達(dá)式。
  return <components[props.storyType] story={props.story} />;
}

以上demo 使用表達(dá)式去輸出一個(gè)標(biāo)簽喊衫,這是不可行的跌造,需要將components[props.storyType]賦值給一個(gè)大寫開頭的變量替換進(jìn)去才行。

解決:要解決這個(gè)問題族购,我們需要先將類型賦值給大寫開頭的變量壳贪。

import React from 'react';
import { PhotoStory, VideoStory } from './stories';

const components = {
  photo: PhotoStory,
  video: VideoStory
};

function Story(props) {
  // 正確!JSX 標(biāo)簽名可以為大寫開頭的變量寝杖。
  const SpecificStory = components[props.storyType];
  return <SpecificStory story={props.story} />;
}

屬性

在jsx中有幾種不同的方式來指定屬性

使用js表達(dá)式

可以傳遞任何{}包裹的javascript表達(dá)式作為一個(gè)屬性值违施。

<MyComponent foo={1 + 2 + 3 + 4} />

對(duì)于MyComponent來說,props.foo的值為10瑟幕,是通過表達(dá)式1+2+3+4計(jì)算出來的磕蒲。

if語句和for循環(huán)在js中不是表達(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>;
}

你可以在相關(guān)部分中了解有關(guān) 條件渲染循環(huán) 的更多信息。

字符串常量

可以將字符串常量作為屬性傳遞鹿霸,以下的2個(gè)jsx是等價(jià)的排吴。

<MyComponents message={"hello"} />
<MyComponents message="hello" />

當(dāng)傳遞一個(gè)字符串常量時(shí),該值會(huì)被解析為HTML非轉(zhuǎn)義字符串懦鼠,所以下面兩個(gè) JSX 表達(dá)式是相同的:

<MyComponent message="&lt;3" />
<MyComponent message={'<3'} />

以上的這點(diǎn)钻哩,了解一下即可。

屬性默認(rèn)為true

如果你沒有給屬性傳值肛冶,則他默認(rèn)為true街氢,因此一下2個(gè)jsx表達(dá)式是等價(jià)的。

<MyTextBox autocomplete />
<MyTextBox autocomplete={true} />

一般情況下睦袖,我們不建議這樣使用珊肃,因?yàn)樗鼤?huì)與 ES6 對(duì)象簡(jiǎn)潔表示法 混淆。比如 {foo}{foo: foo} 的簡(jiǎn)寫,而不是 {foo: true}伦乔。這里能這樣用厉亏,是因?yàn)樗?HTML 的做法。

擴(kuò)展屬性

如果你已經(jīng)有了props對(duì)象烈和,并且想在jsx中傳遞他爱只,可以使用...作為擴(kuò)展操作符來傳遞整個(gè)對(duì)象。以下的2個(gè)組件是等價(jià)的招刹。

function App1() {
  return <Greeting firstName="Ben" lastName="Hector" />;
}

function App2(){
  const props = {firstName:"Ben",lastName="Hector"}
  return <Greeting {...props}>
}

當(dāng)你構(gòu)建通用容器時(shí)恬试,擴(kuò)展屬性會(huì)非常有用。然而疯暑,這樣做也可能讓很多不相關(guān)的屬性训柴,傳遞到不需要它們的組件中使代碼變得混亂。我們建議你謹(jǐn)慎使用此語法妇拯。

子代

在包含開始與結(jié)束標(biāo)簽之間的jsx表達(dá)式中畦粮,標(biāo)記之間的內(nèi)容可以作為特殊的參數(shù)傳遞props.children,有幾種不同的方法來傳遞子代乖阵。
也就是說props.children指代標(biāo)簽中的內(nèi)容宣赔。

字符串常量

你可以在開始和結(jié)束標(biāo)簽之間放入一個(gè)字符串,則 props.children就是那個(gè)字符串瞪浸。這對(duì)于許多內(nèi)置 HTML 元素很有用儒将。例如:

<MyComponent>hello world</MyComponent>

這是有效的 JSX,并且 MyComponent 的 props.children 值將會(huì)直接是 "hello world!"对蒲。因?yàn)?HTML 未轉(zhuǎn)義钩蚊,所以你可以像寫 HTML 一樣寫 JSX:

<div>This is valid HTML &amp; JSX at the same time.</div>

JSX 會(huì)移除空行和開始與結(jié)尾處的空格。標(biāo)簽鄰近的新行也會(huì)被移除蹈矮,字符串常量?jī)?nèi)部的換行會(huì)被壓縮成一個(gè)空格砰逻,所以下面這些都等價(jià):

<div>Hello World</div>

<div>
  Hello World
</div>

<div>
  Hello
  World
</div>

<div>

  Hello World
</div>

jsx

可以通過子代鑲嵌嵌套更多的jsx元素,這對(duì)于鑲嵌組件非常有用泛鸟。

<MyContainer>
  <MyFirstComponent />
  <MySecondComponent />
</MyContainer>

其中可以混合不同類型的子元素蝠咆,同時(shí)用字符串常量和jsx子元素,這是jsx類似html的另一種形式北滥,這在jsx和html中都是有效的刚操。

<div>
  Here is a list:
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
  </ul>
</div>

React組件也可以通過數(shù)組的形式返回多個(gè)元素

render() {
  // 不需要使用額外的元素包裹數(shù)組中的元素
  return [
    // 不要忘記 key :)
    <li key="A">First item</li>,
    <li key="B">Second item</li>,
    <li key="C">Third item</li>,
  ];
}

js表達(dá)式

可以將任何{}包裹的js表達(dá)式作為子代傳遞,比如再芋,以下的表達(dá)式是等價(jià)的菊霜。

<MyComponent>foo</MyComponent>
<MyComponent>{'foo'}</MyComponent>

這對(duì)于渲染任意長(zhǎng)度的jsx表達(dá)式都很有用。下面將會(huì)渲染一個(gè)HTML列表济赎。

function Item(props){
    return <li>{props.message}</li>
}

function TodoList(){
    const todos=[
        'first','second','third'
    ]
    return(
        <ul>
            {todos.map(message=><Item key={message} message={message} />)}
        </ul>
    )
}

ReactDOM.render(
    <TodoList />,document.getElementById('root')
)

js表達(dá)式可以與其他類型的子代混合使用鉴逞。這通常對(duì)于字符串模板非常有用记某。

function Hello(props) {
  return <div>Hello {props.addressee}!</div>;
}

函數(shù)

在通常情況下,插入jsx中的js表達(dá)式被認(rèn)為是字符串构捡、React元素或者這些內(nèi)容的列表辙纬。然而props.children可以向其他屬性一樣傳遞任何的數(shù)據(jù),而不僅僅是React元素叭喜。

如果你調(diào)用自定義組件,就可以使用props.children來獲取進(jìn)行傳遞蓖谢。

// 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>
  );
}

遞給自定義組件的子代可以是任何元素捂蕴,只要該組件在 React 渲染前將其轉(zhuǎn)換成 React 能夠理解的東西。這個(gè)用法并不常見闪幽,但當(dāng)你想擴(kuò)展 JSX 時(shí)可以使用啥辨。

布爾值、Null 和 Undefined 被忽略

false盯腌、null溉知、undefined 和 true 都是有效的子代,但它們不會(huì)直接被渲染腕够。下面的表達(dá)式是等價(jià)的:

<div />

<div></div>

<div>{false}</div>

<div>{null}</div>

<div>{undefined}</div>

<div>{true}</div>

這在根據(jù)條件來確定是否渲染React元素時(shí)非常有用级乍。以下的JSX只會(huì)在showHeader為true時(shí)渲染<Header />組件。

<div>
  {showHeader && <Header />}
  <Content />
</div>

相反帚湘,如果你想讓類似 false玫荣、truenullundefined 出現(xiàn)在輸出中大诸,你必須先把它轉(zhuǎn)換成字符串 :

<div>
  My JavaScript variable is {String(myVariable)}.
</div>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末捅厂,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子资柔,更是在濱河造成了極大的恐慌焙贷,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,865評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贿堰,死亡現(xiàn)場(chǎng)離奇詭異辙芍,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)羹与,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門沸手,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人注簿,你說我怎么就攤上這事契吉。” “怎么了诡渴?”我有些...
    開封第一講書人閱讀 169,631評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵捐晶,是天一觀的道長(zhǎng)菲语。 經(jīng)常有香客問我,道長(zhǎng)惑灵,這世上最難降的妖魔是什么山上? 我笑而不...
    開封第一講書人閱讀 60,199評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮英支,結(jié)果婚禮上佩憾,老公的妹妹穿的比我還像新娘。我一直安慰自己干花,他們只是感情好妄帘,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著池凄,像睡著了一般抡驼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肿仑,一...
    開封第一講書人閱讀 52,793評(píng)論 1 314
  • 那天致盟,我揣著相機(jī)與錄音,去河邊找鬼尤慰。 笑死馏锡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的伟端。 我是一名探鬼主播眷篇,決...
    沈念sama閱讀 41,221評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼荔泳!你這毒婦竟也來了蕉饼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,174評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤玛歌,失蹤者是張志新(化名)和其女友劉穎昧港,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體支子,經(jīng)...
    沈念sama閱讀 46,699評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡创肥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了值朋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片叹侄。...
    茶點(diǎn)故事閱讀 40,918評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖昨登,靈堂內(nèi)的尸體忽然破棺而出趾代,到底是詐尸還是另有隱情,我是刑警寧澤丰辣,帶...
    沈念sama閱讀 36,573評(píng)論 5 351
  • 正文 年R本政府宣布撒强,位于F島的核電站禽捆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏飘哨。R本人自食惡果不足惜胚想,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芽隆。 院中可真熱鬧浊服,春花似錦、人聲如沸胚吁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽囤采。三九已至,卻和暖如春惩淳,著一層夾襖步出監(jiān)牢的瞬間蕉毯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評(píng)論 1 274
  • 我被黑心中介騙來泰國打工思犁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留代虾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,364評(píng)論 3 379
  • 正文 我出身青樓激蹲,卻偏偏與公主長(zhǎng)得像棉磨,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子学辱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 深入JSX date:20170412筆記原文其實(shí)JSX是React.createElement(componen...
    gaoer1938閱讀 8,076評(píng)論 2 35
  • 以下內(nèi)容是我在學(xué)習(xí)和研究React時(shí)乘瓤,對(duì)React的特性、重點(diǎn)和注意事項(xiàng)的提取策泣、精練和總結(jié)衙傀,可以做為React特性...
    科研者閱讀 8,244評(píng)論 2 21
  • 3. JSX JSX是對(duì)JavaScript語言的一個(gè)擴(kuò)展語法, 用于生產(chǎn)React“元素”萨咕,建議在描述UI的時(shí)候...
    pixels閱讀 2,841評(píng)論 0 24
  • React版本:15.4.2**翻譯:xiyoki ** 從根本上說统抬,JSX只是為React.createElem...
    前端xiyoki閱讀 3,038評(píng)論 0 0
  • 最近看了一本關(guān)于學(xué)習(xí)方法論的書,強(qiáng)調(diào)了記筆記和堅(jiān)持的重要性危队。這幾天也剛好在學(xué)習(xí)React聪建,所以我打算每天堅(jiān)持一篇R...
    gaoer1938閱讀 1,692評(píng)論 0 5