React 入門,5個常用DEMO展示

轉自http://blog.csdn.net/iambinger/article/details/51803606


閱讀前請看這裏: 
* 瞭解js及jQuery的使用 
* 對react有一定的瞭解,知道jsx的語法 
* 這裏只講述如何使用react,並不介紹react的優缺點

如果不滿足這些,建議先了解下,然後再看這篇文章

下面會講述5個react的實例,雖然僅有5個,但在常用的開發中,幾乎會包含大部分的情況,只要熟練掌握這5個demo,相信一定會解決大部分問題。

demo中,所有樣例會打包後,傳遞到附件,大家可以下載閱覽,最好自己親手實踐下,不要直接copy代碼,沒有意義。

使用的react版本是0.14.7

DEMO 1 - 最簡單的react渲染

代碼:

<html>
    <head>
        <link href="css/bootstrap.min.css" rel="stylesheet">
    </head>

    <body>
        <h1><span class="label label-info">DEMO 1</span></h1>
        <br><br><br>


        <div class="well" id="well">

        </div>

        <script src="js/jquery.min.js"></script>
        <script src="js/react.js"></script>
        <script src="js/react-dom.js"></script>
        <script src="js/browser.min.js"></script>

        <script type="text/babel">
        var Text = React.createClass({
            render: function() {
                return (
                    <div className="a">
                        大家好,我是用react渲染出來的!
                    </div>
                );
            }
        });

        ReactDOM.render(
            <Text/>,
            document.getElementById('well')
        );
        </script>
    </body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

在瀏覽器中顯示的效果如下

這裏寫圖片描述

講解:

  • 頁面中,只有<div id='well'>這裏的內容是使用react渲染出來的,代碼中這裏是空的,依賴下面的js進行渲染
  • 首先看下 vat Text = 這塊,這裏是聲明一個模塊,名字隨意起,我們把第一個字母大寫,用來區分html中原生的標籤
React.createClass({
    render: function() {
        return (
            <div className="a">
                大家好,我是用react渲染出來的!
            </div>
        );
    }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

這塊是創建一個模塊,使用React.createClass即可創建。 
* 其中參數有很多,但都可以省略,唯有render不可以省略,因爲這是用來表述這個插件被加載後,顯示的是什麼樣子,它的返回結果,就是加載在頁面上最終的樣式。

ReactDOM.render(
   <Text/>,
    document.getElementById('well')
);
  • 1
  • 2
  • 3
  • 4

這段代碼是用來渲染react組件額,第一個參數是組件,第二個參數是要渲染的位置。 
* 使用<Text/>的 方式就可以實例化組件,或者寫成<Text></Text>,要注意下,react中標籤的閉合非常嚴格,任何標籤的關閉與打開必須一一對應,否則會報錯。 
* 到目前爲止,就完成了一次渲染,將Text組件render函數返回的內容,填充到了id=well的div中。


DEMO 2 - 帶有參數的react

往往在使用中,文本的內容並不是寫死的,而是需要被我們指定,這樣組件才能更通用。下面介紹下,如何向react中傳遞參數。

代碼:

<html>
    <head>
        <link href="css/bootstrap.min.css" rel="stylesheet">
    </head>

    <body>
        <h1><span class="label label-info">DEMO 2</span></h1>
        <br><br><br>


        <div class="well" id="well">

        </div>

        <script src="js/jquery.min.js"></script>
        <script src="js/react.js"></script>
        <script src="js/react-dom.js"></script>
        <script src="js/browser.min.js"></script>

        <script type="text/babel">
        var Text = React.createClass({
            render: function() {
                return (
                    <div className="a">
                        大家好,我是用{this.props.name}渲染出來的!age={this.props.age}
                    </div>
                );
            }
        });

        ReactDOM.render(
            <Text name="react" age={181}></Text>,
            document.getElementById('well')
        );

        </script>
    </body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

在瀏覽器中顯示的效果如下

這裏寫圖片描述

講解

  • 首先,這個大體上跟第一個demo類似,唯有實例化Text時,多了參數。
  • 當我們傳遞參數時,寫了兩種方式,一種是 name="react"另一種是age={181},這兩種寫法是有區別的,並不僅僅因爲一個是str,一個是int。如果是str這種類型,寫成 name="xxx"或者name={"xxx"}都是可以的,加了{}的意思就是js中的變量,更加精確了。而後者age={181}是不可以去掉{}的,這樣會引起異常,所以這裏要注意下,並且建議任何類型都加上{}來確保統一。
  • 當在Text初始化時添加了參數,在組件內部,都收集在this.props中,使用時只要{this.props.name}既可以獲取name對應的值,如果取得key並不存在,這裏不會報錯,只是取到的值是空的。當然可以在getDefaultProps中定義默認的props值,即使在沒有傳遞參數的情況下,也能取到默認值。
  • props中的參數,在初始化傳遞後,便不能再修改。

DEMO 3 - state,react的核心

state算是react的核心了,任何頁面的變化,刷新都是state的變化引起。在react中,只要調用了setState都會引起render的重新執行。下面介紹下如何通過鍵盤事件觸發狀態變化。

代碼:

<html>
    <head>
        <link href="css/bootstrap.min.css" rel="stylesheet">
    </head>

    <body>
        <h1><span class="label label-info">DEMO 3</span></h1>
        <br><br><br>


        <div class="well" id="well">

        </div>

        <script src="js/jquery.min.js"></script>
        <script src="js/react.js"></script>
        <script src="js/react-dom.js"></script>
        <script src="js/browser.min.js"></script>

        <script type="text/babel">
        var Text = React.createClass({
            getInitialState: function() {
                return {name: "react"};
            },
            keyUp: function(e){
                this.setState({name: e.target.value});
                console.log(this.state.name);
            },
            render: function() {
                return (
                    <div className="a">
                        大家好,我是用{this.state.name}渲染出來的!
                        <input onKeyUp={this.keyUp} />
                    </div>
                );
            }
        });

        ReactDOM.render(
            <Text></Text>,
            document.getElementById('well')
        );

        </script>
    </body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

在瀏覽器中顯示的效果如下

這裏寫圖片描述

講解:

  • 這次組件中多了兩個函數,getInitialStatekeyUp,其中getInitialState是react中的初始化狀態的函數,類似上一節中getDefaultProps的作用。keyUp是我自定義的函數,用來響應鍵盤事件的。
  • 我們先看render函數,文字渲染中加了{this.state.name},這個是react內部的狀態,可以理解是存儲數據的k-v結構,這裏的v支持的對象較多。{this.state.name}就是引用狀態中的name屬性,與props的區別在於,如果state中不存在這個屬性,是會報錯的,所以我們要在getInitialState中初始化這個狀態的初始值。
  • render中還多了一個,onKeyUp是註冊鍵盤鍵彈起的事件,當按鍵按下後彈起,就會觸發onKeyUp事件,然後通過綁定的this.keyUp,將事件傳遞給了自己定義的keyUp函數中。
  • keyUp函數中,使用了this.setState({name: e.target.value}),setState是react中內部的函數,專門用來更新狀態的,這裏是講狀態中name的值變更爲引起事件的value值。
  • 在react中,每次狀態的變化,都會引起render函數的重新渲染,這是它自己的機制,我們無需人爲處理,當鍵盤輸入內容時,會觸發狀態變化,導致render重新渲染,渲染的過程會從state中取出變量,所以我們就看到了頁面的內容發生了變化。
  • 我們在setState下面加了一個console,通過控制檯可以發現,每次打印的值並不是當前輸入的值,而是上一次輸入的值,這是怎麼回事呢?在setState中,這是一個異步處理的函數,並不是同步的,console在setState後立刻執行了,所以這時候狀態還沒有真正變更完,所以這裏取到的狀態仍舊是更新前的。這裏要特殊注意下。如果需要在更新狀態後,再執行操作怎麼辦呢,setState還有第二個參數,接受一個callback,我們嘗試將keyUp中代碼改成這樣
this.setState({name: e.target.value}, function(){
    console.log(this.state.name);
})
  • 1
  • 2
  • 3
  • 這時候log打印出來的只就是我們期望的內容,當每次狀態更新成功後,都會調用傳進去的callback函數。
  • react中渲染dom有自己的優化方式,首先它在內存中構建一套虛擬的dom,每次更新前將虛擬dom與瀏覽器中dom對比,只講有變化的部分進行更新,這樣大大的提高了性能。或者我們可以重寫函數來控制是否刷新,當然這種方式我們並不提倡。

DEMO 4 - 網絡請求觸發狀態變化

上一節講到狀態變化觸發render的重新渲染,這裏將常用的網絡請求引入,結合到狀態變化中。

代碼:

<html>
    <head>
        <link href="css/bootstrap.min.css" rel="stylesheet">
        <style>
            .div {
                height: 100px;
            }
        </style>
    </head>

    <body>
        <h1><span class="label label-info">DEMO 4</span></h1>
        <br><br><br>


        <div class="well div" id="well">

        </div>

        <script src="js/jquery.min.js"></script>
        <script src="js/react.js"></script>
        <script src="js/react-dom.js"></script>
        <script src="js/browser.min.js"></script>

        <script type="text/babel">
        var Text = React.createClass({
            getInitialState: function() {
                return {cur_time: 0};
            },
            request: function() {
                $.ajax({
                    type: "GET",
                    url: "http://xxx",
                    success: function(data){
                        this.setState({cur_time: data.timestamp});
                    }.bind(this),
                    complete: function(){
                        this.setState({cur_time: Date.parse(new Date()) / 1000});
                    }.bind(this)
                });
            },
            componentDidMount: function(){
                setInterval(this.request, 1000);
            },
            render: function() {
                return (
                    <div className="col-xs-12">
                        當前時間{this.state.cur_time}
                        <div className={ this.state.cur_time % 2 == 0?"hidden": "col-xs-6 alert alert-success"}>
                            <span>最後一位奇數</span>
                        </div>
                        <div className={ this.state.cur_time % 2 != 0?"hidden": "col-xs-6 alert alert-danger"}>
                            <span>最後一位偶數</span>
                        </div>
                    </div>
                );
            }
        });

        ReactDOM.render(
            <Text></Text>,
            document.getElementById('well')
        );

        </script>
    </body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

在瀏覽器中顯示的效果如下

這裏寫圖片描述 
這裏寫圖片描述

講解:

  • 這個例子中,頁面每秒會請求一次網絡,將請求到的數據中時間戳更新到狀態中。但是這個例子中實際上並沒有使用服務返回的時間戳,因爲我在公司使用測試網的接口拿數據,但是開放給大家要換一個公網能拿到時間戳的api,簡單的找了下沒找到,也不想用公司的接口試,所以算是mock了下~,在complete中每次都取瀏覽器時間來更新。
  • 仍舊是先看代碼,相比於上一個例子,這裏多了兩個函數requestcomponentDidMount,其中request是請求網絡的函數,componentDidMount是react內部的函數,也是react生命週期的一部分,它會在render第一次渲染前執行,而且只會執行一次。
  • 先看request,一個普通的ajax請求,在success回調中,假設服務器返回的json爲{“timestamp”: 1467425645},那data.timestamp就取得是1467425645,然後將值賦給state中的cur_time屬性。這時狀態發生了變化,render函數會重新渲染。當然例子中success不會被訪問到,因爲那個url根本不存在,所以我在complete回調中來寫了一個狀態變化,模擬success成功。
  • 爲什麼success回調函數最後會加一個bind(this)?因爲這個函數已經不是react內部的函數了,它是一個外部函數,它裏面的this並不是react組件中的this,所以要將外部函數綁定到react中,並能使用react內部的方法,例如setState,就要在函數最後bind(this),這樣就完成了綁定。
  • 再看下componentDidMount函數,這個函數在render渲染前會執行,裏面的代碼也很簡單,增加了一個定時器,1秒鐘執行一次request。
  • 這裏應該在加一個回調,就是定時器在初始化時創建,卻沒有對應的銷燬,所以在組件銷燬的時候,應該在這個生命週期中銷燬定時器。

DEMO 5 - 組件的嵌套使用

在封裝react時,我們往往按照最小單位封裝,例如封裝一個通用的div,一個通用的span,或者一個通用的table等,所以各自組件對應的方法都會隨着組件封裝起來,例如div有自己的方法可以更改背景色,span可以有自己的方法更改字體大小,或者table有自己的方法來更新table的內容等~ 這裏我們用一個div相互嵌套的例子來查看父子組件如何相互嵌套及調用各自的方法。在下面的例子中,父組件與子組件都有一個方法,來改變自身的背景色,我們實現父子組件相互調用對方的方法,來改變對方的背景色。

代碼:

<html>
    <head>
        <link href="css/bootstrap.min.css" rel="stylesheet">
        <style>
            .child {
                border-color: black;
                border: 1px solid;
                height: 200px;
            }
            .parent {
                height: 400px;
                border: 3px solid;
            }
        </style>
    </head>

    <body>
        <h1><span class="label label-info">DEMO 5</span></h1>
        <br><br><br>


        <div id="well">

        </div>

        <script src="js/jquery.min.js"></script>
        <script src="js/react.js"></script>
        <script src="js/react-dom.js"></script>
        <script src="js/browser.min.js"></script>

        <script type="text/babel">
        var Child = React.createClass({
            getInitialState: function() {
                return {color: ""};
            },
            changeColor: function(e) {
                this.setState({color: e.target.getAttribute("data-color")});
            },
            render: function() {
                return (
                    <div style={{backgroundColor: this.state.color}} className="col-xs-5 col-xs-offset-1 child">
                        <br/>
                        <ul className="list-inline">
                            <li><a href="#" data-color="#286090" className="btn btn-primary" onClick={this.props.parentChangeColor}>&nbsp;</a></li>
                            <li><a href="#" data-color="#31b0d5" className="btn btn-info" onClick={this.props.parentChangeColor}>&nbsp;</a></li>
                            <li><a href="#" data-color="#c9302c" className="btn btn-danger" onClick={this.props.parentChangeColor}>&nbsp;</a></li>
                            <li><a href="#" data-color="#ec971f" className="btn btn-warning" onClick={this.props.parentChangeColor}>&nbsp;</a></li>
                            <li><a href="#" data-color="#e6e6e6" className="btn btn-default" onClick={this.props.parentChangeColor}>&nbsp;</a></li>
                        </ul>
                    </div>
                );
            }
        });

        var Parent = React.createClass({
            getInitialState: function() {
                return {color: ""};
            },
            changeColor: function(e) {
                this.setState({color: e.target.getAttribute("data-color")});
            },
            child1ChangeColor: function(e) {
                this.refs["child1"].changeColor(e);
            },
            child2ChangeColor: function(e) {
                this.refs["child2"].changeColor(e);
            },
            render: function() {
                return (
                    <div style={{backgroundColor: this.state.color}} className="col-xs-10 col-xs-offset-1 parent">
                        <br/>
                        <ul className="list-inline">
                            <li>對應第一個child</li>
                            <li><a href="#" data-color="#286090" className="btn btn-primary" onClick={this.child1ChangeColor}>&nbsp;</a></li>
                            <li><a href="#" data-color="#31b0d5" className="btn btn-info" onClick={this.child1ChangeColor}>&nbsp;</a></li>
                            <li><a href="#" data-color="#c9302c" className="btn btn-danger" onClick={this.child1ChangeColor}>&nbsp;</a></li>
                            <li><a href="#" data-color="#ec971f" className="btn btn-warning" onClick={this.child1ChangeColor}>&nbsp;</a></li>
                            <li><a href="#" data-color="#e6e6e6" className="btn btn-default" onClick={this.child1ChangeColor}>&nbsp;</a></li>
                        </ul>
                        <ul className="list-inline">
                            <li>對應第二個child</li>
                            <li><a href="#" data-color="#286090" className="btn btn-primary" onClick={this.child2ChangeColor}>&nbsp;</a></li>
                            <li><a href="#" data-color="#31b0d5" className="btn btn-info" onClick={this.child2ChangeColor}>&nbsp;</a></li>
                            <li><a href="#" data-color="#c9302c" className="btn btn-danger" onClick={this.child2ChangeColor}>&nbsp;</a></li>
                            <li><a href="#" data-color="#ec971f" className="btn btn-warning" onClick={this.child2ChangeColor}>&nbsp;</a></li>
                            <li><a href="#" data-color="#e6e6e6" className="btn btn-default" onClick={this.child2ChangeColor}>&nbsp;</a></li>
                        </ul>
                        <hr/>

                        <Child ref="child1" parentChangeColor={this.changeColor} />
                        <Child ref="child2" parentChangeColor={this.changeColor} />
                    </div>
                );
            }
        });


        ReactDOM.render(
            <Parent/>,
            document.getElementById('well')
        );

        </script>
    </body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105

在瀏覽器中顯示的效果如下

這裏寫圖片描述

講解:

  • 首先說下,剛打開頁面並不是這樣的,背景都是白色的。這裏的截圖是點擊各個按鈕後變色的樣子。
  • 在這個例子中,藍色的div是一個父組件,它裏面包含了兩個子組件,分別是紅色和橙色,這兩個子組件實際上是一模一樣的。我們先看下父組件如何調用子組件。
  • 代碼中,子組件裏面定義了changeColor函數,用來接收onClick事件,並將點擊的按鈕的data-color屬性值作爲色值,更改到state中的color屬性中,然後觸發render來更新背景色。在父組件調用子組件時,我們寫了,裏面的ref=”child1”就是react中提供的一個屬性標籤,它與普通的props不同,這裏寫上ref=”xxx”後,在父組件中,使用this.refs[“child1”]就可以引用對應的子組件,當然這裏的ref的值是可以隨意定義,只要不重複就好。這樣就可以實現組組件引用子組件,然後直接調用裏面的方法就好,例如child1ChangeColor中就有this.refs["child1"].changeColor(e);的使用。連起來說下邏輯,在點擊父組件中第一列中的按鈕後,觸發onClick事件,然後onClick事件後,傳遞到child1ChangeColor後,將事件傳遞進入,然後再次傳遞給子組件的changeColor中,因爲子組件的changeColor是更改子組件自身的state,所以這時候子組件再次渲染,於是改變了顏色。這就是父組件調用子組件的邏輯。
  • 再說下子組件何如調用父組件的方法,父組件自身也有一個changeColor函數,用來改變自身的背景色。當父組件調用子組件時,,通過props,也就是第二個例子中講的那樣,通過參數的方式傳遞給子組件,這樣子組件中就可以使用this.props.parentChangeColor,來把子組件的onClick事件傳遞給父組件的changeColor方法中,來改變父組件的背景色。這就是子組件調用父組件函數的方法。
  • 還有一種情況,就是一個父組件下有多個子組件,但是子組件中並沒有直接的關係,這時候如果一個子組件調用另一個子組件的方法,就得通過他們共同的父組件來作爲中轉,在父組件中增加函數來作爲中轉的函數,來實現子組件間的調用。

好啦,以上就是這次分享給大家的react的5個DEMO,雖然只有5個demo,但在常用的情況下應該可以滿足大部分的需求,只要非常瞭解這5個demo就好了。更多的細節大家可以去react官網看下文檔,例如事件,生命週期等,都有較詳細的說明。英文文檔大家不用擔心看不懂,在react文檔地址後面,加一個zh-CH就會變成中文啦~ 例如這個https://facebook.github.io/react/docs/getting-started.html可改成 https://facebook.github.io/react/docs/getting-started-zh-CN.html ,這樣就可以看了。

附件地址在github上~

https://github.com/5977862/react-demo


另入門實例

React 入門實例教程

http://www.ruanyifeng.com/blog/2015/03/react.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章