接觸React也有一段時(shí)間鲁冯,一直想對(duì)自己工作學(xué)習(xí)中遇到的一些知識(shí)點(diǎn)做一個(gè)總結(jié),卻遲遲沒(méi)有付諸行動(dòng)色查,終于下定決心薯演。本文主要對(duì)自己遇到的一些疑惑的知識(shí)點(diǎn)進(jìn)行總結(jié)。
1. JSX是什么
JSX是運(yùn)用于React架構(gòu)中的一種JavaScript的語(yǔ)法擴(kuò)展秧了,格式類似于模版語(yǔ)言跨扮,主要用來(lái)聲明React中的元素。推薦在React中使用JSX的原因如下:
- 執(zhí)行更快, JSX在編譯為JavaScript代碼后做了優(yōu)化
- 類型安全验毡,在編譯過(guò)程中可以發(fā)現(xiàn)錯(cuò)誤
- 使用JSX編寫模版更加快速簡(jiǎn)單
2. 為什么用className
- ES5之前衡创,在對(duì)象中不能使用保留字,JSX作為JavaScript的擴(kuò)展晶通,所以采用className代替class;
-
React最初的理念是想和瀏覽器的DOM API保持一致璃氢,dom操作元素時(shí)設(shè)置class使用className這個(gè)API:
-
解構(gòu)賦值問(wèn)題, 解構(gòu)屬性如果分配class變量會(huì)報(bào)錯(cuò), 如下所示:
3. 為什么不能直接this.state.xx = xx
剛接觸到React的時(shí)候,我犯過(guò)直接用this.state.xx = xx的錯(cuò)誤, state的值確實(shí)會(huì)更新, 但不會(huì)觸發(fā)UI的更新, 后面在了解了setState的原理后才知道其中原因狮辽。es6中constructor里初始化state使用this.state, 其他情況this.state是只讀的, 修改state值采用setState方法, setState不僅僅更新了this.state的值一也,也是觸發(fā) React的render的機(jī)制巢寡。
4. 關(guān)于setState, 同步還是異步, 第二個(gè)參數(shù)用法,參數(shù)采用對(duì)象和函數(shù)的區(qū)別...
4.1. setState同步還是異步
setState異步行為和第二個(gè)參數(shù)用法
通過(guò)console控制臺(tái)可以看到打印count: 1, 點(diǎn)擊 div (通過(guò)合成事件綁定) 后打印1, 以上是setState中的異步行為; 修改incrementCount函數(shù)如下所示:
通過(guò)控制臺(tái)打印的count值為更新后的;setState函數(shù)第二個(gè)參數(shù)是一個(gè)回調(diào)函數(shù),當(dāng)setState結(jié)束并重新呈現(xiàn)UI時(shí)調(diào)用, 主要用來(lái)監(jiān)聽(tīng)React渲染結(jié)果
setState的同步行為
通過(guò)console控制臺(tái)可以看到打印setTimeout: 1, 點(diǎn)擊 div (通過(guò)原生事件綁定) 后打印2, 以上是setState中的同步行為;
以下是我簡(jiǎn)單的總結(jié), 水平有限
React在其內(nèi)部機(jī)制能檢測(cè)的地方,比如合成事件, 鉤子函數(shù), 生命周期中表現(xiàn)出異步行為, 在其機(jī)制檢測(cè)不到的地方, 例如setInterval, setTimeout, promise, 原生事件中表現(xiàn)出同步行為;
4.2 setState參數(shù)采用對(duì)象和函數(shù)的區(qū)別
setState參數(shù)采用對(duì)象的行為
從代碼層面上看, 點(diǎn)擊div后, 頁(yè)面上會(huì)顯示couont: 3, 實(shí)際只增加了1,這是 React批量更新的結(jié)果;
setState參數(shù)采用函數(shù)的行為
通過(guò)控制臺(tái)打印, 點(diǎn)擊一次 div后, 實(shí)現(xiàn)了累加3次的結(jié)果,傳入的參數(shù)result是一個(gè) state對(duì)象, 每次調(diào)用plusCount之前, result都是最新的 state;
通過(guò)對(duì)比發(fā)現(xiàn), setState的參數(shù)采用函數(shù)能夠得到可靠的state值, 如果你要使用當(dāng)前組件的狀態(tài)或者屬性值來(lái)計(jì)算下一個(gè)狀態(tài)塘秦,可以采用函數(shù)作為 setState 的參數(shù)讼渊;
5. React中組件為什么要大寫字母開頭
在用React開發(fā)過(guò)程中, 都是采用JSX語(yǔ)法, 我曾經(jīng)寫了一個(gè)小寫字母開頭的組件, 結(jié)果就是在頁(yè)面上找不到我寫的組件, 后面定位到React組件必須大寫字母開頭;
React中 從JSX語(yǔ)法轉(zhuǎn)變?yōu)檎鎸?shí)的dom的過(guò)程: JSX -> virtual DOM -> real DOM, 瀏覽器無(wú)法識(shí)別JSX語(yǔ)法, 需要babel進(jìn)行轉(zhuǎn)譯轉(zhuǎn)化為virtual DOM, 原因出在babel的轉(zhuǎn)譯過(guò)程;
babel調(diào)用React.createElement(type, config, children)轉(zhuǎn)譯JSX語(yǔ)法, 組件首字母小寫時(shí), babel轉(zhuǎn)譯時(shí)會(huì)當(dāng)成字符串傳遞進(jìn)去, 首字母大寫時(shí), babel會(huì)傳遞一個(gè)變量進(jìn)去;
6. React中組件通信
React是單項(xiàng)數(shù)據(jù)流, React中組件通信分幾種情況, 父組件向子組件通信, 子組件向父組件通信, 跨級(jí)組件通信, 沒(méi)有嵌套關(guān)系的組件之間通信;
父子組件通信
React中數(shù)據(jù)自上而下傳遞, 父組件向子組件通信比較常見(jiàn), 父組件通過(guò)props向子組件傳遞信息;
子組件通過(guò)利用回調(diào)函數(shù)和自定義事件機(jī)制向父組件傳遞信息; 可以簡(jiǎn)單理解為父組件向子組件通信采用屬性通信, 子組件向父組件通信采用事件通信;
跨級(jí)組件通信
跨級(jí)組件之間可以通過(guò)層層傳遞props進(jìn)行通信; 兄弟組件之間可以利用同一層級(jí)的上級(jí)作為中轉(zhuǎn)站進(jìn)行通信, 如果兄弟組件都是頂層組件,可以在外層套一層組件, 該組件起到保存數(shù)據(jù)和傳遞信息的作用; 組件層級(jí)嵌套比較深, 可以通過(guò)context方式, 可以在contructor中傳遞context參數(shù), 利用上下文getChildContext來(lái)傳遞信息, 任何一層級(jí)的子級(jí)都可以通過(guò)this.context直接訪問(wèn)(context是一個(gè)全局變量, 且不知道是哪里傳遞過(guò)來(lái)的, React官方文檔不建議使用); 組件之間還可以通過(guò)全局事件來(lái)通信, 例如不同的頁(yè)面可以通過(guò)參數(shù)傳遞數(shù)據(jù), 下個(gè)頁(yè)面通過(guò)location.param獲取;
沒(méi)有嵌套關(guān)系組件通信
沒(méi)有嵌套關(guān)系的組件之間可以采用自定義事件進(jìn)行通信, 例如發(fā)布/訂閱模式;
React最難的在于如何高效的實(shí)現(xiàn)組件之間的通信, 自己實(shí)現(xiàn)組件間通信, 狀態(tài)難以管理, 可以借助狀態(tài)管理工具如flux, redux, mobx等;
總結(jié)
本文只是對(duì)React部分知識(shí)點(diǎn)做一些簡(jiǎn)單的總結(jié), 還有一些不全面和不夠深入的地方, 后續(xù)文章會(huì)繼續(xù)總結(jié)。