React2 组件的内部状态

在上文《React1 创建React组件、组件的属性》 中,了解到组件的视图是属性的映射,通过改变组件属性可以触发组件重新渲染,从而改变组件的视图

其实组件的视图是由属性和内部状态映射而来的,即 view=f(props,state),跟属性类似,状态的改变也会触发组件的重新渲染,只不过状态是组件内部基于自身逻辑或者用户事件自己维护的,而不是由外部输入。


组件的内部状态

       可以通过 ReactDOM.render(,container) 的方式,将带有特定属性的组件渲染到页面的某个DOM节点中(container)

       示例:

        function Clock(props){
          return (
            

Hello World

It Is {props.time}

) } function tick(){ ReactDOM.render( , document.getElementById('root') ) } setInterval(tick,1000)
        示例解析:

                例子中定义了一个 Clock 组件,组件接收一个 time 属性,在组件外部通过 setInterval 周期性的调用 ReactDOM.render 不断更新 Clock 的属性并重新渲染

        在实际场景中,对于一个时钟组件,我们希望只调用一次 ReactDOM.render(,container) 然后它可以自己更新自己的视图

        更容易在页面上放置多个时钟,即复用性更好。

        要达到这个目的,就需要组件内部状态来支持。组件有一个特殊的属性 state 用来保存组件的内部状态。

        用户可以通过 this.setState(statePatch) 来更新组件的状态,组件的状态更新后会重新执行 render 方法来更新视图,以上例子内部改造后

        示例:

         class Clock extends React.Component{
           construstor(props){
             super(props);
               this.state={
                 time:new Date();
             }
           }
           componentDidMount(){
             this.timeID=setInterval(()=>this.tick(),1000);
           }
           componentWillUnmount(){
             clearInterval(this.timeID)
           }
           tick(){
             this.setState({
               time:new Date()
             })
           }
           render(){
             return(
               

Hello World

It Is {this.state.time.toLocaleTimeString()}

) } } ReactDOM.render( , document.getElementById('root') )
          此时,Clock 作为一个完整的时钟组件就可以自己更新自己了,如果想要使用组件的内部状态,那组件必须以类继承的方式来定义,而不能使用函数式组件

         所以说,函数式组件也被常称作为无状态组件(stateless)

         例子中有用到 componentDidMount 和  componentWillUnmount 两个函数,它们是组件的生命周期函数

         改造后的例子,只需要调用一次 ReactDOM.render 即可,在实例的项目中,一个完整的单页面web应用,

         也只需要调用一次 ReactDOM.render 方法把根组件挂载到页面中即可

初始化组件内部状态

        在创建一个拥有内部状态的组件时,需要对内部状态进行初始化,即设置组件的最初状态是什么,

        是在构造函数 constructor 中设置 state 属性就可以

        示例:               

         class MyComponent extends React.Component{
           construstor(props){
             super(props);  //这行代码不可缺少
             this.state={
               name:'Luky'
             }
           }
         }
setState 大多数情况下是异步的

         setState 多数情况下是异步的,异步意味着通过 setState 更新组件状态后, 不能立刻通过 this.state 来获取到更新后的值

         另外当连续多次调用 setState 来更新同一个字段时,只有最后一次更新才会生效

         示例:            

 
  
        
         class Test extends React.Component{
           constructor(props){
             super(props);
             this.state={
               value:0
             }
           }
           addTree(){
             this.setState({value:this.state.value+1});
             this.setState({value:this.state.value+2});
             this.setState({value:this.state.value+3});
          }
           render(){
             return (
               

Value:{this.state.value}

) } } ReactDOM.render( , document.getElementById('root') )

        示例结果:        

      React2 组件的内部状态_第1张图片React2 组件的内部状态_第2张图片只以最后一次更新为准

        如果需要代码正常工作,需要通过回调函数的方式来生成下一个state

        示例:

         this.setState(preState=>({value:preState.value+1}));
         this.setState(preState=>({value:preState.value+2}));
         this.setState(preState=>({value:preState.value+3}));

      示例结果:

      React2 组件的内部状态_第3张图片React2 组件的内部状态_第4张图片

        解析:

                 实际上只有在React能控制的事件处理过程中调用的 setState 才是异步的,如:生命周期函数,React内置的button、input等组件的事件处理函数

                 在某些特殊的组件中,可能需要通过addEventListener来设置某些DOM事件处理函数,在这种通过原生JS API 来设置的事件处理过程中调用setState就是同步的,

                 会立即更新 this.state,另外还有 setInterval、setTimeout等原生API的回调函数也是如此



文件借鉴于: http://react-china.org/t/react-react/15548

你可能感兴趣的:(React2 组件的内部状态)