最初使用React時(shí),沒(méi)有太注意細(xì)節(jié),只是會(huì)使用,實(shí)現(xiàn)功能,當(dāng)使用一段時(shí)間再回過(guò)頭來(lái)看官方文檔時(shí)發(fā)現(xiàn)有些東西原來(lái)是這樣的,下面就把再次看文檔時(shí)覺(jué)得柳暗花明的地方總結(jié)一下,也算是對(duì)React基礎(chǔ)學(xué)習(xí)告一段落,開啟下一篇章。
key應(yīng)該是穩(wěn)定的,且唯一的,盡量不要用索引作為key
都知道React組件渲染列表時(shí)需要為每個(gè)列表元素分配一個(gè)在列表中獨(dú)一無(wú)二的key,key可以在DOM中的某些元素被增加或刪除視乎幫助React識(shí)別哪些發(fā)生了變化,通常列表數(shù)據(jù)都會(huì)有id字段,習(xí)慣用id值作為key,當(dāng)沒(méi)有id或其他唯一標(biāo)識(shí)時(shí),也會(huì)用序列號(hào)索引index作為key,之前并沒(méi)有覺(jué)得用index有什么不好之處,再次看文檔發(fā)現(xiàn)序列號(hào)索引作為key有一些弊端。
如果列表可以重新排序,不建議使用索引作為key,因?yàn)闀?huì)導(dǎo)致渲染變得很慢,如果不重排,沒(méi)問(wèn)題。
為什么變得很慢?
React通過(guò)對(duì)比算法來(lái)更新組件,使用key來(lái)匹配原本樹的子節(jié)點(diǎn)和新樹的子節(jié)點(diǎn),比如以下列表,在開始插入元素:
<ul>
<li key='6'>6</li>
<li key='7'>7</li>
</ul>
<ul>
<li key='5'>5</li>
<li key='6'>6</li>
<li key='7'>7</li>
</ul>
沒(méi)有使用index作為key,React知道key為'5'的元素是新的,僅移動(dòng)key為'6'、'7'的元素就可以了。
如果使用index作為key,上述列表的變化會(huì)導(dǎo)致key值的變化,列表元素不能復(fù)用,造成不必要的重建,也可能會(huì)以意想不到的方式更新,所以會(huì)變慢。
注意:不要使用不穩(wěn)定的key(類似Math.random()生成的)
React中布爾值、Null和Undefined被忽略,數(shù)字0不會(huì)被忽略
React使用條件渲染時(shí),通常用JavaScript的邏輯與&&,當(dāng)showHeader為true時(shí)渲染<Header />,如下:
<div>
{showHeader && <Header />}
</div>
但數(shù)字0不會(huì)像預(yù)期的哪樣運(yùn)行,如下:
<div>
{props.messages.length &&
<MessageList messages={props.messages} />
}
</div>
props.messages為空數(shù)組時(shí),仍然會(huì)渲染<MessageList />,要解決這個(gè)問(wèn)題,確保 && 前面的表達(dá)式始終為布爾值:
<div>
{props.messages.length > 0 &&
<MessageList messages={props.messages} />
}
</div>
使用PropTypes進(jìn)行類型檢查是很必要的
最開始寫React的時(shí)候從來(lái)都不加PropTypes,覺(jué)得沒(méi)什么必要,現(xiàn)在發(fā)現(xiàn)PropTypes進(jìn)行類型檢查是很必要的,如果父組件傳給子組件的參數(shù)不符合PropTypes配置,控制臺(tái)就會(huì)報(bào)錯(cuò),給出錯(cuò)誤信息,這樣可以快速定位問(wèn)題。
另外通過(guò)defaultProps為props定義默認(rèn)值時(shí),類型檢查也會(huì)應(yīng)用在 defaultProps 上面,因?yàn)轭愋蜋z查發(fā)生在 defaultProps 賦值之后。
使用說(shuō)明請(qǐng)查看官方文檔:https://doc.react-china.org/docs/typechecking-with-proptypes.html
React中獲取真實(shí)DOM節(jié)點(diǎn)或 React 元素時(shí)使用Refs
獲取在 render 方法中創(chuàng)建的 DOM 節(jié)點(diǎn)或 React 元素時(shí),最好使用“回調(diào) ref”的方式,不要用DOM操作也不要用舊版 API:String 類型的 Refs
render() {
return (
//回調(diào)ref
<input ref={input => this.inputRef = input}/>
//string類型的ref
<input ref=“inputRef”/>
);
}
不要在函數(shù)式組件中使用ref屬性來(lái)進(jìn)行回調(diào)函數(shù)的綁定,因?yàn)楹瘮?shù)式組件是沒(méi)有實(shí)例的,準(zhǔn)確的說(shuō)函數(shù)式組件不是一個(gè)真正的類
React.Fragment組件的使用
在React中組件返回多個(gè)元素時(shí)要被一個(gè)元素包裹,不然會(huì)報(bào)錯(cuò),我們通常用div元素,這個(gè)div元素沒(méi)有什么實(shí)際的意義,并且會(huì)在DOM中增加額外節(jié)點(diǎn),建議用React.Fragment組件,不會(huì)增加額外的節(jié)點(diǎn),目前key 是唯一可以傳遞給 Fragment 的屬性。
render() {
return (
<React.Fragment>
<h1>React 文檔</h1>
<div>React內(nèi)容</div>
</React.Fragment>
);
}