React 精簡快速入門

React.png

React是一個用于構(gòu)建用戶界面的Javascript庫
和龐大的AngularJS不同咧擂,React專注于MVC架構(gòu)中的V,即視圖
reACT 重新造了個輪子: JSX
React引入了 虛擬DOM的概念
開發(fā)者操作虛擬DOM灯变,React在必要的時候?qū)⑺鼈冧秩镜秸嬲?DOM上
虛擬DOM是React的基石

在React中炫刷,應(yīng)用程序在虛擬DOM上操作淹魄, React在每次需要渲染時利赋,會先比較當(dāng)前DOM內(nèi)容和待渲染內(nèi)容的差異水评, 然后再決定如何最優(yōu)地更新DOM。

除了性能的考慮媚送,React引入虛擬DOM更重要的意義是提供了一種一致的開發(fā)方 式來開發(fā)服務(wù)端應(yīng)用中燥、Web應(yīng)用和手機(jī)端應(yīng)用:

因為有了虛擬DOM這一層,所以通過配備不同的渲染器塘偎,就可以將虛擬DOM的內(nèi)容 渲染到不同的平臺疗涉。而應(yīng)用開發(fā)者,使用JavaScript就可以通吃各個平臺了式塌。

相當(dāng)棒的思路博敬!

  • createElement(type,[props],[children...]) - 在虛擬DOM上創(chuàng)建指定的React元素

參數(shù)type用來指定要創(chuàng)建的元素類型,可以是一個字符串或一個React組件類型峰尝。當(dāng)使用 字符串時,這個參數(shù)應(yīng)當(dāng)是標(biāo)準(zhǔn)的HTML標(biāo)簽名稱收恢,比如:p武学、div、canvas等等伦意。

參數(shù)props是可選的JSON對象火窒,用來指定元素的附加屬性,比如樣式驮肉、CSS類等等熏矿。 我們在示例中簡單的設(shè)置為null。

從第三個參數(shù)children開始的所有參數(shù),都被認(rèn)為是這個元素的子元素票编⊥蚀ⅲ考慮到 虛擬DOM好歹也是DOM,容易理解React需要通過這些子元素參數(shù)慧域,讓我們可以構(gòu)造虛擬DOM樹:

var el = React.createElement(
"ul",
 null,
React.createElement("li",null,"China"),
React.createElement("li",null,"Japan"),
React.createElement("li",null,"Korea")
);

上面的例子在虛擬DOM中創(chuàng)建了一個具有三個li子元素的ul元素鲤竹,看起來有點累。不過 想想昔榴,造一個輪子辛藻,總會付出一些代價的。

在示例中互订,我們簡單地傳入了一個文本子元素作為p元素的內(nèi)容吱肌。

  • render(element,container,[callback]) - 將虛擬DOM上的對象渲染到真實DOM上

參數(shù)element是我們使用createElement()方法創(chuàng)建的React元素,注意仰禽,不是HTML元素岩榆!

參數(shù)container是真實DOM中的HTML元素,作為渲染的目標(biāo)容器坟瓢,它的內(nèi)容將被render()方法 的執(zhí)行改變勇边。

callback參數(shù)是可選的函數(shù),當(dāng)渲染完成或更新后被執(zhí)行折联,通常我們不用它粒褒。

React組件

在React中定義一個組件也是相當(dāng)?shù)娜菀祝M件就是一個 實現(xiàn)預(yù)定義接口的JavaScript類:

  • React.createClass(meta)

參數(shù)meta是一個實現(xiàn)預(yù)定義接口的JavaScript對象诚镰,用來 對React組件原型進(jìn)行擴(kuò)展奕坟。

在meta中,至少需要實現(xiàn)一個render()方法清笨,而這個方法月杉, 必須而且只能返回一個有效的React元素。

這意味著抠艾,如果你的組件是由多個元素構(gòu)成的苛萎,那么你必須在外邊包一個頂層 元素,然后返回這個頂層元素检号。比如我們創(chuàng)建一個布局組件:

 render:function(){
 return React.createElement(
   "div",null,
React.createElement("div",null,"header"),
React.createElement("div",null,"content"),
React.createElement("div",null,"footer")
 );

}

注意 :你的React組件名稱的首字母應(yīng)當(dāng)大寫腌歉, 關(guān)于大小寫的差異你會在后面發(fā)現(xiàn)。

在示例代碼中齐苛,我們實現(xiàn)了一個液晶顯示組件EzLedComp(為了更逼真一些翘盖, 定義了簡單的樣式,別忘了翻看一下)凹蜂,你應(yīng)該會注意到div元素的樣式類是用 className而不是class聲明的馍驯,這是因為class 是JavaScript的保留字阁危,渲染后,真實的DOM還會是:

<div class="ez-led">Hello, React!</div>

組件定義以后汰瘫,和標(biāo)準(zhǔn)HTML標(biāo)簽一樣狂打,可以使用createElement()方法 創(chuàng)建元素,只是這時吟吝,第一個參數(shù)是我們定義的組件類菱父,而不是標(biāo)簽名字符串:

  • React.createElement(EzLedComp);

修改示例代碼,定義一個兩排字的液晶顯示組件

輪子來了:JSX == javascript + XML

<script src="lib/react.min.js"></script>

<script src="lib/JSXTransformer.js"></script>

                //JSX-->
                <div>
                    <div className="ez-led">Hello, React!</div>
                    <div className="ez-led">2015-04-15</div>
                </div>;
                //<--JSX
  • 指定腳本類型

在html文件中引入的JSX腳本剑逃,需要指定類型為text/jsx:

  • //內(nèi)聯(lián)腳本
  • <script type="text/jsx">...</script>
  • //外部腳本
  • <script src="a.js" type="text/jsx"></script>
  • 引入JSX語法轉(zhuǎn)換庫

在html中使用JSX浙宜,還需要引入JSX語法轉(zhuǎn)換庫JSXTransform.js。 這個庫加載后蛹磺,將在DOM樹構(gòu)造完成后(通過監(jiān)聽DOMContentLoaded事件)處理 JSX腳本:

    1. 搜索DOM樹中的script節(jié)點粟瞬,如果其類型為text/jsx則進(jìn)行后續(xù)處理
    1. 讀取script節(jié)點的內(nèi)容,將其轉(zhuǎn)化為JavaScript代碼
    1. 構(gòu)造一個新的script元素萤捆,設(shè)置其內(nèi)容為轉(zhuǎn)化結(jié)果代碼,并追加到DOM樹head元素中

JSXTransform.js引入后通過全局對象JSXTransformer提供了API接口俗或, 我們可以使用transform()方法來模擬這個語法自動轉(zhuǎn)換的過程市怎。

在右邊的示例代碼中,為了避免自動轉(zhuǎn)換辛慰,我們將script元素的類型設(shè)置為text/jsx2区匠, 同時為了簡化DOM元素定位,給它加了一個id帅腌。

屬性 : props
三種寫法

//定義React組件
var EzLampComp = React.createClass({
render : function(){
//取得屬性值
var onoff = this.props.onoff;

            //返回React元素
            if(onoff == "on")
                return <span className = "ez-lamp on"></span>;  //JSX
            else
                return <span className = "ez-lamp off"></span>;  //JSX
        }
    });
    //渲染React元素
  1. 屬性
    React.render(
    < EzLampComp onoff="off" /> ,
    document.querySelector("#content"));

  2.  var myOnoff = "on";
     React.render(
     < EzLampComp onoff={myOnoff} />,
     document.querySelector("#content"));
    
  3.   varmyOnoff="on";
      React.render(
      React.createElement(
      EzLampComp,
      {
      onoff : myOnoff
      }),
      document.querySelector("#content"));
    

內(nèi)聯(lián)樣式

在前面的示例中驰弄,每當(dāng)需要設(shè)定元素的樣式,我們總是使用樣式類速客。但有時我們的確需要 直接在元素上聲明內(nèi)聯(lián)樣式戚篙,就像在HTML中一樣:

  • //HTML
    <div style="width:200px;height:200px;"></div>

在React元素中聲明樣式,需要給出一個JSON對象溺职,其字段對應(yīng)樣式名稱岔擂,比如要渲染出 上面的HTML片段,需要這樣:

    var myStyle = {
     width:"200px",
    height:"200px"
    };
  • //JSX
    var e = <div style={myStyle} />;

  • //JavaScript
    var e = React.createElement(
    "div",{
    style : myStyle
    });

  • //render
    React.render(e,...);

  • 注意1 - 對應(yīng)樣式名稱的字段辅愿,需要使用駝峰式命名

比如:border-radius樣式需要使用borderRadius來訪問智亮,而background-image 樣式需要使用backgroundImage來訪問。

  • 注意2 - 樣式名稱中的供應(yīng)商前綴点待,除ms外都需要大寫首字母

對于供應(yīng)商前綴(-webkit, -moz, -o, -ms),除了ms弃舒,其他都需要將首字母大寫癞埠。 比如:-webkit-transition應(yīng)當(dāng)通過WebkitTransition來訪問状原,然而-ms-transition 則需要通過msTransition來訪問。

狀態(tài)記憶 : state

很多情況下苗踪,組件實例的外觀及行為通過使用props變量進(jìn)行定制就可以了颠区。 這樣的組件我們稱之為無狀態(tài)/stateless的組件,因為在任何時刻通铲,組件 實例的表現(xiàn)都僅僅取決于外部傳入的props屬性毕莱,與 它自身之前的表現(xiàn)毫無關(guān)系,即颅夺,它本身沒有任何記憶朋截。

讓一個組件擁有記憶能力,意味著它不僅能對外界的刺激產(chǎn)生反應(yīng)(通過props 傳入的數(shù)據(jù)吧黄、或用戶的交互事件)部服,也能根據(jù)自身的狀態(tài)對同樣的刺激做出 不同的反應(yīng)。

比如示例中的切換開關(guān)拗慨,它可以響應(yīng)用戶的點擊事件赵抢,如果當(dāng)前狀態(tài)是關(guān),那么它就 切換到開的狀態(tài)(顯示開狀態(tài)的圖片)宠叼;而如果當(dāng)前狀態(tài)是開车吹,那么它就切換到關(guān)的 狀態(tài)(顯示關(guān)狀態(tài)的圖片):

現(xiàn)在思考一下窄驹,使用props可以實現(xiàn)這個切換開關(guān)嗎证逻?

React的組件的確引入了狀態(tài)機(jī)的概念囚企,通過將組件劃分為不同的狀態(tài)龙宏,使組件具有 了一定的記憶能力:

  • state - 組件的狀態(tài)變量

每個React組件實例都有一個state變量,用來保存組件的當(dāng)前狀態(tài)辆影⊥芗ィ可以在 任何時刻使用this.state讀取當(dāng)前狀態(tài)。

  • getInitialState() - 設(shè)置組件初始狀態(tài)

組件的實現(xiàn)者應(yīng)當(dāng)實現(xiàn)一個getInitialState()方法來設(shè)置組件的初始狀態(tài)旁涤。getInitialState()方法必須返回一個JSON對象或空值null劈愚, 這意味著即使你只需要一個簡單的標(biāo)志作為狀態(tài)造虎,比如true或false纷闺,也要把它放到JSON對象里犁功。

  • setState(currentState) - 設(shè)置組件當(dāng)前狀態(tài)

盡管可以使用this.state來直接設(shè)置組件當(dāng)前狀態(tài),但React要求我們使用setState()方法來進(jìn)行狀態(tài)設(shè)置署鸡。這是因為靴庆,setState()方法會自動 地重新渲染組件炉抒,而這通常是我們所期望的焰薄。

參數(shù)currentState是一個JSON對象塞茅,不必包含狀態(tài)變量的所有字段季率,setState()方法會 將這個參數(shù)值與當(dāng)前狀態(tài)this.sate進(jìn)行合并飒泻,結(jié)果作為狀態(tài)變量的新值蠢络。

生命周期

在組件實例的整個周期中,React將在特定的時間點調(diào)用以下方法:

  • componentWillMount() - 組件實例即將掛接(初次渲染)時被調(diào)用

這個方法在整個生命周期中只會被調(diào)用一次啡省。

  • componentDidMount() - 組件實例掛接(初次渲染)后被調(diào)用

這個方法在整個生命周期中只會被調(diào)用一次卦睹。

  • componentWillReceiveProps(nextProps) - 組件實例即將設(shè)置新屬性時被調(diào)用

參數(shù)nextProps表示即將應(yīng)用到組件實例上的新屬性值结序。

這個方法在初次渲染時不會被調(diào)用纵潦。在此方法內(nèi)調(diào)用setState()不會引起重新渲染邀层。

  • shouldComponentUpdate(nextProps, nextState) - 組件實例即將重新渲染時被調(diào)用

參數(shù)nextProps傳入即將應(yīng)用到組件實例上的新屬性值劲赠,參數(shù)nextState傳入組件實例即將被 設(shè)置的狀態(tài)值秸谢。如果這個方法返回false估蹄,那么組件實例就不會被重新渲染元媚。除非我們明確地 知道刊棕,新的屬性和狀態(tài)不需要進(jìn)行重新渲染,否則這個方法都應(yīng)該返回true网严。

這個方法在初次渲染時或通過forceUpdate()方法進(jìn)行渲染時不會被調(diào)用震束。

  • componentWillUpdate(nextProps, nextState) - 組件實例即將重新渲染時被調(diào)用

這個方法在初次渲染時不會被調(diào)用。注意:不能在此方法內(nèi)調(diào)用setState()割疾。

  • componentDidUpdate(prevProps, prevState) - 組件實例重新渲染后被調(diào)用

這個方法在初次渲染時不會被調(diào)用宏榕。

  • componentWillUnmount() - 組件實例即將從DOM樹移除時被調(diào)用

這個方法在整個生命周期中只會被調(diào)用一次侵佃。

訪問DOM

在React中馋辈,有時需要_直接訪問_React元素對應(yīng)的DOM對象,比如讀取用戶的輸入叉抡。 這需要兩個步驟:

  • 設(shè)置React元素的ref屬性

如果需要在代碼中訪問某個React元素的DOM對象,那么首先需要設(shè)置這個React 元素的ref屬性烙常。

比如蚕脏,我們需要讀取文本輸入框的值驼鞭,那么首先給這個input元素指定ref屬性:

  • //JSX
    <input type="text" defaultValue="beijing" ref="q"
    placeholder="請輸入城市拼音,如:beijing"/>

聲明了React元素的ref屬性之后译隘,可以通過this.refs對象訪問 這個組件,比如上面的示例中:this.refs.q指向input組件對象厅目,你應(yīng)該已經(jīng)注意到, 我們?yōu)镽eact元素設(shè)置的ref屬性值葫笼,在這里被用為this.refs對象的鍵值路星。

  • 獲得DOM對象

在設(shè)置了React元素的ref屬性后,可以使用React.findDOMNode()方法獲得對應(yīng)的 DOM對象:

  • React.findDOMNode(component)

參數(shù)component是一個React組件對象访诱,如前所述触菜,我們可以通過this.refs對象獲得宏邮。

如果React元素已經(jīng)渲染到DOM樹上纽帖,findDOMNode()方法將返回組件對象對應(yīng)的DOM節(jié) 點對象疫萤,后續(xù)就可以使用標(biāo)準(zhǔn)的DOM API操作這個DOM對象了犬缨。

右邊的示例實現(xiàn)了一個簡單的天氣查詢組件怀薛,在文本框中輸入城市名稱的拼音枝恋,點擊按鈕 就可以獲得這個城市的當(dāng)前天氣信息。天氣數(shù)據(jù)實時從openweathermap.org網(wǎng)站讀取就漾,所以 可能會慢點呐能,也可能,失效:

表單輸入

在React中,表單輸入元素如 input, textarea, option等摆出,和其他標(biāo)準(zhǔn)的HTML元素 相比需要特殊的注意:

  • 文本輸入框

不要使用value屬性設(shè)置文本輸入框元素的初值朗徊,應(yīng)當(dāng)使用defaultValue:

  • //JSX
    <input type = "text" defaultValue = "demo"/>

  • 復(fù)選按鈕

不要使用checked屬性設(shè)置復(fù)選按鈕的初始選中狀態(tài),應(yīng)當(dāng)使用defaultChecked:

  • //JSX
    <input type = "checkbox" defaultChecked/>

  • 單選按鈕組

不要使用option元素的selected屬性設(shè)置單選按鈕組的初始選中狀態(tài)偎漫,應(yīng)當(dāng)使用 select元素的defaultValue:

  • //JSX
    <select defaultValue="A">
    <option value="A">China</option>
    <option value="B">India</option>
    <option value="C">Japan</option>
    </select>

      <!DOCTYPE html>
      <html>
    

<head>
<meta charset="utf-8">
<title>EzLoginComp</title>
<script src="lib/react.min.js"></script>
<script src="lib/JSXTransformer.js"></script>
</head>
<body>
<div id="content"></div>
<script type="text/jsx">
//組件定義
var EzLoginComp = React.createClass({
auth : function(event){
var account = React.findDOMNode(this.refs.account).value,
pass = React.findDOMNode(this.refs.password).value;
alert([account,pass]);

        },
        render : function(){

            return     <div className = "ez-login">
                        <div className="row title">
                            <h1>登錄</h1>
                        </div>
                        <div className="row account">
                            <label>用戶</label>
                            <input type="text" defaultValue="asasassa" ref="account"/>
                        </div>
                        <div className="row pass">
                            <label>密碼</label>
                            <input type="text" ref="password"/>
                        </div>
                        <div className="row remember">
                            <input type="checkbox" defaultChecked/>
                            <span>記住密碼</span>
                        </div>
                        <div className="row button">
                            <button onClick={this.auth}>登錄</button>
                        </div>
                    </div>;
        }
    });
    //渲染
    React.render(<EzLoginComp/>,document.querySelector("#content"));
       </script>
    </body>
    </html>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末爷恳,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子象踊,更是在濱河造成了極大的恐慌温亲,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件栈虚,死亡現(xiàn)場離奇詭異泌射,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)号显,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事滞详“斗龋” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵逾冬,是天一觀的道長嘀趟。 經(jīng)常有香客問我炕柔,道長,這世上最難降的妖魔是什么衰琐? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布淫奔。 她就那樣靜靜地躺著,像睡著了一般鼠哥。 火紅的嫁衣襯著肌膚如雪菜皂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機(jī)與錄音秫逝,去河邊找鬼刷后。 笑死班巩,一個胖子當(dāng)著我的面吹牛睡陪,可吹牛的內(nèi)容都是我干的兰迫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蜗元,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤舀武,失蹤者是張志新(化名)和其女友劉穎顽染,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體轰绵,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡粉寞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了左腔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片唧垦。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖翔悠,靈堂內(nèi)的尸體忽然破棺而出业崖,到底是詐尸還是另有隱情野芒,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布双炕,位于F島的核電站狞悲,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏妇斤。R本人自食惡果不足惜摇锋,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望站超。 院中可真熱鬧荸恕,春花似錦、人聲如沸死相。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽算撮。三九已至生宛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肮柜,已是汗流浹背陷舅。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留审洞,地道東北人莱睁。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像芒澜,于是被迫代替她去往敵國和親仰剿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 原教程內(nèi)容詳見精益 React 學(xué)習(xí)指南痴晦,這只是我在學(xué)習(xí)過程中的一些閱讀筆記酥馍,個人覺得該教程講解深入淺出,比目前大...
    leonaxiong閱讀 2,840評論 1 18
  • 本筆記基于React官方文檔阅酪,當(dāng)前React版本號為15.4.0。 1. 安裝 1.1 嘗試 開始之前可以先去co...
    Awey閱讀 7,712評論 14 128
  • 以下內(nèi)容是我在學(xué)習(xí)和研究React時汁针,對React的特性术辐、重點和注意事項的提取、精練和總結(jié)施无,可以做為React特性...
    科研者閱讀 8,238評論 2 21
  • 已經(jīng)記不清當(dāng)我把這件事告訴媽媽時猾骡,媽媽說了什么瑞躺》筇拢可是 當(dāng)她聽聞此事時后憂慮與焦急的神情以及送我走時,目中滿盈著的對...
    未明海閱讀 243評論 0 0
  • 感謝遇見幢哨,感恩陪伴赡勘。 我也算是富有的人了吧, 擁有視我如寶的家人捞镰, 待我如親人的朋友闸与。 這樣的美好大概是來自是塵世...
    等待ye是一種幸福閱讀 101評論 0 0