• 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

  • 相关阅读:
    vue-cli
    respond.js
    dataTable调用接口渲染数据,没有数据,报错
    jq自定义鼠标右键菜单
    datatables通过ajax调用渲染数据,怎么根据数据给td添加class
    【C++ Primer 第11章 练习答案】2. 关联容器概述
    【Leetcode】1. Two Sum
    【C++】拷贝构造函数(深拷贝,浅拷贝)详解
    【图的遍历】广度优先遍历(DFS)、深度优先遍历(BFS)及其应用
    【C++ Primer 第十三章】4. 拷贝控制示例
  • 原文地址:https://www.cnblogs.com/vajoy/p/4803585.html
Copyright © 2020-2023  润新知