<meta charset="utf-8">
經(jīng)過這段時(shí)間的學(xué)習(xí)和實(shí)踐,對(duì)React有了一定的了解,謹(jǐn)以此文記錄自己對(duì)React的認(rèn)識(shí)。如有不妥之處,歡迎批評(píng)指正。
React的三項(xiàng)核心技術(shù):
- 虛擬DOM
- 響應(yīng)式UI
- 組件
一、虛擬DOM
- DOM(Document Object Model)
說到虛擬DOM,我們先來回顧一下什么是DOM。在《JavaScript DOM 編程方法》中的定義是:DOM是一套對(duì)文檔的內(nèi)容進(jìn)行抽象和概念化的方法。簡而言之,它是文檔對(duì)應(yīng)的對(duì)象模型,DOM把一份文檔(以HTML為例)表示為一棵樹,在DOM中,文檔是由節(jié)點(diǎn)構(gòu)成的集合,而節(jié)點(diǎn)又分為不同的類型,元素(element)節(jié)點(diǎn)、文本(text)節(jié)點(diǎn)、屬性(attribute)節(jié)點(diǎn)。DOM就是為了操作HTML中的元素,例如我們常用的的getElementById(),就是DOM中的一個(gè)方法。DOM不是一種編程語言,但是我們用JS對(duì)網(wǎng)頁進(jìn)行的所有操作都是通過DOM進(jìn)行的。用戶在網(wǎng)頁看到的內(nèi)容是開發(fā)者告訴DOM應(yīng)該表現(xiàn)成什么樣子,jQuery 和 React 都是庫,開發(fā)者使用它們作為與 DOM 交流的工具。
我們知道,瀏覽器的工作流是:創(chuàng)建DOM樹、創(chuàng)建渲染樹、布局、繪制。每一次的每一次的 DOM 操作,都會(huì)引發(fā)一次從創(chuàng)建 DOM 樹、創(chuàng)建渲染樹、布局到繪制的全過程,尤其是在創(chuàng)建渲染樹階段,對(duì)節(jié)點(diǎn)樣式的計(jì)算量通常很大。而正常的,由用戶引發(fā)的頁面改變往往不止一次的 DOM 操作,多次計(jì)算,將導(dǎo)致頁面性能大幅降低。在之前的jQuery開發(fā)中我發(fā)現(xiàn)一旦DOM操作比較復(fù)雜,需要花大量時(shí)間理清他們之間的聯(lián)系,而且DOM操作引發(fā)的重復(fù)計(jì)算會(huì)導(dǎo)致頁面的渲染等待時(shí)間會(huì)變長。
- 虛擬DOM
相比于操作真實(shí)DOM,React的虛擬DOM就能展示它在速度上的優(yōu)勢了。React是開發(fā)者和DOM樹之間的中間人,它簡化了二者的溝通成本,還會(huì)用虛擬DOM來速寫真實(shí)DOM,開發(fā)者只用不停地告訴React他的要求,React會(huì)在草稿中快速記錄下所有細(xì)節(jié)并在合適的時(shí)候拿給DOM樹看。React十分機(jī)智,它會(huì)對(duì)草稿進(jìn)行去重和對(duì)比篩選出最終樣板后展示給DOM樹,讓他能夠付出最小的工作量根據(jù)要求展示出需要的樣子。
一開始對(duì)虛擬DOM的理解停留在:通過JavaScript對(duì)象模擬原生DOM,加上DOM Diff 極大提升了DOM操作的性能。然而,虛擬DOM最大的意義不在于性能的提升,而在于對(duì)DOM進(jìn)行了一層抽象。它在UI和代碼之間建立了一個(gè)隔離層,減少了邏輯和試圖的耦合性,提高了代碼的可移植性和可維護(hù)性。
<meta charset="utf-8">

二、響應(yīng)式UI
使用 jQuery 來更新 DOM需要在適當(dāng)?shù)臅r(shí)機(jī)以正確的順序來指定要更改的元素,React可以通過改變應(yīng)用中的數(shù)據(jù)來改變React應(yīng)用的狀態(tài),React應(yīng)用中的每一部分都使用props(外部傳入)和states(本身)兩個(gè)屬性來儲(chǔ)存狀態(tài)。state屬性產(chǎn)生于ReactElement的內(nèi)部,可傳遞到子ReactElement中作為props。這兩者的差異就好比小時(shí)候我媽每天要打電話告訴我明天穿什么衣服的時(shí)候,之前的描述是你先穿哪件秋衣,再套哪件馬甲,再穿哪個(gè)外套,現(xiàn)在她只用拍張照告訴我她的搭配,我自己去穿就好。
用數(shù)據(jù)去驅(qū)動(dòng)組件狀態(tài)的變化,開發(fā)者專注于數(shù)據(jù)部分,當(dāng)數(shù)據(jù)不變時(shí)只有一種對(duì)應(yīng)的界面, 因而程序有著更好的可預(yù)測性。
三、組件
- 基本思想
React從功能的角度出發(fā),將用戶界面上每一個(gè)功能相對(duì)獨(dú)立的模塊定義成組件,然后將小組件通過組合或嵌套的方式構(gòu)成大組件,最終完成整體UI的構(gòu)建。對(duì)比MVC的將模型—視圖—控制器定義成不同的類,實(shí)現(xiàn)表現(xiàn),數(shù)據(jù),控制的分離,組件化開發(fā)模式的思想是用戶界面功能模塊間的分離,從功能的角度出發(fā),將用戶界面分成不同的組件,每個(gè)組件都獨(dú)立封裝。這樣做的好處有,一個(gè)復(fù)雜的UI可以拆分成多個(gè)簡單的UI組件;每個(gè)組件都是具有獨(dú)立功能的,可用于多個(gè)場景;每個(gè)小組件僅包含自身的邏輯,更容易被維護(hù)。React里將組件看成一個(gè)狀態(tài)機(jī),先設(shè)置初始狀態(tài),在用戶的操作使得狀態(tài)屬性發(fā)生改變時(shí),會(huì)重新渲染用戶界面,而且會(huì)向下遍歷整棵組件樹,重新渲染使用該屬性的組件。
- 函數(shù)組件和類組件
React有兩種組件,函數(shù)組件(Functional Components) 和類組件(Class Components),我觀察到在實(shí)際工程中大量使用了類組件,在了解了函數(shù)組件的試用場景和功能實(shí)現(xiàn)之后,此處要好好pick一下。
函數(shù)組件是純展示組件,這種組件無法使用State,也無法使用組件的生命周期方法,因此它只負(fù)責(zé)根據(jù)傳入的props來渲染DOM,不涉及到state狀態(tài)的操作。函數(shù)組件是無狀態(tài)的,因此就不會(huì)有組件實(shí)例化的過程,無實(shí)例化過程也就不需要分配多余的內(nèi)存,從而性能得到一定的提升,同時(shí)也就不能訪問this對(duì)象。

從以上的定義方式我們可以看出聲明簡潔,代碼量少。函數(shù)組件不需要聲明類,可以避免大量的譬如extends或者constructor這樣的代碼;不需要聲明this,也不需要將函數(shù)的this關(guān)鍵字綁定到當(dāng)前作用域。因此如果開發(fā)中組件僅僅需要展示,盡量使用函數(shù)組件。
類組件是React推薦的組件定義方式,React 升級(jí)到 v0.13 后就支持了 ES6 的class語法,我們可以使用class App extends React.Component{…}的方式創(chuàng)建組件,這也是目前官方推薦創(chuàng)建有狀態(tài)組件的方式。React.Component創(chuàng)建組件時(shí),事件函數(shù)并不會(huì)自動(dòng)綁定this,需要我們手動(dòng)綁定,不然this將不會(huì)指向當(dāng)前組件的實(shí)例對(duì)象。以下有三種手動(dòng)綁定方法:在構(gòu)造函數(shù)中完成綁定;在調(diào)用時(shí)使用method.bind(this)來完成綁定;使用arrow function來綁定。
- 組件間通信
我們知道React是單向數(shù)據(jù)流,數(shù)據(jù)主要從父節(jié)點(diǎn)通過props傳遞到子節(jié)點(diǎn)。如果頂層(父級(jí))的某個(gè)props改變了,React會(huì)重渲染所有的子節(jié)點(diǎn)。不可以使用this.props直接修改props,因?yàn)閜rops是只讀的,props是用于整個(gè)組件樹中傳遞數(shù)據(jù)和配置。state和props的區(qū)別在于前者只存在于組件內(nèi)部,只能從當(dāng)前組件調(diào)用this.setState修改state值。
父組件向子組件傳遞直接通過props。子組件向父組件通信可以通過在父組件里聲明回調(diào)函數(shù),通過props傳遞給子組件,子組件調(diào)用該函數(shù),把要傳遞的內(nèi)容通過參數(shù)傳給父組件。兄弟間通信可以借助共同擁有的父組件,而如果兄弟組件都是最高層的組件,為了能夠讓它們進(jìn)行通信,必須在它們外層再套一層組件,這個(gè)外層的組件起著保存數(shù)據(jù),傳遞信息的作用,這其實(shí)就是redux所做的事情。
因?yàn)橹暗那岸碎_發(fā)一直使用jQuery,對(duì)比了兩者,在此我要為jQuery多說幾句:
- React并不適合所有項(xiàng)目,需要結(jié)合實(shí)際情況綜合考慮
- jQuery與React并不是一個(gè)層面上的東西,jQuery只是一個(gè)工具庫,這里只是展示兩種編程模式的思維差異。React適合用在那些DOM操作復(fù)雜的單頁面應(yīng)用,jQuery則是個(gè)用來幫你完成一些基本操作的工具庫
- 理解一個(gè)技術(shù)的思想比學(xué)會(huì)怎么用它更重要,同時(shí)我們還需要知道不同的技術(shù)間的區(qū)別的核心在哪,這樣我們才能學(xué)會(huì)用合適的技術(shù)去解決合適的問題
- jQuery可以寫出非常簡潔的代碼。但是必須想出良好的代碼結(jié)構(gòu),每次想要增加新功能的時(shí)候還需要特別注意是否影響代碼的重構(gòu),使用React會(huì)幫助團(tuán)隊(duì)內(nèi)部擁有更好的代碼結(jié)構(gòu),頁面性能也會(huì)得到相應(yīng)的提高