转载

React系列之(二)-React组件的生命周期

在组件的整个生命周期中,随着该组件的props或者state的变化,它的DOM表现也将有相应的改变,一个组件就是一个状态机,对于特定的输入,它总会返回一致的输出。

React为每个组件提供了勾子函数去响应不同的时期–创建时,存在时以及销毁时。

创建时

当你首次使用一个组件类时,你会看到下面的这些方法依次被调用:

  1. getDefaultPops
  2. getInitialState
  3. componentWillMount
  4. render
  5. componentDidMount

getDefaultPops

对于组件类来说,这个方法只会被调用一次,该组件类的所有后续应用,getDefaultPops将不会再被调用,它用于返回组件实例的默认props值,值得注意的是,任何引用类型的值(如数组,对象),都会在所有实中共享,而不是每个组件实例拥有单独的副本,所以不要在组件实例中去修改props,把它当成只读的数据最好。

getInitialState

对于每个组件实例来讲,这个方法只会调用一次,注意它和getDefaultPops的调用是有区别的,getDefaultPops是对于组件类来说只调用一次,后续该类的应用都不会被调用,而getInitialState是对于每个组件实例来讲都会调用,并且只调一次。它用来初始化每个实例的state,在这个方法里,可以访问组件的props.值得注意的是,在getInitialState方法中,尝试通过this.props来创建state的做法是一种反模式。React专注于维护数据的单一来源。

//反模式 var CountDown = React.createClass({  getDefaultPops:function(){   return {    date:new Date()   }  },  getInitialState:function(){   retrun {    surplus:this.props.date - new Date()   }  },  render:function(){   return (    <div>{this.state.surplus}</div>   )  } })

上面这种就是一种反模式,经过计算后的值不应该赋给state,正确的模式应该是在渲染时计算这些值。这样保证了计算后的值永远不会与派生出它的props值不同步。

//正确写法 var CountDown = React.createClass({  getDefaultPops:function(){   return {    date:new Date()   }  },  render:function(){   var surplus = this.props.date - new Date();   return (    <div>{surplus}</div>   )  } })

然而,如果你的目的并不是同步,而是简单的初始化state,那么在getInitialState方法中使用props是没有问题的。比如:

//简单的初始化state var Checkbox = React.createClass({  getDefaultPops:function(){   return {    checked:false   }  },  getInitialState:function(){   return {    checked:this.props.checked   }  },  render:function(){   return (    <div className="checkbox">     <input type="checkbox" checked={this.state.checked} />    </div>   )  } })

componentWillMount

此方法在初始化之后,渲染之前被调用。

render

render方法会创建一个虚拟DOM,用来表示组件的输出。对于一个组件来讲,render方法是唯一一个必需的方法。render方法需要满足下面几点:

– 只能通过this.props和this.state访问数据

– 可以返回null,false或者任何React组件

– 只能出现一个顶级组件,不能返回一组元素(新手特别注意)

render方法返回的结果并不是真正的DOM元素,而是一个虚拟的表现,类似于一个DOM tree的结构的对象。react之所以效率高,就是这个原因。

componentDidMount

在render方法成功执行并真实的DOM已经被渲染后,componentDidMount方法才会被执行,你可以在该方法内部获取DOM节点,并操作它。

存在时

此时组件已经渲染好并且用户可以与它进行交互,比如鼠标点击,手指点按,或者其它的一些事件,导致应用状态的改变,你将会看到下面的方法依次被调用

1. componentWillReceiveProps

2. shouldComponentUpdate

3. componentWillUpdate

4. render

5. componentDidUpdate

componentWillReceiveProps

组件的props属性可以通过父组件来更改,这时,componentWillReceiveProps将来被调用。可以在这个方法里更新state,以触发render方法重新渲染组件。

//实现一个简单的全选与全不选效果 var Checkbox = React.createClass({  getDefaultPops:function(){   return {    checked:false   }  },  getInitialState:function(){   return {    checked:this.props.checked   }  },  componentWillReceiveProps:function(nextProps){   if(nextProps.checked !== this.state.checked){    this.setState({     checked:nextProps.checked    });   }  },  render:function(){   <div className="checkbox">    <input type="checkbox" checked={this.state.checked} />   </div>  } }); var AllChoose = React.createClass({  getDefaultPops:function(){   return {    checked:false   }  },  getInitialState:function(){   return {    checked:this.props.checked   }  },  handleChange:function(){   this.setState({    checked:!this.state.checked   });  },  render:function(){   return (    <div className="checkbox">     <input type="checkbox" checked={this.state.checked} onChange={this.handleChange}/>     <Checkbox checked={this.state.checked}/>     <Checkbox checked={this.state.checked}/>     <Checkbox checked={this.state.checked}/>    </div>   );  } });

shouldComponentUpdate

如果你确定组件的props或者state的改变不需要重新渲染,可以通过在这个方法里通过返回false来阻止组件的重新渲染,返回false则不会执行render以及后面的componentWillUpdate,componentDidUpdate方法。继续上面的例子,比如上面的第二个checkbox因为某些原因为禁用了,那么即使全选这个checkbox被选中了,它也不应该跟着一起被选中,所以Checkbox这个组件还需要作一些小调整

var Checkbox = React.createClass({  getDefaultPops:function(){   return {    checked:false,    disabled:false   }  },  getInitialState:function(){   return {    checked:this.props.checked,    disabled:this.props.disabled   }  },  componentWillReceiveProps:function(nextProps){   if(nextProps.checked !== this.state.checked){    this.setState({     checked:nextProps.checked    });   }  },  shouldComponentUpdate:function(){   return !this.state.disabled //当checkbox的disabled属性为true时,取反,返回false,阻止重新渲染  },  render:function(){   <div className="checkbox">    <input type="checkbox" checked={this.state.checked} />   </div>  } });

componentWillUpdate

这个方法和componentWillMount类似,在组件接收到了新的props或者state即将进行重新渲染前,该方法会被调用,注意不要在此方面里再去更新props或者state.

componentDidUpdate

这个方法和componentDidMount类似,在组件重新被渲染之后,它会被调用。可以在这里访问并修改DOM。

销毁时

随着一个组件从它的层级结构中被移除,这个组件的生命也算是走到了尽头,此时componentWillUnmout会被执行,提供一个让你做一些清理工作的机会。

componentWillUnmout

比如现在有一个组件,里面有一个循环执行的函数,当这个组件被销毁时,我们需要停止这个循环,否则会造成资源上的浪费,这个停止的语句就可以写在componentWillUnmout里。

//一个简单的计时器 var Clock = React.createClass({  getInitialState:function(){   return {    now:new Date()-0   }  },  tick:function(){   this.setState({now:new Date()-0})  },  componentDidMount:function(){   this.interval = setInterval(this.tick,1000);  },  componentWillUnmout:function(){   clearInterval(this.interval); //清除setInterval,释放资源  },  render:function(){   return (    <div>     {this.state.now}    </div>   )  } })

以上就是react组件在不同时间所提供的API,在每一个时间节点上都有相应的API让我们可以去处理,实现我们想要的效果。

正文到此结束
Loading...