一看就懂的ReactJs入門教程-精華版

作者:雲(yún)霏霏
原文地址:http://www.cnblogs.com/yunfeifei/

現(xiàn)在最熱門的前端框架有AngularJS怀挠、React躬它、Bootstrap等组贺。自從接觸了ReactJS,ReactJs的虛擬DOM(Virtual DOM)和組件化的開發(fā)深深的吸引了我仪吧,下面來跟我一起領略ReactJs的風采吧~~ 文章有點長出皇,耐心讀完副渴,你會有很大收獲哦~

一斥滤、ReactJS簡介

React 起源于 Facebook 的內部項目将鸵,因為該公司對市場上所有 JavaScript MVC 框架,都不滿意佑颇,就決定自己寫一套顶掉,用來架設 Instagram 的網(wǎng)站。做出來以后挑胸,發(fā)現(xiàn)這套東西很好用痒筒,就在2013年5月開源了。由于 React 的設計思想極其獨特茬贵,屬于革命性創(chuàng)新簿透,性能出眾,代碼邏輯卻非常簡單解藻。所以老充,越來越多的人開始關注和使用,認為它可能是將來 Web 開發(fā)的主流工具螟左。

ReactJS官網(wǎng)地址: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操作通常是性能瓶頸產(chǎn)生的原因(如何進行高性能的復雜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ā)難度降低,可能產(chǎn)生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下載非常簡單佳窑,為了方便大家下載制恍,這里再一次給出下載地址,下載完成后神凑,我么看到的是一個壓縮包净神。解壓后,我們新建一個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.jsJSXTransformer.js,它們必須首先加載熄求。其中渣玲,JSXTransformer.js的作用是將 JSX 語法轉為 JavaScript 語法。這一步很消耗時間弟晚,實際上線的時候忘衍,應該將它放到服務器完成。

到這里我們就可以開始編寫代碼了卿城,首先我們先來認識一下ReactJs里面的React.render方法:

React.render是 React 的最基本方法枚钓,用于將模板轉為 HTML 語言,并插入指定的 DOM 節(jié)點瑟押。

下面我們在script標簽里面編寫代碼搀捷,來輸出Hello,world多望,代碼如下:

React.render(
        <h1>Hello, world!</h1>,
        document.getElementById('container')
      );

這里需要注意的是指煎,react并不依賴jQuery,當然我們可以使用jQuery便斥,但是render里面第二個參數(shù)必須使用JavaScript原生的getElementByID方法威始,不能使用jQuery來選取DOM節(jié)點枢纠。

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

到這里,恭喜沸停,你已經(jīng)步入了ReactJS的大門~下面能颁,讓我們來進一步學習ReactJs吧

三占业、Jsx語法

HTML 語言直接寫在 JavaScript 語言之中南蹂,不加任何引號六剥,這就是 JSX 的語法,它允許 HTML 與 JavaScript 的混寫峰伙,了解過AngularJs的看到下面的代碼一定會感覺很熟悉的疗疟,我們來看代碼:

var names = ['Jack', 'Tom', 'Alice'];

      React.render(
        <div>
        {
          names.map(function (name) {
            return <div>Hello, {name}!</div>
          })
        }
        </div>,
        document.getElementById('container')
      );

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

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

var arr = [
        <h1>Hello world!</h1>,
        <h2>React is perfect!</h2>,
      ];
      React.render(
        <div>*{arr}*</div>,
        document.getElementById('container')
      );

顯示結果如下:

這里的星號只是做標識用的店诗,大家不要被她迷惑了。

你看到這里音榜,說明你對React還是蠻感興趣的庞瘸,恭喜你,堅持下來了赠叼,那么下面擦囊,我們開始學習React里面的"真功夫"了~~ Are you ready?

四、ReactJS組件

1嘴办、組件屬性

前面說了霜第,ReactJS是基于組件化的開發(fā),下面我們開始來學習ReactJS里面的組件户辞,React 允許將代碼封裝成組件(component)泌类,然后像插入普通 HTML 標簽一樣,在網(wǎng)頁中插入這個組件。React.createClass方法就用于生成一個組件類刃榨。

下面弹砚,我們來編寫第一個組件Greet,有一個name屬性枢希,然后輸出hello + name的值桌吃,代碼如下:

var Greet = React.createClass({
        render: function() {
          return <h1>Hello {this.props.name}</h1>;
        }
      });

      React.render(
        <Greet name="Jack" />,
        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)機制。先看代碼:

var InputState = React.createClass({
        getInitialState: function() {
          return {enable: false};
        },
        handleClick: function(event) {
          this.setState({enable: !this.state.enable});
        },
        render: function() {
          
          return (
            <p>
               <input type="text" disabled={this.state.enable} />
               <button onClick={this.handleClick}>Change State</button>
            </p>
          );
        }
      });

      React.render(
        <InputState />,
        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, objectnextState):組件判斷是否重新渲染時調用茂腥。

下面來看一個例子:

var Hello = React.createClass({
        getInitialState: function () {
          return {
            opacity: 1.0
          };
        },

        componentDidMount: function () {
          this.timer = setInterval(function () {
            var opacity = this.state.opacity;
            opacity -= .05;
            if (opacity < 0.1) {
              opacity = 1.0;
            }
            this.setState({
              opacity: opacity
            });
          }.bind(this), 100);
        },

        render: function () {
          return (
            <div style={{opacity: this.state.opacity}}>
              Hello {this.props.name}
            </div>
          );
        }
      });

      React.render(
        <Hello name="world"/>,
        document.body
      );

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

4般渡、組件的嵌套

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

var Search = React.createClass({
        render: function() {
          return (
            <div>
               {this.props.searchType}:<input type="text" />
               <button>Search</button>
            </div>
          );
        }
      });
      var Page = React.createClass({
        render: function() {
          return (
            <div>
               <h1>Welcome!</h1>
               <Search searchType="Title" />
               <Search  searchType="Content" />
            </div>
          );
        }
      });
      React.render(
        <Page />,
        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. 變量名用{}包裹,且不能加雙引號街夭。

六砰碴、參考資料

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市板丽,隨后出現(xiàn)的幾起案子呈枉,更是在濱河造成了極大的恐慌,老刑警劉巖埃碱,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件猖辫,死亡現(xiàn)場離奇詭異,居然都是意外死亡砚殿,警方通過查閱死者的電腦和手機啃憎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來似炎,“玉大人辛萍,你說我怎么就攤上這事∠勖辏” “怎么了贩毕?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長仆嗦。 經(jīng)常有香客問我辉阶,道長,這世上最難降的妖魔是什么欧啤? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮启上,結果婚禮上邢隧,老公的妹妹穿的比我還像新娘。我一直安慰自己冈在,他們只是感情好倒慧,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般纫谅。 火紅的嫁衣襯著肌膚如雪炫贤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天付秕,我揣著相機與錄音兰珍,去河邊找鬼。 笑死询吴,一個胖子當著我的面吹牛掠河,可吹牛的內容都是我干的。 我是一名探鬼主播猛计,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼唠摹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了奉瘤?” 一聲冷哼從身側響起勾拉,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盗温,沒想到半個月后藕赞,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡肌访,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年找默,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吼驶。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡惩激,死狀恐怖,靈堂內的尸體忽然破棺而出蟹演,到底是詐尸還是另有隱情风钻,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布酒请,位于F島的核電站骡技,受9級特大地震影響,放射性物質發(fā)生泄漏羞反。R本人自食惡果不足惜布朦,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦宋梧、人聲如沸介牙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蒲犬。三九已至陨收,卻和暖如春肛搬,著一層夾襖步出監(jiān)牢的瞬間没佑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工温赔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蛤奢,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓让腹,卻偏偏與公主長得像远剩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子骇窍,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內容