秒懂 ReactJS

ThoughtWorks發表於2016-05-18

這篇文章是為ReactJS小白準備的,希望他們快速抓住ReactJS的要點並能在實踐中隨機應變。

兩句話版本

  • ReactJs把檢視更新簡化為一個render函式
  • render函式接收兩個引數,分別是配置項和狀態

長版本

ReactJs是一個專注於View的Web前端框架。Web前端的View就是瀏覽器中的Dom元素,改變View的唯一途徑就是修改瀏覽器中的Dom元素,因此ReactJs的核心任務就是如何修改Dom元素,作為一個成功的框架,ReactJs使修改Dom元素變得高效而又簡單。

ReactJs把修改Dom的操作簡化成一個函式renderInto(parentDom, props, states)=>htmlString,這個函式的意圖就是根據props,states計算出檢視對應的html字串並新增為parentDom的子節點。props和states就是普通的javascript物件,這個函式的核心邏輯就是計算html元素的機構及元素屬性然後拼接成字串返回。作為框架,ReactJs用JSX形式的DSL解決了拼接html的任務並接管了更新到parentDom的職責。看一個例子,理解這個函式並理解ReactJs怎麼使用這個函式你就可以一個人開始ReactJs之旅了。

函式第一行根據props計算title,第二行根據states計算description,最後以JSX形式返回拼接好的html字串。

如果你用過AngularJs,EmberJs等類似的前端框架,你可能會覺得沒什麼了不起,不就是把模板和邏輯放到一起嗎?是的,沒錯,但這不僅僅是組織形式上的改變,而是程式設計隱喻的轉變—從複雜的MVC或MVVM模式到簡單的render函式。還有一點不同是JSX最終編譯成呼叫react-dom的javascript語句,而不是直接生成字串。

render函式還只是ReactJs這座冰山的一角,”React”會在render函式的輸入變化時再次呼叫這個函式。再看一個例子。

這個例子增加了一個”+1”按鈕,當使用者點選按鈕時會修改states,ReactJs在states變化時的”React”就是再次呼叫render函式,然後用新輸出更新瀏覽器的dom。

可能你會問,props和states不就是Model嗎?是的,可以理解成Model,但此Model非彼Model,props和states都是為View服務的而非和View平起平坐。

可能你還會問,為啥不把props和states合併成一個物件?要回答這個問題,就涉及到複雜檢視的場景。想想看,當檢視內的元素不斷增加時,程式碼上如何處理,還要在一個render函式裡折騰嗎?肯定不會。我猜你已經想到了,要把大問題拆小。ReactJs給出的解決方法就是把大檢視拆成若干個小檢視,每個檢視都有自己的render函式,在JSX中可以直接使用檢視標籤。看一個例子。

這個例子中有兩類View,分別是Score和ScoreList。ScoreList的render函式中使用Score標籤並給出配置項name的值。詳細看一下Score,ReactJs提供createClass方法定義檢視,在render函式中通過this.props訪問外部傳入的配置項,通過this.states訪問檢視內部的狀態。從意圖上看,props外部傳入檢視的配置項,擁有者是父檢視,檢視內部只能讀取配置項,states的擁有者是檢視自身。

區分props和states的結果就是,子檢視沒辦法直接改變父檢視,檢視改變一定是自觸發改變的檢視開始向子檢視傳播。對上面的例子,當Tom的Score改變時,ScoreList其他部分一定不會改變,所以檢視更新從Tom的Score檢視開始就可以,這就保證了能更高效地計算檢視變化,再加上VirtualDom的使用,使ReactJs的效率大大超過其他框架。

當子檢視需要改變父檢視時,也一定是從父檢視開始向下更新。假如上面的例子中ScoreList還有平均分的檢視,當Tom的分數改變時,需要更新ScoreList中的平均分。這就需要Score檢視在處理”+1”輸入時把變化通知到ScoreList,做法時給Score增加配置項,ScoreList中定義更新平均分的函式並把函式作為配置項傳給Score。當ScoreList更新時,因為Jerry的props和states都沒變化,所以Jerry的Score檢視不需要更新。

這就是ReactJs的全部祕密了(不過Web前端本身是一個複雜系統,你還需要了解更多其他內容)。

相關文章