React是Facebook在2013年推出的前段框架。React不是一個(gè)MVC框架瘫絮,React是一個(gè)構(gòu)造可組合式用戶界面的庫嘱吗。它鼓勵(lì)創(chuàng)建可重用的UI組件會(huì)隨著時(shí)間而改變的數(shù)據(jù)勺像。React采用不同的方法凫乖,當(dāng)組件第一次初始化時(shí)确垫,render方法調(diào)用,為試圖生成一個(gè)輕量級(jí)的表現(xiàn)帽芽。通過這個(gè)表現(xiàn)删掀,產(chǎn)生一個(gè)標(biāo)簽字符串,然后插入文檔中导街。當(dāng)數(shù)據(jù)變化時(shí)披泪,render方法再次被調(diào)用。為了盡可能有效的完成更新搬瑰,我們比較之前調(diào)用的render返回的值與新的值款票,然后產(chǎn)生一個(gè)最小的變更去應(yīng)用DOM中。
問題出現(xiàn)的根源
- 傳統(tǒng) UI 操作關(guān)注太多細(xì)節(jié)
- 應(yīng)用程序狀態(tài)分散在各處難以追蹤和維護(hù)
Facebook認(rèn)為MVC無法滿足他們的擴(kuò)展需求泽论,由于他們非常巨大的代碼庫和龐大的組織艾少,使得MVC很快變得復(fù)雜,每當(dāng)需要添加一項(xiàng)新功能或者特性時(shí)翼悴,系統(tǒng)的復(fù)雜就成級(jí)數(shù)的增長(zhǎng)缚够,致使代碼變得脆弱而不可預(yù)測(cè),結(jié)果導(dǎo)致他們的MVC正在土崩瓦解鹦赎。認(rèn)為MVC不適合大規(guī)模的應(yīng)用谍椅。當(dāng)系統(tǒng)中有很多模型和相應(yīng)的視圖時(shí),其復(fù)雜度就會(huì)迅速擴(kuò)大钙姊,非常難以理解和調(diào)試毯辅,特別是模型和視圖可能存在雙向數(shù)據(jù)流動(dòng)。
React:始終整體"刷新"頁面煞额,無需關(guān)心細(xì)節(jié)。以組件的方式去描述UI沾谜,4個(gè)必須API膊毁,單向數(shù)據(jù)流,完善的錯(cuò)誤提示基跑。
數(shù)據(jù)模型如何解決
傳統(tǒng)MVC難以擴(kuò)展和維護(hù)婚温,Model和View之間的關(guān)系錯(cuò)綜復(fù)雜而且雙向綁定,如果業(yè)務(wù)復(fù)雜出現(xiàn)問題后很難去追蹤是Model的問題還是View的問題媳否。
針對(duì)這個(gè)問題栅螟,React提出Flux架構(gòu)荆秦,該設(shè)計(jì)模式的核心思想就是單向數(shù)據(jù)流。首先用戶操作產(chǎn)生Action力图,Action經(jīng)過Dispatcher再發(fā)送到Store步绸,Store根據(jù)Action來進(jìn)行處理,View是綁定到Store上的吃媒,此時(shí)View隨Store更新而更新瓤介。
Flux架構(gòu)的衍生項(xiàng)目:Redux、Mobx赘那。
組件
React組件由props和state最終得到一個(gè)View刑桑。狀態(tài)有外部傳過來狀態(tài)和內(nèi)部維護(hù)狀態(tài),兩種狀態(tài)最終決定了View募舟。React一般不提供方法祠斧,而是某種狀態(tài)機(jī),可以理解React組件為一個(gè)純函數(shù)拱礁,React是單向數(shù)據(jù)綁定梁肿。
以組件的方式考慮UI的構(gòu)建,將UI組織成組件樹的形式觅彰。
下面的評(píng)論框由CommentBox吩蔑、CommentList和CommentForm三個(gè)組件共同完成,代碼部分除了div和h1標(biāo)準(zhǔn)的html的tag外還有CommentList和CommentForm兩個(gè)自定義組件共同完成填抬。
受控組件的狀態(tài)來自外部烛芬,要傳遞value和onChange,非受控組件的狀態(tài)由內(nèi)部維護(hù)飒责,如果外部需要可以通過其他方式獲取赘娄,也就不需要傳遞value和onChange。
在創(chuàng)建組件時(shí)要遵守單一職責(zé)原則宏蛉。每個(gè)組件只做一件事遣臼,組件是構(gòu)建UI的最小元素,每個(gè)組件都應(yīng)該盡量的小拾并,這樣才能夠讓復(fù)雜度分散出去揍堰,在以后的開發(fā)中如果組件變得復(fù)雜,應(yīng)該拆分成小組件嗅义。
數(shù)據(jù)狀態(tài)管理要遵守DRY原則屏歹。能計(jì)算得到的狀態(tài)就不要單獨(dú)存儲(chǔ);組件盡量無狀態(tài)之碗,所需數(shù)據(jù)通過props獲取以提高組件的性能蝙眶。
JSX的本質(zhì)
JSX:在JavaScript代碼中直接寫HTML標(biāo)記。JSX并不是模板語言褪那,只是一種語法糖幽纷。TIP:自定義組件以大寫字母開頭式塌,React認(rèn)為小寫的tag是原生DOM節(jié)點(diǎn),如div友浸;JSX標(biāo)記可以直接使用屬性語法峰尝,例如<menu.Item />
。
比如我們定義了一個(gè)變量name尾菇,又定義了一個(gè)HTML的element:
const name = 'Vincent Wang';
const element = <h1>Hello, {name}</h1>
實(shí)際上是動(dòng)態(tài)創(chuàng)建了一個(gè)組件境析,而且是用JavaScript語法。
JSX本身也是表達(dá)式派诬,element返回一個(gè)HTML的節(jié)點(diǎn):
const element = <h1>Hello, world!</h1>
在屬性中使用表達(dá)式劳淆,如果給一個(gè)組件傳遞屬性的值,這個(gè)屬性的值可以是JavaScript的表達(dá)式:
<MyComment foo={1 + 2} />
延展屬性默赂,如果給一個(gè)組件傳遞一組值沛鸵,此時(shí)我們不需要一個(gè)一個(gè)填寫,只需要...
語法缆八,
const props = { name: "Red", value: "red" };
const greeting = <Greeting {...props} />;
表達(dá)式作為子元素曲掰,子元素是React的一個(gè)特殊屬性。只需要用大括號(hào)將JavaScript語法包起來奈辰。
const element = <li>{props.message}</li>
** JSX的優(yōu)點(diǎn)**
- 有聲明式創(chuàng)建界面的直觀
- 代碼動(dòng)態(tài)創(chuàng)建界面的靈活
- 不需要學(xué)習(xí)新的模板語言
React生命周期及使用場(chǎng)景
React主要分三個(gè)階段:Render階段(計(jì)算當(dāng)前的狀態(tài))栏妖、Pre-commit階段(讀取DOM內(nèi)容)和Commit階段(React把當(dāng)前狀態(tài)映射到DOM節(jié)點(diǎn)時(shí)需要實(shí)際更新DOM節(jié)點(diǎn))。
圖片來源:http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
生命周期可以分為三個(gè)類型:掛載時(shí)奖恰、更新時(shí)和卸載時(shí)吊趾。
創(chuàng)建時(shí)
- constructor
一個(gè)組件的構(gòu)造函數(shù)的創(chuàng)建,也是唯一可以直接修改state的地方瑟啃。 - getDerivedStateFromProps
從外部的屬性初始化內(nèi)部的狀態(tài)论泛,在初始安裝和后續(xù)更新上,都在調(diào)用render方法之前立即調(diào)用getDerivedStateFromProps蛹屿。它返回一個(gè)對(duì)象以更新狀態(tài)屁奏,或者返回null則不更新任何內(nèi)容。這個(gè)方法一般不建議使用错负,如果state需要從props中獲取的時(shí)候坟瓢,可以通過props動(dòng)態(tài)計(jì)算等到,不需要單獨(dú)存儲(chǔ)這個(gè)狀態(tài)湿颅,否則要維護(hù)兩者狀態(tài)一致性载绿,這樣會(huì)增加復(fù)雜度,每次render都會(huì)調(diào)用油航。一般表單控件獲取默認(rèn)值。
3.render
描述UI DOM結(jié)構(gòu)怀浆,類組件中唯一需要的方法谊囚。 - componentDidMount
掛載組件(插入樹中)后立即調(diào)用componentDidMount()
怕享。我們可以在此處發(fā)起請(qǐng)求或者定義外部的資源等。只執(zhí)行一次镰踏,可以獲取外部資源函筋。
更新時(shí)
當(dāng)組件有新的屬性或者修改了state內(nèi)部狀態(tài),當(dāng)然如果強(qiáng)制刷新forceUpdate
可以會(huì)觸發(fā)奠伪。
- getDerivedStateFromProps
同樣是從外部屬性得到內(nèi)部的狀態(tài) - shouldComponentUpdate
使用shouldComponentUpdate()讓React知道組件的輸出是否不受當(dāng)前狀態(tài)或道具更改的影響跌帐。在這里可以做一些組件的性能優(yōu)化,比如props即使發(fā)生變化且UI不需要更新绊率,這時(shí)可以通知React組件直接返回false則不需要Update谨敛。一般可以由PureComponent自動(dòng)實(shí)現(xiàn),來判斷當(dāng)前state和props是否發(fā)生變化滤否。 - render
計(jì)算虛擬的DOM脸狸,虛擬DOM維持內(nèi)部的UI狀態(tài),計(jì)算diff等藐俺。 - getSnapshotBeforeUpdate
它使組件可以在DOM可能發(fā)生更改之前從DOM捕獲一些信息(例如炊甲,滾動(dòng)位置),返回的任何值都將作為參數(shù)傳遞給componentDidUpdate()欲芹,一般在獲取render之前的DOM狀態(tài)時(shí)使用卿啡。 - componentDidUpdate
發(fā)生更新后,立即調(diào)用componentDidUpdate()菱父,初始渲染不調(diào)用此方法颈娜。React更新的事情做完后可以根據(jù)實(shí)際業(yè)務(wù)在此處做一些處理,然后更新到UI上滞伟。頁面根據(jù)props變化來重新獲取數(shù)據(jù)揭鳞。
卸載時(shí)
- componentWillUnmount
當(dāng)組件移除時(shí),需要銷毀組件來釋放資源梆奈。
該文章為記錄本人的學(xué)習(xí)路程野崇,也希望能夠幫助大家,知識(shí)共享亩钟,共同成長(zhǎng)乓梨,共同進(jìn)步!G逅帧扶镀!文章地址:http://www.reibang.com/p/b6f5547e0caa