現在最熱門的前端架構有AngularJS、React、Bootstrap等。自從接觸了ReactJS,ReactJs的虛拟DOM(Virtual DOM)群組件化的開發深深的吸引了我,下面來跟我一起領略ReactJs的風采吧~~ 文章有點長,耐心讀完,你會有很大收獲哦~
一、ReactJS簡介
React 起源于 Facebook 的内部項目,因為該公司對市場上所有 JavaScript MVC 架構,都不滿意,就決定自己寫一套,用來架設 Instagram 的網站。做出來以後,發現這套東西很好用,就在2013年5月開源了。由于 React 的設計思想極其獨特,屬于革命性創新,性能出衆,代碼邏輯卻非常簡單。是以,越來越多的人開始關注和使用,認為它可能是将來 Web 開發的主流工具。
ReactJS官網位址:http://facebook.github.io/react/

Github位址:https://github.com/facebook/react
二、對ReactJS的認識及ReactJS的優點
首先,對于React,有一些認識誤區,這裡先總結一下:
React不是一個完整的MVC架構,最多可以認為是MVC中的V(View),甚至React并不非常認可MVC開發模式;
React的伺服器端Render能力隻能算是一個錦上添花的功能,并不是其核心出發點,事實上React官方站點幾乎沒有提及其在伺服器端的應用;
有人拿React和Web Component相提并論,但兩者并不是完全的競争關系,你完全可以用React去開發一個真正的Web Component;
React不是一個新的模闆語言,JSX隻是一個表象,沒有JSX的React也能工作。
1、ReactJS的背景和原理
在Web開發中,我們總需要将變化的資料實時反應到UI上,這時就需要對DOM進行操作。而複雜或頻繁的DOM操作通常是性能瓶頸産生的原因(如何進行高性能的複雜DOM操作通常是衡量一個前端開發人員技能的重要名額)。React為此引入了虛拟DOM(Virtual DOM)的機制:在浏覽器端用Javascript實作了一套DOM API。基于React進行開發時所有的DOM構造都是通過虛拟DOM進行,每當資料變化時,React都會重新建構整個DOM樹,然後React将目前整個DOM樹和上一次的DOM樹進行對比,得到DOM結構的差別,然後僅僅将需要變化的部分進行實際的浏覽器DOM更新。而且React能夠批處理虛拟DOM的重新整理,在一個事件循環(Event Loop)内的兩次資料變化會被合并,例如你連續的先将節點内容從A變成B,然後又從B變成A,React會認為UI不發生任何變化,而如果通過手動控制,這種邏輯通常是極其複雜的。盡管每一次都需要構造完整的虛拟DOM樹,但是因為虛拟DOM是記憶體資料,性能是極高的,而對實際DOM進行操作的僅僅是Diff部分,因而能達到提高性能的目的。這樣,在保證性能的同時,開發者将不再需要關注某個資料的變化如何更新到一個或多個具體的DOM元素,而隻需要關心在任意一個資料狀态下,整個界面是如何Render的。
如果你像在90年代那樣寫過伺服器端Render的純Web頁面那麼應該知道,伺服器端所要做的就是根據資料Render出HTML送到浏覽器端。如果這時因為使用者的一個點選需要改變某個狀态文字,那麼也是通過重新整理整個頁面來完成的。伺服器端并不需要知道是哪一小段HTML發生了變化,而隻需要根據資料重新整理整個頁面。換句話說,任何UI的變化都是通過整體重新整理來完成的。而React将這種開發模式以高性能的方式帶到了前端,每做一點界面的更新,你都可以認為重新整理了整個頁面。至于如何進行局部更新以保證性能,則是React架構要完成的事情。
借用Facebook介紹React的視訊中聊天應用的例子,當一條新的消息過來時,傳統開發的思路如上圖,你的開發過程需要知道哪條資料過來了,如何将新的DOM結點添加到目前DOM樹上;而基于React的開發思路如下圖,你永遠隻需要關心資料整體,兩次資料之間的UI如何變化,則完全交給架構去做。可以看到,使用React大大降低了邏輯複雜性,意味着開發難度降低,可能産生Bug的機會也更少。
2、元件化
虛拟DOM(virtual-dom)不僅帶來了簡單的UI開發邏輯,同時也帶來了元件化開發的思想,所謂元件,即封裝起來的具有獨立功能的UI部件。React推薦以元件的方式去重新思考UI構成,将UI上每一個功能相對獨立的子產品定義成元件,然後将小的元件通過組合或者嵌套的方式構成大的元件,最終完成整體UI的建構。例如,Facebook的instagram.com整站都采用了React來開發,整個頁面就是一個大的元件,其中包含了嵌套的大量其它元件,大家有興趣可以看下它背後的代碼。
如果說MVC的思想讓你做到視圖-資料-控制器的分離,那麼元件化的思考方式則是帶來了UI功能子產品之間的分離。我們通過一個典型的Blog評論界面來看MVC群組件化開發思路的差別。
對于MVC開發模式來說,開發者将三者定義成不同的類,實作了表現,資料,控制的分離。開發者更多的是從技術的角度來對UI進行拆分,實作松耦合。
對于React而言,則完全是一個新的思路,開發者從功能的角度出發,将UI分成不同的元件,每個元件都獨立封裝。
在React中,你按照界面子產品自然劃分的方式來組織和編寫你的代碼,對于評論界面而言,整個UI是一個通過小元件構成的大元件,每個元件隻關心自己部分的邏輯,彼此獨立。
React認為一個元件應該具有如下特征:
(1)可組合(Composeable):一個元件易于和其它元件一起使用,或者嵌套在另一個元件内部。如果一個元件内部建立了另一個元件,那麼說父元件擁有(own)它建立的子元件,通過這個特性,一個複雜的UI可以拆分成多個簡單的UI元件;
(2)可重用(Reusable):每個元件都是具有獨立功能的,它可以被使用在多個UI場景;
(3)可維護(Maintainable):每個小的元件僅僅包含自身的邏輯,更容易被了解和維護;
二、下載下傳ReactJS,編寫Hello,world
ReactJs下載下傳非常簡單,為了友善大家下載下傳,這裡再一次給出下載下傳位址http://facebook.github.io/react/downloads.html,下載下傳完成後,我麼看到的是一個壓縮包。解壓後,我們建立一個html檔案,引用react.js和JSXTransformer.js這兩個js檔案。html模闆如下(js路徑改成自己的):
這裡大家可能會奇怪,為什麼script的type是text/jsx,這是因為 React 獨有的 JSX 文法,跟 JavaScript 不相容。凡是使用 JSX 的地方,都要加上 type="text/jsx" 。 其次,React 提供兩個庫: react.js 和 JSXTransformer.js ,它們必須首先加載。其中,JSXTransformer.js 的作用是将 JSX 文法轉為 JavaScript 文法。這一步很消耗時間,實際上線的時候,應該将它放到伺服器完成。
到這裡我們就可以開始編寫代碼了,首先我們先來認識一下ReactJs裡面的React.render方法:
React.render 是 React 的最基本方法,用于将模闆轉為 HTML 語言,并插入指定的 DOM 節點。
下面我們在script标簽裡面編寫代碼,來輸出Hello,world,代碼如下:
這裡需要注意的是,react并不依賴jQuery,當然我們可以使用jQuery,但是render裡面第二個參數必須使用JavaScript原生的getElementByID方法,不能使用jQuery來選取DOM節點。
然後,在浏覽器打開這個頁面,就可以看到浏覽器顯示一個大大的Hello,world,因為我們用了<h1>标簽。
到這裡,恭喜,你已經步入了ReactJS的大門~~下面,讓我們來進一步學習ReactJs吧~~
三、Jsx文法
HTML 語言直接寫在 JavaScript 語言之中,不加任何引号,這就是 JSX 的文法,它允許 HTML 與 JavaScript 的混寫,了解過AngularJs的看到下面的代碼一定會感覺很熟悉的,我們來看代碼:
這裡我們聲明了一個names數組,然後周遊在前面加上Hello,輸出到DOM中,輸出結果如下:
JSX 允許直接在模闆插入 JavaScript 變量。如果這個變量是一個數組,則會展開這個數組的所有成員,代碼如下:
顯示結果如下:
這裡的星号隻是做辨別用的,大家不要被她迷惑了~~
你看到這裡,說明你對React還是蠻感興趣的,恭喜你,堅持下來了,那麼下面,我們開始學習React裡面的"真功夫"了~~ Are you ready?
四、ReactJS元件
1、元件屬性
前面說了,ReactJS是基于元件化的開發,下面我們開始來學習ReactJS裡面的元件,React 允許将代碼封裝成元件(component),然後像插入普通 HTML 标簽一樣,在網頁中插入這個元件。React.createClass 方法就用于生成一個元件類。
下面,我們來編寫第一個元件Greet,有一個name屬性,然後輸出hello + name的值,代碼如下:
看到這段代碼,接觸過AngularJS的朋友們是不是有一種熟悉的感覺,不過這裡有幾點需要注意:
1、擷取屬性的值用的是this.props.屬性名
2、建立的元件名稱首字母必須大寫。
3、為元素添加css的class時,要用className.
4、元件的style屬性的設定方式也值得注意,要寫成style={{width: this.state.witdh}}
2、元件狀态
元件免不了要與使用者互動,React 的一大創新,就是将元件看成是一個狀态機,一開始有一個初始狀态,然後使用者互動,導緻狀态變化,進而觸發重新渲染 UI 。下面我們來編寫一個小例子,一個文本框和一個button,通過點選button可以改變文本框的編輯狀态,禁止編輯和允許編輯。通過這個例子來了解ReactJS的狀态機制。先看代碼:
這裡,我們又使用到了一個方法getInitialState,這個函數在元件初始化的時候執行,必需傳回NULL或者一個對象。這裡我們可以通過this.state.屬性名來通路屬性值,這裡我們将enable這個值跟input的disabled綁定,當要修改這個屬性值時,要使用setState方法。我們聲明handleClick方法,來綁定到button上面,實作改變state.enable的值.效果如下:
原理分析:
當使用者點選元件,導緻狀态變化,this.setState 方法就修改狀态值,每次修改以後,自動調用 this.render 方法,再次渲染元件。
這裡值得注意的幾點如下:
1、getInitialState函數必須有傳回值,可以是NULL或者一個對象。
2、通路state的方法是this.state.屬性名。
3、變量用{}包裹,不需要再加雙引号。
3、元件的生命周期
元件的生命周期分成三個狀态:
Mounting:已插入真實 DOM
Updating:正在被重新渲染
Unmounting:已移出真實 DOM
React 為每個狀态都提供了兩種處理函數,will 函數在進入狀态之前調用,did 函數在進入狀态之後調用,三種狀态共計五種處理函數。
componentWillMount()
componentDidMount()
componentWillUpdate(object nextProps, object nextState)
componentDidUpdate(object prevProps, object prevState)
componentWillUnmount()
此外,React 還提供兩種特殊狀态的處理函數。
componentWillReceiveProps(object nextProps):已加載元件收到新的參數時調用
shouldComponentUpdate(object nextProps, object nextState):元件判斷是否重新渲染時調用
下面來看一個例子:
上面代碼在hello元件加載以後,通過 componentDidMount 方法設定一個定時器,每隔100毫秒,就重新設定元件的透明度,進而引發重新渲染。
4、元件的嵌套
React是基于元件化的開發,那麼元件化開發最大的優點是什麼?毫無疑問,當然是複用,下面我們來看看React中到底是如何實作元件的複用的,這裡我們還寫一個例子來說吧,代碼如下:
這裡我們建立了一個Search元件,然後又建立了一個Page元件,然後我們在Page元件中調用Search元件,并且調用了兩次,這裡我們通過屬性searchType傳入值,最終顯示結果如圖:
五、ReactJs小結
關于ReactJS今天就先學習到這裡了,下面來總結一下,主要有以下幾點:
1、ReactJs是基于元件化的開發,是以最終你的頁面應該是由若幹個小元件組成的大元件。
2、可以通過屬性,将值傳遞到元件内部,同理也可以通過屬性将内部的結果傳遞到父級元件(留給大家研究);要對某些值的變化做DOM操作的,要把這些值放到state中。
3、為元件添加外部css樣式時,類名應該寫成className而不是class;添加内部樣式時,應該是style={{opacity: this.state.opacity}}而不是style="opacity:{this.state.opacity};"。
4、元件名稱首字母必須大寫。
5、變量名用{}包裹,且不能加雙引号。