react初學者必讀

現(xiàn)在最熱門的前端框架有AngularJS甚侣、React、Bootstrap等间学。自從接觸了ReactJS渺绒,ReactJs的虛擬DOM(Virtual?DOM)和組件化的開發(fā)深深的吸引了我,下面來跟我一起領略ReactJs的風采吧~~ 文章有點長菱鸥,耐心讀完宗兼,你會有很大收獲哦~

?一、ReactJS簡介

  React 起源于 Facebook 的內部項目氮采,因為該公司對市場上所有 JavaScript MVC 框架壹无,都不滿意,就決定自己寫一套拓哟,用來架設 Instagram 的網站浙滤。做出來以后,發(fā)現(xiàn)這套東西很好用躯概,就在2013年5月開源了登钥。由于?React?的設計思想極其獨特,屬于革命性創(chuàng)新娶靡,性能出眾牧牢,代碼邏輯卻非常簡單。所以,越來越多的人開始關注和使用塔鳍,認為它可能是將來?Web?開發(fā)的主流工具伯铣。

ReactJS官網地址:http://facebook.github.io/react/

Github地址:https://github.com/facebook/react


?二、對ReactJS的認識及ReactJS的優(yōu)點

?首先轮纫,對于React腔寡,有一些認識誤區(qū),這里先總結一下:

React不是一個完整的MVC框架掌唾,最多可以認為是MVC中的V(View)放前,甚至React并不非常認可MVC開發(fā)模式;

React的服務器端Render能力只能算是一個錦上添花的功能糯彬,并不是其核心出發(fā)點犀斋,事實上React官方站點幾乎沒有提及其在服務器端的應用;

有人拿React和Web?Component相提并論情连,但兩者并不是完全的競爭關系叽粹,你完全可以用React去開發(fā)一個真正的Web?Component;

React不是一個新的模板語言却舀,JSX只是一個表象虫几,沒有JSX的React也能工作。

1挽拔、ReactJS的背景和原理

在Web開發(fā)中辆脸,我們總需要將變化的數(shù)據(jù)實時反應到UI上,這時就需要對DOM進行操作螃诅。而復雜或頻繁的DOM操作通常是性能瓶頸產生的原因(如何進行高性能的復雜DOM操作通常是衡量一個前端開發(fā)人員技能的重要指標)啡氢。React為此引入了虛擬DOM(Virtual DOM)的機制:在瀏覽器端用Javascript實現(xiàn)了一套DOM API∈趼悖基于React進行開發(fā)時所有的DOM構造都是通過虛擬DOM進行倘是,每當數(shù)據(jù)變化時,React都會重新構建整個DOM樹袭艺,然后React將當前整個DOM樹和上一次的DOM樹進行對比搀崭,得到DOM結構的區(qū)別,然后僅僅將需要變化的部分進行實際的瀏覽器DOM更新猾编。而且React能夠批處理虛擬DOM的刷新瘤睹,在一個事件循環(huán)(Event Loop)內的兩次數(shù)據(jù)變化會被合并,例如你連續(xù)的先將節(jié)點內容從A變成B答倡,然后又從B變成A轰传,React會認為UI不發(fā)生任何變化,而如果通過手動控制瘪撇,這種邏輯通常是極其復雜的获茬。盡管每一次都需要構造完整的虛擬DOM樹港庄,但是因為虛擬DOM是內存數(shù)據(jù),性能是極高的锦茁,而對實際DOM進行操作的僅僅是Diff部分攘轩,因而能達到提高性能的目的叉存。這樣码俩,在保證性能的同時,開發(fā)者將不再需要關注某個數(shù)據(jù)的變化如何更新到一個或多個具體的DOM元素歼捏,而只需要關心在任意一個數(shù)據(jù)狀態(tài)下稿存,整個界面是如何Render的。

如果你像在90年代那樣寫過服務器端Render的純Web頁面那么應該知道瞳秽,服務器端所要做的就是根據(jù)數(shù)據(jù)Render出HTML送到瀏覽器端瓣履。如果這時因為用戶的一個點擊需要改變某個狀態(tài)文字,那么也是通過刷新整個頁面來完成的练俐。服務器端并不需要知道是哪一小段HTML發(fā)生了變化袖迎,而只需要根據(jù)數(shù)據(jù)刷新整個頁面。換句話說腺晾,任何UI的變化都是通過整體刷新來完成的燕锥。而React將這種開發(fā)模式以高性能的方式帶到了前端,每做一點界面的更新悯蝉,你都可以認為刷新了整個頁面归形。至于如何進行局部更新以保證性能,則是React框架要完成的事情鼻由。

  借用Facebook介紹React的視頻中聊天應用的例子暇榴,當一條新的消息過來時,傳統(tǒng)開發(fā)的思路如上圖蕉世,你的開發(fā)過程需要知道哪條數(shù)據(jù)過來了蔼紧,如何將新的DOM結點添加到當前DOM樹上;而基于React的開發(fā)思路如下圖狠轻,你永遠只需要關心數(shù)據(jù)整體歉井,兩次數(shù)據(jù)之間的UI如何變化,則完全交給框架去做哈误×ㄖ粒可以看到,使用React大大降低了邏輯復雜性蜜自,意味著開發(fā)難度降低菩貌,可能產生Bug的機會也更少。


2重荠、組件化

  虛擬DOM(virtual-dom)不僅帶來了簡單的UI開發(fā)邏輯箭阶,同時也帶來了組件化開發(fā)的思想,所謂組件,即封裝起來的具有獨立功能的UI部件仇参。React推薦以組件的方式去重新思考UI構成嘹叫,將UI上每一個功能相對獨立的模塊定義成組件,然后將小的組件通過組合或者嵌套的方式構成大的組件诈乒,最終完成整體UI的構建罩扇。例如,F(xiàn)acebook的instagram.com整站都采用了React來開發(fā)怕磨,整個頁面就是一個大的組件喂饥,其中包含了嵌套的大量其它組件,大家有興趣可以看下它背后的代碼肠鲫。

如果說MVC的思想讓你做到視圖-數(shù)據(jù)-控制器的分離员帮,那么組件化的思考方式則是帶來了UI功能模塊之間的分離。我們通過一個典型的Blog評論界面來看MVC和組件化開發(fā)思路的區(qū)別导饲。

對于MVC開發(fā)模式來說捞高,開發(fā)者將三者定義成不同的類,實現(xiàn)了表現(xiàn)渣锦,數(shù)據(jù)硝岗,控制的分離。開發(fā)者更多的是從技術的角度來對UI進行拆分泡挺,實現(xiàn)松耦合辈讶。

對于React而言,則完全是一個新的思路娄猫,開發(fā)者從功能的角度出發(fā)贱除,將UI分成不同的組件,每個組件都獨立封裝媳溺。

在React中月幌,你按照界面模塊自然劃分的方式來組織和編寫你的代碼,對于評論界面而言悬蔽,整個UI是一個通過小組件構成的大組件扯躺,每個組件只關心自己部分的邏輯,彼此獨立蝎困。

React認為一個組件應該具有如下特征:

(1)可組合(Composeable):一個組件易于和其它組件一起使用录语,或者嵌套在另一個組件內部。如果一個組件內部創(chuàng)建了另一個組件禾乘,那么說父組件擁有(own)它創(chuàng)建的子組件澎埠,通過這個特性,一個復雜的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路徑改成自己的):

<!DOCTYPE html><html><head><script src="build/react.js"></script><script src="build/JSXTransformer.js"></script></head><body><div id="container"></div><script type="text/jsx">// ** Our code goes here! **</script></body></html>

這里大家可能會奇怪缤至,為什么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 節(jié)點捧搞。

下面我們在script標簽里面編寫代碼,來輸出Hello狮荔,world胎撇,代碼如下:

React.render(

? ? ? ?

Hello, world!

,? ? ? ? document.getElementById('container')

? ? ? );

這里需要注意的是,react并不依賴jQuery殖氏,當然我們可以使用jQuery晚树,但是render里面第二個參數(shù)必須使用JavaScript原生的getElementByID方法,不能使用jQuery來選取DOM節(jié)點受葛。

?然后题涨,在瀏覽器打開這個頁面偎谁,就可以看到瀏覽器顯示一個大大的Hello,world,因為我們用了<h1>標簽纲堵。

到這里巡雨,恭喜,你已經步入了ReactJS的大門~~下面席函,讓我們來進一步學習ReactJs吧~~


?三铐望、Jsx語法

?  HTML 語言直接寫在 JavaScript 語言之中,不加任何引號茂附,這就是 JSX 的語法正蛙,它允許 HTML 與 JavaScript 的混寫,了解過AngularJs的看到下面的代碼一定會感覺很熟悉的营曼,我們來看代碼:

varnames = ['Jack', 'Tom', 'Alice'];

? ? ? React.render(

? ? ? ?

? ? ? ? {

? ? ? ? ? names.map(function (name) {

? ? ? ? ? ? return

Hello, {name}!
? ? ? ? ? })

? ? ? ? }

? ? ? ? ,? ? ? ? document.getElementById('container')

? ? ? );

這里我們聲明了一個names數(shù)組乒验,然后遍歷在前面加上Hello,輸出到DOM中,輸出結果如下:

JSX 允許直接在模板插入 JavaScript 變量蒂阱。如果這個變量是一個數(shù)組锻全,則會展開這個數(shù)組的所有成員,代碼如下:

vararr = [

? ? ? ?

Hello world!

,? ? ? ?

React is perfect!

,? ? ? ];

? ? ? React.render(

? ? ? ?

*{arr}*
,? ? ? ? document.getElementById('container')

? ? ? );

顯示結果如下:

這里的星號只是做標識用的录煤,大家不要被她迷惑了~~

?你看到這里鳄厌,說明你對React還是蠻感興趣的,恭喜你妈踊,堅持下來了了嚎,那么下面,我們開始學習React里面的"真功夫"了~~ Are you ready?


?四廊营、ReactJS組件

1歪泳、組件屬性?

  前面說了,ReactJS是基于組件化的開發(fā)赘风,下面我們開始來學習ReactJS里面的組件夹囚,React?允許將代碼封裝成組件(component),然后像插入普通?HTML?標簽一樣邀窃,在網頁中插入這個組件荸哟。React.createClass?方法就用于生成一個組件類。

下面瞬捕,我們來編寫第一個組件Greet鞍历,有一個name屬性,然后輸出hello + name的值肪虎,代碼如下:

varGreet = React.createClass({

? ? ? ? render: function() {

? ? ? ? ? return

Hello {this.props.name}

;? ? ? ? }

? ? ? });

? ? ? React.render(

? ? ? ? ,? ? ? ? document.getElementById('container')

? ? ? );

看到這段代碼劣砍,接觸過AngularJS的朋友們是不是有一種熟悉的感覺,不過這里有幾點需要注意:

1扇救、獲取屬性的值用的是this.props.屬性名

  2刑枝、創(chuàng)建的組件名稱首字母必須大寫香嗓。

3、為元素添加css的class時装畅,要用className.

  4靠娱、組件的style屬性的設置方式也值得注意,要寫成style={{width: this.state.witdh}}


2掠兄、組件狀態(tài)

  組件免不了要與用戶互動像云,React 的一大創(chuàng)新,就是將組件看成是一個狀態(tài)機蚂夕,一開始有一個初始狀態(tài)迅诬,然后用戶互動,導致狀態(tài)變化婿牍,從而觸發(fā)重新渲染 UI 侈贷。下面我們來編寫一個小例子,一個文本框和一個button牍汹,通過點擊button可以改變文本框的編輯狀態(tài)铐维,禁止編輯和允許編輯柬泽。通過這個例子來理解ReactJS的狀態(tài)機制慎菲。先看代碼:

varInputState = React.createClass({

? ? ? ? getInitialState: function() {

? ? ? ? ? return{enable:false};

? ? ? ? },

? ? ? ? handleClick: function(event) {

? ? ? ? ? this.setState({enable: !this.state.enable});

? ? ? ? },

? ? ? ? render: function() {


? ? ? ? ? return (

? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? ? ? Change State? ? ? ? ? ?

? ? ? ? ? );

? ? ? ? }

? ? ? });

? ? ? React.render(

? ? ? ? ,? ? ? ? document.getElementById('container')

? ? ? );

這里,我們又使用到了一個方法getInitialState,這個函數(shù)在組件初始化的時候執(zhí)行锨并,必需返回NULL或者一個對象露该。這里我們可以通過this.state.屬性名來訪問屬性值,這里我們將enable這個值跟input的disabled綁定第煮,當要修改這個屬性值時解幼,要使用setState方法。我們聲明handleClick方法包警,來綁定到button上面撵摆,實現(xiàn)改變state.enable的值.效果如下:

原理分析:

當用戶點擊組件,導致狀態(tài)變化害晦,this.setState 方法就修改狀態(tài)值特铝,每次修改以后,自動調用 this.render 方法壹瘟,再次渲染組件鲫剿。

這里值得注意的幾點如下:

1、getInitialState函數(shù)必須有返回值稻轨,可以是NULL或者一個對象灵莲。

  2、訪問state的方法是this.state.屬性名殴俱。

  3政冻、變量用{}包裹枚抵,不需要再加雙引號。


3明场、組件的生命周期  

組件的生命周期分成三個狀態(tài):

Mounting:已插入真實?DOM

Updating:正在被重新渲染

Unmounting:已移出真實 DOM

React?為每個狀態(tài)都提供了兩種處理函數(shù)俄精,will?函數(shù)在進入狀態(tài)之前調用,did?函數(shù)在進入狀態(tài)之后調用榕堰,三種狀態(tài)共計五種處理函數(shù)竖慧。

componentWillMount()

componentDidMount()

componentWillUpdate(object?nextProps,?object?nextState)

componentDidUpdate(object prevProps, object prevState)

componentWillUnmount()

此外,React 還提供兩種特殊狀態(tài)的處理函數(shù)逆屡。

componentWillReceiveProps(object nextProps):已加載組件收到新的參數(shù)時調用

shouldComponentUpdate(object nextProps, object nextState):組件判斷是否重新渲染時調用


下面來看一個例子:

varHello = React.createClass({

? ? ? ? getInitialState: function () {

? ? ? ? ? return {

? ? ? ? ? ? opacity: 1.0? ? ? ? ? };

? ? ? ? },

? ? ? ? componentDidMount: function () {

? ? ? ? ? this.timer = setInterval(function () {

? ? ? ? ? ? varopacity =this.state.opacity;

? ? ? ? ? ? opacity -= .05;

? ? ? ? ? ? if(opacity < 0.1) {

? ? ? ? ? ? ? opacity = 1.0;

? ? ? ? ? ? }

? ? ? ? ? ? this.setState({

? ? ? ? ? ? ? opacity: opacity

? ? ? ? ? ? });

? ? ? ? ? }.bind(this), 100);

? ? ? ? },

? ? ? ? render: function () {

? ? ? ? ? return (

? ? ? ? ? ?

? ? ? ? ? ? ? Hello {this.props.name}

? ? ? ? ? ? ? ? ? ? ? );

? ? ? ? }

? ? ? });

? ? ? React.render(

? ? ? ? ,? ? ? ? document.body

? ? ? );

上面代碼在hello組件加載以后圾旨,通過 componentDidMount 方法設置一個定時器,每隔100毫秒魏蔗,就重新設置組件的透明度砍的,從而引發(fā)重新渲染。


4莺治、組件的嵌套

  React是基于組件化的開發(fā)廓鞠,那么組件化開發(fā)最大的優(yōu)點是什么?毫無疑問谣旁,當然是復用床佳,下面我們來看看React中到底是如何實現(xiàn)組件的復用的,這里我們還寫一個例子來說吧榄审,代碼如下:

varSearch = React.createClass({

? ? ? ? render: function() {

? ? ? ? ? return (

? ? ? ? ? ?

? ? ? ? ? ? ? {this.props.searchType}:? ? ? ? ? ? ? Search? ? ? ? ? ?
? ? ? ? ? );

? ? ? ? }

? ? ? });

? ? ? varPage = React.createClass({

? ? ? ? render: function() {

? ? ? ? ? return (

? ? ? ? ? ?

? ? ? ? ? ? ?

Welcome!

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? );

? ? ? ? }

? ? ? });

? ? ? React.render(

? ? ? ? ,? ? ? ? document.getElementById('container')

? ? ? );

這里我們創(chuàng)建了一個Search組件砌们,然后又創(chuàng)建了一個Page組件,然后我們在Page組件中調用Search組件搁进,并且調用了兩次浪感,這里我們通過屬性searchType傳入值,最終顯示結果如圖:


?五饼问、ReactJs小結

關于ReactJS今天就先學習到這里了影兽,下面來總結一下,主要有以下幾點:

  1莱革、ReactJs是基于組件化的開發(fā)峻堰,所以最終你的頁面應該是由若干個小組件組成的大組件。

  2驮吱、可以通過屬性茧妒,將值傳遞到組件內部,同理也可以通過屬性將內部的結果傳遞到父級組件(留給大家研究)左冬;要對某些值的變化做DOM操作的桐筏,要把這些值放到state中。

  3拇砰、為組件添加外部css樣式時梅忌,類名應該寫成className而不是class;添加內部樣式時狰腌,應該是style={{opacity: this.state.opacity}}而不是style="opacity:{this.state.opacity};"。

  4牧氮、組件名稱首字母必須大寫琼腔。

  5、變量名用{}包裹踱葛,且不能加雙引號丹莲。


?六、參考資料

React中文文檔 ?http://reactjs.cn/

React 入門實例教程 ? ?http://www.ruanyifeng.com/blog/2015/03/react.html

顛覆式前端UI開發(fā)框架:React ??http://www.infoq.com/cn/articles/subversion-front-end-ui-development-framework-react

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末尸诽,一起剝皮案震驚了整個濱河市甥材,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌性含,老刑警劉巖洲赵,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異商蕴,居然都是意外死亡叠萍,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門绪商,熙熙樓的掌柜王于貴愁眉苦臉地迎上來苛谷,“玉大人,你說我怎么就攤上這事部宿〕唬” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵理张,是天一觀的道長。 經常有香客問我绵患,道長雾叭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任落蝙,我火速辦了婚禮织狐,結果婚禮上,老公的妹妹穿的比我還像新娘筏勒。我一直安慰自己移迫,他們只是感情好,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布管行。 她就那樣靜靜地躺著厨埋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪捐顷。 梳的紋絲不亂的頭發(fā)上荡陷,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天雨效,我揣著相機與錄音,去河邊找鬼废赞。 笑死徽龟,一個胖子當著我的面吹牛,可吹牛的內容都是我干的唉地。 我是一名探鬼主播据悔,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼耘沼!你這毒婦竟也來了屠尊?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤耕拷,失蹤者是張志新(化名)和其女友劉穎讼昆,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體骚烧,經...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡浸赫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了赃绊。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片既峡。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖碧查,靈堂內的尸體忽然破棺而出运敢,到底是詐尸還是另有隱情,我是刑警寧澤忠售,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布传惠,位于F島的核電站,受9級特大地震影響稻扬,放射性物質發(fā)生泄漏卦方。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一泰佳、第九天 我趴在偏房一處隱蔽的房頂上張望盼砍。 院中可真熱鬧,春花似錦逝她、人聲如沸浇坐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽近刘。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間跌宛,已是汗流浹背酗宋。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留疆拘,地道東北人蜕猫。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像哎迄,于是被迫代替她去往敵國和親回右。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內容