讓我們一起學(xué)習(xí)React
React 是Facebook在2013 年開(kāi)源在github上的javaScript庫(kù),React把用戶(hù)界面抽象成一個(gè)個(gè)組件,如按鈕組件Button、對(duì)話框組件Dialog、日期組件 Calemdar 開(kāi)發(fā)者通過(guò)組合這些組件,最終得到功能豐富、可交互的頁(yè)面。通過(guò)引入jsx語(yǔ)法,復(fù)用組件變得非常容易,同時(shí)也能保證組件結(jié)構(gòu)清晰。有了組件這層抽象,React把代碼和真實(shí)渲染目標(biāo)隔離開(kāi)來(lái),除了可以再瀏覽器端渲染DOM來(lái)開(kāi)發(fā)網(wǎng)頁(yè)之外,還能用于開(kāi)發(fā)原生移動(dòng)應(yīng)用。
1.1 專(zhuān)注于視圖層
我們的應(yīng)用已經(jīng)變得前所未有的復(fù)雜,因而開(kāi)發(fā)工具也必須變得越來(lái)越強(qiáng)大,和Angular等框架不同,React并不是完整的,,MVC/MVVM 框架,它專(zhuān)注于提供清晰、簡(jiǎn)潔的View(視圖)層解決方案,而又與模板引擎不同,React不僅僅專(zhuān)注于view層的問(wèn)題,又是一個(gè)包括view和controller的庫(kù),對(duì)于復(fù)雜的應(yīng)用,可以根據(jù)業(yè)務(wù)場(chǎng)景自行選擇業(yè)務(wù)層框架,并根據(jù)需要搭配Flux、redux來(lái)使用。
React不像其他框架那樣提供; 許多復(fù)雜的概念與繁瑣的API 它以Minimal API interface為目標(biāo)只提供組件化相關(guān)的非常少量的API,同時(shí)為了保持靈活性,它沒(méi)有自創(chuàng)一套規(guī)則,而是盡可能的讓用戶(hù)使用原生的javaScript進(jìn)行開(kāi)發(fā),只要熟悉原生的javaScript并了解重要概念后,就可以很容易上手React應(yīng)用。
1.2 VirtualDOM
真實(shí)頁(yè)面對(duì)應(yīng)一個(gè)DOM樹(shù),在傳統(tǒng)頁(yè)面開(kāi)發(fā)模式中,每次需要更新頁(yè)面的時(shí)候,都要手動(dòng)操作DOM來(lái)進(jìn)行更新,如圖。

DOM操作非常昂貴。我們都知道在前端開(kāi)發(fā)中,性能消耗最大的就是DOM更新操作,而且這部分代碼會(huì)讓整體項(xiàng)目代碼變得難以維護(hù)。React把真實(shí)的DOM數(shù)轉(zhuǎn)變成了javaScript對(duì)象樹(shù),也就是viretual DOM

每一次數(shù)據(jù)更新后,重新計(jì)算 viretual DOM 并和上一次生成的 viretual DOM 做對(duì)比,對(duì)發(fā)生變化的部分做批量的更新,React 也提供了直觀的 shouldComponentUpdate 生命周期回調(diào)來(lái)減少數(shù)據(jù)變化后不必要的 viretual DOM對(duì)比過(guò)程,保證性能。
我們說(shuō) viretual DOM 提升了React的性能,但是這并不是React的唯一的亮點(diǎn),此外viretual DOM的渲染方法也比傳統(tǒng)的 DOM 操作好一些,但并不明顯,因?yàn)閷?duì)比DOM 節(jié)點(diǎn)也是需要計(jì)算資源的。
它最大的好處其實(shí)還在于方便和其他平臺(tái)進(jìn)行集成,比如React-native 是基于viretual DOM渲染出來(lái)的原生控件,因?yàn)镽eact組件可以映射為對(duì)應(yīng)的原生控件在輸出的時(shí)候,是輸出WEB DOM還是 Android控件 還是ios控件就由平臺(tái)決定了,因此,React-native 有一個(gè)口號(hào)——learn once,write anywhere
1.3 函數(shù)式編程
在過(guò)去,工業(yè)界的編程方式一直是以命令式編程為主,命令式編程解決的是做什么的問(wèn)題比如圖靈機(jī),而現(xiàn)代計(jì)算機(jī)就是一個(gè)經(jīng)歷了多次進(jìn)化的高級(jí)圖靈機(jī),如果說(shuō)人腦最擅長(zhǎng)的是分析問(wèn)題,那計(jì)算機(jī)擅長(zhǎng)的是執(zhí)行命令,電腦的運(yùn)算速度明顯快過(guò)人腦,命令式編程就像是在給電腦下命令,現(xiàn)在主要的編程語(yǔ)言(包括C和java)都是由命令式編程構(gòu)建起來(lái)的。
而函數(shù)式編程,對(duì)應(yīng)的是聲明式編程,它是人類(lèi)模仿自己的思考方式發(fā)明出來(lái)的,聲明式編程的本質(zhì)是lambda演算,試想當(dāng)我們操作數(shù)據(jù)的每一個(gè)元素并返回一個(gè)新的數(shù)組的時(shí)候,如果是計(jì)算機(jī)的思考方式則是需要一個(gè)新的數(shù)組然后遍歷原來(lái)的數(shù)組,并計(jì)算賦值;如果是人的思考方式,則是構(gòu)建一個(gè)規(guī)則,這個(gè)過(guò)程就變成構(gòu)建一個(gè)f函數(shù)作用在數(shù)組上,然后返回新的數(shù)組,這樣,計(jì)算可以被重復(fù)利用。
2.1 JSX語(yǔ)法
當(dāng)初學(xué)習(xí)React的時(shí)候,jsx是我們遇到的第一個(gè)新的概念,也許我們都是寫(xiě)習(xí)慣js程序的開(kāi)發(fā)者,對(duì)于類(lèi)似于靜態(tài)編譯并不感冒,早些年風(fēng)靡前端的coffeescript也因?yàn)镋S6標(biāo)準(zhǔn)化的加速推進(jìn),慢慢變成了茶語(yǔ)飯后的談資,面對(duì) React 我們又一次需要玩轉(zhuǎn)一門(mén)新的靜態(tài)轉(zhuǎn)譯語(yǔ)言,這一次,有什么不一樣呢?
2.2 JSX的由來(lái)
JSX和React有什么關(guān)系呢?簡(jiǎn)單來(lái)說(shuō),React為了方便View層組件化,承載了構(gòu)建HTML結(jié)構(gòu)化頁(yè)面的職責(zé),“從這點(diǎn)上來(lái)看,React 與其他 javaScript 模板語(yǔ)言有著許多異曲同工之處,但不同之處在于 React 是通過(guò)創(chuàng)建與更新虛擬元素(virtual element)來(lái)管理整個(gè) Virtual DOM 的。
其中,虛擬元素可以理解為和真實(shí)的元素的對(duì)應(yīng),它的構(gòu)建與更新都是在內(nèi)存中完成的,并不會(huì)影響真正渲染到DOM中去,在React中創(chuàng)建虛擬元素可以分為兩類(lèi),DOM元素(DOM element) 與組件元素(component element)分別對(duì)應(yīng)著原生DOM 元素和自定義元素,而JSX與創(chuàng)建元素的過(guò)程有著莫大的關(guān)聯(lián)。
接著,我們從這兩種元素的構(gòu)建開(kāi)始說(shuō)起
-
1.DOM 元素
從過(guò)往的經(jīng)驗(yàn)中知道,“Web 頁(yè)面是由一個(gè)個(gè) HTML 元素嵌套組合而成的。當(dāng)使用javaScript來(lái)描述這些元素的時(shí)候,這些元素可以簡(jiǎn)單地被表示成純粹的 JSON 對(duì)象。比如,現(xiàn)在需要描述一個(gè)按鈕(button),這用 HTML 語(yǔ)法表示非常簡(jiǎn)單:<button class="btn btn-blue"> <em>Confirm</em> </button>其中包括了元素的類(lèi)型和屬性。如果轉(zhuǎn)成 JSON 對(duì)象,那么依然包括元素的類(lèi)型以及屬性:
{ type: 'button', props: { className: 'btn btn-blue', children: [{ type: 'em', props: { children: 'Confirm' } }] } }這樣,我們就可以在js中創(chuàng)建Virtual DOM 元素了。
在React中 到處都是可以復(fù)用的元素,這些元素并不是真實(shí)的實(shí)例,它只是讓React告訴開(kāi)發(fā)者,想要在屏幕上顯示什么。我們無(wú)法通過(guò)方法去調(diào)用這些元素,他們只是不可遍的描述對(duì)象
- 組件元素
當(dāng)然,我們可以很方便地封裝上述的button 元素,得到一種構(gòu)建按鈕的公共方法:
const Button = ({ color, text }) => {
return {
type: 'button',
props: {
className: `btn btn-${color}`,
children: {
type: 'em',
props: {
children: text,
},
},
},
};
}
自然,當(dāng)我們要生成 DOM 元素中具體的按鈕時(shí),就可以方便地調(diào)用 Button({color: 'blue', text: 'Confirm'}) 來(lái)創(chuàng)建。
仔細(xì)思考這個(gè)過(guò)程可以發(fā)現(xiàn),Button 方法其實(shí)也可以作為元素而存在,方法名對(duì)應(yīng)了 DOM 元素類(lèi)型,參數(shù)對(duì)應(yīng)了 DOM 元素屬性,
那么它就具備了元素的兩大必要條件,這樣構(gòu)建的元素就是自定義類(lèi)型的元素,或者稱(chēng)之為組件元素。我們用JSON結(jié)構(gòu)來(lái)描述它:
{
type: Button,
props: {
color: 'blue',
children: 'Confirm'
}
}
這也是 React 的核心思想之一。因?yàn)橛泄驳谋磉_(dá)方法,我們就可以讓元素們彼此嵌套或混合。這些層層封裝的組件元素,就是所謂的 React 組件,最終我們可以用遞歸渲染的方式構(gòu)建出完全的 DOM 元素樹(shù).