ReactJS入門(四)—— 組件API


本篇將介紹 React 組件的API,其中主要的幾個API我們在第一篇的時候便已介紹過,這里可以做個溫故知新。

本篇的代碼你也可以在我的Github上獲取到。

 

setState

參數: nextState(object), [callback(function)]

設置 nextState 的某個鍵(屬性)(別忘了我們可以在 shouldComponentUpdate 方法中獲取到 nextState 的值來跟當前的 this.state 進行對比),然后下一次 EventLoop 時 this.state 的對應鍵就會被更新為該設定的值。

通常我們如果希望在某個事件或某個回調中來重新渲染組件(觸發UI更新內容),setState 是一個最常用的觸發方法,因為我們把UI內容跟state狀態直接(或者通過某些條件)綁定在了一起,一旦state發生改變並觸動了綁定的邏輯,那么UI內容自然也會跟着變動:

    var Component1 = React.createClass({
        getInitialState: function() {
            return {
                isClick: !1
            }
        },
        componentDidUpdate: function(){
            console.log('componentDidUpdate')
        },
        clickCb: function() {
            this.setState({
                isClick : !0
            }, function(){
                console.log(this.state.isClick)
            })
        },
        render: function() {
            return (<div onClick={this.clickCb}>
            isClick:{this.state.isClick ? 'yes' : 'nope'}
            </div>)
        }
    });
    var div = document.getElementById('a');
    React.render(
        <Component1 />, div
    );

如上我們通過 state.isClick 來決定div內要顯示的內容,而我們點擊div時會改變 state.isClick 的狀態,從而觸發綁定條件更改了div中的內容。

注意這段代碼里我們使用了 componentDidUpdate 方法,如第二篇文章中所介紹的,它在組件重新渲染后會立即觸發。我們點擊 div 之后發現打印順序是這樣的:

即我們在 setState 方法中所定義的回調,它是在組件重新渲染之后才執行的,而不是在我們變更了 nextState 的值之后就立即觸發。

replaceState

參數: nextState(object), [callback(function)]

類似於 setState(),但是刪除之前所有已存在的 state 鍵(key),這些鍵都不在 nextState 中。

這句話怎么理解呢?我們看這個例子:

    var Component1 = React.createClass({
        getInitialState: function() {
            return {
                isClick: !1,
                abc: 1   //注意這里我們初始化了一個 state.abc
            }
        },
        clickCb: function() {
            this.replaceState({
                isClick : !0
            }, function(){
                console.log(this.state)
            })
        },
        render: function() {
            return (<div onClick={this.clickCb}>
            isClick:{this.state.isClick ? 'yes' : 'nope'}
            </div>)
        }
    });
    var div = document.getElementById('a');
    React.render(
        <Component1 />, div
    );

注意我們在 getInitialState 里還額外定義了一個 abc 的 state 屬性,但在 replaceState 后再試着打印 this.state,會發現這個 state.abc 已經被刪除了(如果換成 setState 則不會被刪除)

所以顧名思義,replaceState 就是一個徹底更換掉 state 的方法,尋常使用的時候需要小心使用,避免刪掉一些重要的state屬性。

forceUpdate

參數: [callback(function)]

顧名思義就是在任何調用的時刻強制渲染組件,例如即使 shouldComponentUpdate 返回了false:

    var Component1 = React.createClass({
        shouldComponentUpdate: function(nextProps, nextState){
            console.log( this.state, nextState );
            this.forceUpdate(function(){
                console.log('強制渲染完成')
            }); //強制渲染,去掉這行則不會渲染
            return false;
        },
        componentDidUpdate: function(){
            console.log('componentDidUpdate')
        },
        getInitialState: function() {
            return {
                isClick: !1
            }
        },
        clickCb: function() {
            this.setState({
                isClick : !this.state.isClick
            })
        },
        render: function() {
            return (<div onClick={this.clickCb}>
            isClick:{this.state.isClick ? 'yes' : 'nope'}
            </div>)
        }
    });
    var div = document.getElementById('a');
    var c1 = React.render(
        <Component1 />, div
    );

注意該方法的回調,也是在重新渲染之后才執行的。

另一個使用 forceUpdate 的場景可以是,我們不以 props 或 state 來作為觸發渲染的條件,例如使用了一個變量來作為UI內容,在該變量的值改變了且我們希望觸發渲染時,可以使用該方法,當然這種形式是不推薦的。

getDOMNode()

返回組件/ReactElement掛載到頁面上所對應的DOM元素:

    var Component1 = React.createClass({
        getInitialState: function() {
            return {
                isClick: !1
            }
        },
        clickCb: function() {
            this.setState({
                isClick : !0
            }, function(){
                console.log(this.state.isClick)
            })
        },
        render: function() {
            return (<div onClick={this.clickCb}>
            isClick:{this.state.isClick ? 'yes' : 'nope'}
            </div>)
        }
    });
    var div = document.getElementById('a');
    var c = React.render(
        <Component1 />, div
    );
    console.log(c.getDOMNode())

打印結果:

另外,若 render 返回 null 或者 false 的時候,this.getDOMNode() 將返回 null。

isMounted()

返回一個 Boolean 值,如果組件掛載到了 DOM 中,isMounted() 返回 true。

其適用於異步請求的情景下:

    var Component1 = React.createClass({
        getInitialState: function() {
            return {
                content: 'hello'
            }
        },
        componentWillMount: function () {
            doSomething(props).then(function (content) {
                if (this.isMounted()) {
                    this.setState({content: content});
                }
            }.bind(this));
        },
        render: function() {
            if(this.state.isClick){
                return (<div>
                content:{this.state.content}
                </div>)
            } else {
                return false;
            }
        }
    });
    var div = document.getElementById('a');
    var c = React.render(
        <Component1 />, div
    );

如上代碼,我們在 componentWillMount 的時候執行一個異步請求 doSomething,在其獲取到服務器數據的時候修改 state 的值,前提是組件已經掛載到頁面上。

如果該異步請求完成得很快,我們獲取到新content時候組件可能還在處於掛載中(mounting)的過程,那么 state 則保持不變(因為此時 isMounted() 將返回false )。

setProps

參數: nextProps(object), [callback(function)]

跟 setState 類似,不過修改的是 props 罷了:

    var Component1 = React.createClass({
        clickCb: function() {
            this.setProps({
                name : 'cnBlog'
            }, function(){
                console.log(this.props)
            })
        },
        render: function() {
            return (<div onClick={this.clickCb}>
                    {this.props.sayhi || 'www.'}
                    {this.props.name || 'nothing'}
            </div>)
        }
    });
    var div = document.getElementById('a');
    React.render(
            <Component1 name="VaJoy" sayhi="Hello " />, div
    );

replaceProps

參數: nextProps(object), [callback(function)]

類似於 setProps,會替換掉現有的 props 的鍵,我們依舊使用上一段代碼,不過把 setProps 換成 replaceProps:

    var Component1 = React.createClass({
        clickCb: function() {
            this.replaceProps({
                name : 'cnBlog'
            }, function(){
                console.log(this.props)
            })
        },
        render: function() {
            return (<div onClick={this.clickCb}>
                    {this.props.sayhi || 'www.'}
                    {this.props.name || 'nothing'}
            </div>)
        }
    });
    var div = document.getElementById('a');
    React.render(
            <Component1 name="VaJoy" sayhi="Hello " />, div
    );

我們這時再點擊組件,會發現 props.sayHi 已被刪除了:

Refs

事實上這個不屬於組件的方法,但也是在組件中常用的一個小技巧,故在這里做介紹。

我們在前面提到,可以使用 ReactClass.getDOMNode() 的方法來獲取到組件渲染在頁面上的DOM節點,但是如果我們希望獲取到的,是組件中的某個DOM元素呢?

這時候我們可以使用定義 refs 的形式,來方便我們獲取對應的元素:

    var Component1 = React.createClass({
        clickCb: function(e) {
            if(e.target === this.refs.li2.getDOMNode()){
                alert('你點到第二個LI了')
            }
        },
        render: function() {
            return (<ul onClick={this.clickCb}>
                <li>1</li>
                <li ref="li2">2</li>
                <li>3</li>
            </ul>)
        }
    });
    var div = document.getElementById('a');
    React.render(
            <Component1 />, div
    );

如上我們給組件中的第二個<li>綁定了一個 ref 屬性,值為“li2”,這意味着我們可以在組件中以 this.refs.li2 的形式來獲取到該ReactElement。

然后綁定點擊事件,在點擊的時候判斷被點擊的 li 元素是否等於 this.refs.li2.getDOMNode(),是的話則彈出alert。

官方也給出了一個實用的demo:

  var App = React.createClass({
    getInitialState: function() {
      return {userInput: ''};
    },
    handleChange: function(e) {
      this.setState({userInput: e.target.value});
    },
    clearAndFocusInput: function() {
      // Clear the input
      this.setState({userInput: ''}, function() {
        // 組件重繪后會立即執行這句代碼:
        this.refs.theInput.getDOMNode().focus();   // input成功聚焦(focus)
      });
    },
    render: function() {
      return (
        <div>
          <div onClick={this.clearAndFocusInput}>
            Click to Focus and Reset
          </div>
          <input
            ref="theInput" //我們可以在組件里以 this.refs.theInput 獲取到它
            value={this.state.userInput}
            onChange={this.handleChange}
          />
        </div>
      );
    }
  });

到此位置我們便基本入門了 React 的大部分主要的API,后續我們將以項目實踐的形式來進一步學習React。

共勉~!

donate


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM