jsx語法
1.元素的類名用className
2.渲染富文本內(nèi)容厌衔,會(huì)默認(rèn)被轉(zhuǎn)義而把標(biāo)簽展示出來底循,所以要用另外一種方法寨昙,用dangerouslySetInnerHTML={{__html:detail}}來展示装获。第一個(gè)花括號(hào)表示里面是一個(gè)js表達(dá)式篙梢,第二個(gè)花括號(hào)表示這個(gè)js表達(dá)式就是一個(gè)對(duì)象吼砂。
3.如果需要再元素上用for屬性逆航,就不能寫for,要寫htmlFor渔肩,比如<label htmlFor=""></label>
4.注釋 多行注釋 {/注釋內(nèi)容/} 單行注釋 //注釋內(nèi)容
組件間的傳值
1.父組件是通過屬性的形式向子組件傳數(shù)據(jù)的因俐,子組件通過this.props接收數(shù)據(jù)
2.在子組件中不允許直接修改父組件的內(nèi)容,要在子組件中調(diào)用父組件的方法來修改父組件的內(nèi)容周偎。父組件通過屬性的方式向子組件傳遞一個(gè)方法抹剩,子組件通過this.props調(diào)用這個(gè)方法。
代碼優(yōu)化
1.在constructor里為方法進(jìn)行函數(shù)作用域的綁定栏饮,這樣可以綁定函數(shù)作用域的綁定只會(huì)執(zhí)行一次吧兔,節(jié)約性能。
constructor(props){
super(props);
this.state = {
inputValue:'',
listData:[],
}
this.handleInputChange = this.handleInputChange.bind(this)
this.handleBtnClick = this.handleBtnClick.bind(this)
this.handleDelete = this.handleDelete.bind(this)
}
2.在使用this.props里的屬性的時(shí)候袍嬉,先進(jìn)行解構(gòu)賦值獲取屬性境蔼。
3.引入樣式的代碼,放在最引入組件的最后伺通。
4.render方法里融合的邏輯比如map遍歷箍土,會(huì)讓代碼很長,可以通過提煉一個(gè)方法來返回這段代碼罐监,會(huì)讓這段代碼體積變小吴藻,顯得比較精簡。
5.react新版已經(jīng)不推薦使用setState傳遞一個(gè)對(duì)象來進(jìn)行數(shù)據(jù)變更了弓柱,而是傳遞一個(gè)函數(shù)來變更沟堡,這個(gè)函數(shù)最終返回一個(gè)需要更新的數(shù)據(jù)對(duì)象。
this.setState(()=>{
return {
}
})
//es6簡寫
this.setState(()=>({
}))
6.用index做key值矢空,是一種不靠譜不負(fù)責(zé)任的行為航罗,有可能會(huì)造成代碼的錯(cuò)誤。
7.單向數(shù)據(jù)流:父組件可以向子組件傳值屁药,但是子組件一定不能直接修改這個(gè)值粥血,否則會(huì)報(bào)錯(cuò)。
React思考
1.React是聲明式開發(fā),使得我們可以減少大量DOM操作的代碼量复亏;
2.可以與其他框架并存趾娃;
3.組件化;
4.單向數(shù)據(jù)流缔御,父組件可以向子組件傳遞數(shù)據(jù)抬闷,但是子組件絕對(duì)不能直接修改這個(gè)數(shù)據(jù);
5.是視圖層框架刹淌,react在做大型項(xiàng)目的時(shí)候不夠用饶氏,只能用它搭建視圖讥耗,只解決數(shù)據(jù)和頁面渲染方面的東西有勾,需要用到flux,redux這樣的數(shù)據(jù)層框架來輔助開發(fā)古程,所以不是大型的完整框架蔼卡。
6.是函數(shù)式編程:constructor(),render()等等,帶來的好處是維護(hù)起來比較容易挣磨,每個(gè)函數(shù)各司其職雇逞;方便自動(dòng)化測(cè)試。
React開發(fā)調(diào)試工具 react developer tools
進(jìn)入chrome瀏覽器擴(kuò)展程序茁裙,進(jìn)入app store應(yīng)用商店塘砸,搜索react developer tools進(jìn)行安裝。
propTypes與defaultProps的應(yīng)用
1.使用PropTypes進(jìn)行類型檢查晤锥,propTypes限制傳值的類型掉蔬,string,func,number等等,類型不對(duì)矾瘾,就會(huì)報(bào)出警告女轿。
出于性能原因,propTypes僅在開發(fā)模式下檢查
2.使用propTypes要先引入壕翩,import PropTypes from 'prop-types'蛉迹;
import PropTypes from 'prop-types'
TodoItem.propTypes = {
item: PropTypes.string,
index: PropTypes.number,
handleDelete: PropTypes.func
}
3.當(dāng)給一個(gè)值設(shè)置了類型,但是父組件沒有給子組件傳這個(gè)值放妈,那么就不會(huì)校驗(yàn)北救,也不會(huì)有警告。如果設(shè)置為必須芜抒,就會(huì)校驗(yàn)珍策,PropTypes.string.isRequired
4.propTypes設(shè)置為isRequuired的時(shí)候,可以通過defaultProps設(shè)置一個(gè)默認(rèn)值挽绩。
TodoItem.defaultProps = {
item:'hello react'
}
props,state與render函數(shù)之間的關(guān)系
1.state數(shù)據(jù)與render頁面聯(lián)動(dòng)底層的原理
當(dāng)組件的state或者props發(fā)生改變的時(shí)候膛壹,這個(gè)組件的render函數(shù)就會(huì)被重新執(zhí)行。render重新執(zhí)行,就會(huì)拿到最新的數(shù)據(jù)去渲染頁面模聋。
2.當(dāng)父組件的render函數(shù)被運(yùn)行的時(shí)候肩民,它的子組件的render函數(shù)都將被重新運(yùn)行(即使props沒有發(fā)生改變,也會(huì)被運(yùn)行)链方。
3.當(dāng)子組件通過父組件傳來的方法更改父組件的state的時(shí)候持痰,父組件的render會(huì)重新執(zhí)行,因?yàn)楦附M件的render函數(shù)重新執(zhí)行祟蚀,子組件的render函數(shù)也被重新執(zhí)行工窍。
React中的虛擬DOM
虛擬DOM是一個(gè)js對(duì)象,用它來描述真實(shí)DOM前酿。
React數(shù)據(jù)視圖更新原理:
1.state數(shù)據(jù)
2.JSX模板
3.數(shù)據(jù) + 模板生成虛擬DOM
['div',{id:'box'},['span',{},'hello world']]
4.用虛擬DOM的結(jié)構(gòu)生成真實(shí)DOM來顯示
<div id='box'><span>hello world</span></div>
5.state發(fā)生變化
6.數(shù)據(jù) + 模板生成新的虛擬DOM
['div',{id:'box'},['span',{},'hello react']]
7.比較原始虛擬DOM與新的虛擬DOM的區(qū)別患雏,找出區(qū)別是什么
['div',{id:'box'},['span',{},'hello world']]
['div',{id:'box'},['span',{},'hello react']]
8.直接操作DOM,修改區(qū)別。
深入了解虛擬DOM
JSX代碼到真是DOM的原理:
JSX由Reacet.createElement()函數(shù)轉(zhuǎn)為虛擬DOM罢维,虛擬DOM再轉(zhuǎn)為真實(shí)DOM渲染淹仑。
JSX -> createElement -> 虛擬DOM(js對(duì)象) ->真實(shí)DOM
render(){
return (
<div><span>{this.props.content}</span></div>
)
}
//如果不用jsx,以下代碼同樣實(shí)現(xiàn)肺孵。但還是jsx更清晰簡單匀借。
render(){
return (
React.createElement('div',{},React.createElement('span',{},this.props.content))
)
}
虛擬DOM的優(yōu)點(diǎn):
1.性能提升了,因?yàn)檎鎸?shí)DOM的比對(duì)變?yōu)榱薺s對(duì)象的比對(duì)平窘;
2.使得跨端應(yīng)用得以實(shí)現(xiàn)吓肋,React Native。虛擬DOM轉(zhuǎn)為原生組件瑰艘,就可以寫原生應(yīng)用了是鬼,一套代碼,實(shí)現(xiàn)網(wǎng)頁和原生應(yīng)用磅叛;
虛擬DOM的diff算法(原始虛擬DOM與新的虛擬DOM如何比對(duì))
1.為什么setState設(shè)計(jì)成異步的
是為了提升react底層的性能屑咳。當(dāng)state數(shù)據(jù)發(fā)生變化的時(shí)候,react會(huì)進(jìn)行虛擬DOM比對(duì)弊琴。setState是異步的兆龙,如果短時(shí)間內(nèi),發(fā)生了多次setState敲董,react可以把多次setState合并成一次setState紫皇,只進(jìn)行一次虛擬DOM比對(duì),然后更新一次DOM腋寨,就可以省去多次DOM比對(duì)帶來的性能上的耗費(fèi)聪铺。所以setState設(shè)計(jì)成異步函數(shù)的初衷本質(zhì)上是為了react底層的性能。
2.同層比對(duì)
在虛擬DOM比對(duì)的時(shí)候有個(gè)同層比對(duì)的概念萄窜,diff算法比對(duì)兩個(gè)虛擬DOM差異的時(shí)候铃剔,會(huì)逐層的比對(duì)撒桨,如果這一層虛擬DOM一致,就接著比對(duì)下一層键兜,如果這一層虛擬DOM不一致的話凤类,下面的就不會(huì)再比對(duì)了,重新生成一遍下面的所有DOM普气,直接用新的替換掉老的谜疤,這樣提升性能。(這樣可能會(huì)導(dǎo)致有些沒有變化的DOM的渲染的浪費(fèi)现诀,但是這種比對(duì)算法簡單夷磕,比對(duì)速度快,節(jié)省了算法上的性能消耗仔沿。)
3.key值比對(duì)
react中在做列表循環(huán)的時(shí)候要引入key值坐桩,實(shí)際上是為了提高虛擬DOM比對(duì)的性能。虛擬DOM的比對(duì)于未,以key值做關(guān)聯(lián)撕攒,所以key值要保持穩(wěn)定陡鹃。
在項(xiàng)目中盡量不要用index做key值烘浦,因?yàn)閕ndex做key值不穩(wěn)定,比如刪除了列表中的第一項(xiàng)萍鲸,列表中的后面的其他項(xiàng)的index值跟著發(fā)生變化闷叉,就導(dǎo)致key值不穩(wěn)定,原始虛擬DOM上的key值與新的虛擬DOM上的key值不同脊阴,影響比對(duì)性能握侧。
同層比對(duì),key值比對(duì)嘿期,都是diff算法中的一部分品擎。
React中ref的使用
1.ref等于一個(gè)箭頭函數(shù),函數(shù)接收一個(gè)參數(shù)备徐,這個(gè)參數(shù)是指向當(dāng)前元素對(duì)應(yīng)的真實(shí)的DOM對(duì)象萄传。幫助我們?cè)趓eact里面直接獲取一個(gè)DOM元素。
一般情況下不建議使用蜜猾。
用到的時(shí)候要注意秀菱,如果希望數(shù)據(jù)更新之后獲取DOM,那么在setState的回調(diào)函數(shù)里去獲取蹭睡。因?yàn)閟etState是一個(gè)異步函數(shù)衍菱,不是立即執(zhí)行的。
React的聲明周期函數(shù)
聲明周期函數(shù)是指在某一個(gè)時(shí)刻組件會(huì)自動(dòng)調(diào)用執(zhí)行的函數(shù)肩豁。
一.Initialization 初始化過程
initialization是初始化過程脊串,組件會(huì)初始化自己的數(shù)據(jù)辫呻,props,state琼锋。constructor是初始化的位置印屁,接收props,定義state斩例。
二.Mounting 掛載過程
一個(gè)組件要被渲染掛載到頁面上雄人,mounting就是掛載的意思。初始化之后就去掛載念赶。
1.componentWillMount
在組件即將被掛載到頁面的時(shí)刻自動(dòng)執(zhí)行础钠。
2.render
3.componentDidMount
在組件掛載到頁面之后自動(dòng)被執(zhí)行。
三.Updating 更新過程
props發(fā)生變化叉谜,或者state發(fā)生變化旗吁,總之?dāng)?shù)據(jù)發(fā)生變化的時(shí)候,就是更新的過程停局。
1.componentWillReceiveProps
一個(gè)組件要從父組件接收參數(shù)很钓,在父組件render執(zhí)行的時(shí)候,如果這個(gè)組件是第一次存在于父組件中董栽,componentWillReceiveProps不會(huì)執(zhí)行码倦,如果這個(gè)組件已經(jīng)存在于父組件中,才會(huì)執(zhí)行锭碳。
2.shouldComponentUpdate
組件更新之前會(huì)被自動(dòng)執(zhí)行,返回一個(gè)布爾類型的結(jié)果袁稽。返回true可以更新,返回false不會(huì)更新擒抛,后面的生命周期都不走了推汽。
3.componentWillUpdate
組件更新之前,在shouldComponentUpdate返回true的時(shí)候會(huì)自動(dòng)執(zhí)行歧沪,返回false的時(shí)候就不會(huì)執(zhí)行了歹撒。
4.render
5.componentDidUpdate
組件更新完成之后,會(huì)自動(dòng)執(zhí)行
四.Unmounting卸載過程
1.componentWillUnmount
當(dāng)一個(gè)組件即將被從頁面中移除的時(shí)候诊胞,會(huì)被執(zhí)行暖夭。
React 聲明周期函數(shù)的使用場景
為什么唯獨(dú)render函數(shù)刪除了之后,程序會(huì)報(bào)錯(cuò)厢钧?因?yàn)镃omponent組件里面默認(rèn)內(nèi)置了其他的生命周期函數(shù)鳞尔,但是沒有內(nèi)置render函數(shù)的默認(rèn)實(shí)現(xiàn),所以render需要自己定義早直。
1.應(yīng)用shouldComponentUpdate來提高組件的性能寥假。
shouldComponentUpdate(nextProps,nextState){
if(nextProps.content!==this.props.content){
return true
}else{
return false
}
}
通過shouldComponentUpdate生命周期函數(shù)提升了組件的性能,避免一個(gè)組件做無畏的render操作霞扬,render函數(shù)重新執(zhí)行糕韧,react底層需要生成一份虛擬DOM,與之前的虛擬DOM作比對(duì)枫振,這樣做可以省略比對(duì)。
2.在componentDidMount中發(fā)送ajax請(qǐng)求
在componentDidMount里發(fā)送ajax請(qǐng)求萤彩,只執(zhí)行一次粪滤,不會(huì)重復(fù)執(zhí)行。
如果在componentWillMount發(fā)送請(qǐng)求雀扶,當(dāng)我們?nèi)憆eactNative或者用react做服務(wù)端的同構(gòu)杖小,可能會(huì)與以后更高端的一些技術(shù)產(chǎn)生沖突,為了避免沖突愚墓,把a(bǔ)jax請(qǐng)求放在componentDidMount里是最合理的予权。
3.使用axios擴(kuò)展工具發(fā)送ajax請(qǐng)求
axios是易用簡潔高效的http庫,它基于promise浪册,符合最新的es規(guī)范扫腺,提供并發(fā)的api,客戶端防止csrf(跨站點(diǎn)請(qǐng)求偽造Cross—Site Request Forgery)村象。體積較小笆环。
axios,ajax與fetch厚者,三選一躁劣,axios當(dāng)之無愧。
查看:axios籍救,ajax與fetch的區(qū)別