React技术栈之React(三)组件的生命周期
React技术栈之React(一)初识React React严格定义了组件的生命周期,共3个过程: 三种不同的过程,React库会依次调用组件的一些生命周期函数。所以,定义一个React组件,实际上就是定制这些生命周期函数。 组件装载过程装载过程依次调用的生命周期函数: constructorES6中每个类的构造函数,创造一个组件实例,当然会调用对应的构造函数。
React组件需要构造函数,是为了以下目的: getInitialState和getDefaultProps这2个函数,只有在通过React.createClass方法创造的组件类才会发生作用。这是过时的方法,ES6创造的组件中用不到。 假如用React.createClass定义组件Sample,设定内部状态foo初始值为bar,同时设定sampleProp的prop初始值为0,代码如下: const Sample = React.createClass({ getInitialState: function(){ return {foo: 'bar'}; },getDefaultProps: function() { return {sampleProp: 0} } }); 用ES6的话,在构造函数中给this.state赋值完成状态初始化,给类的属性defaultProps赋值指定props初始值: class Sample extends React.Component { constructor(props) { super(props); this.state = {foo: 'bar'}; } } Sample.defaultProps = { return {sampleProp: 0}; }; renderReact组件可以忽略其他所有函数都不实现,但是一定要实现render函数,因为所有React组件的父类React.Component类对除render之外的生命周期函数都有默认实现。render函数并不做实际的渲染动作,它只负责返回一个JSX描述的结构,最终由React来操作渲染过程。 render函数应该是一个纯函数,完全根据this.state和this.props来决定返回的结果,而且不要产生任何副作用。在render函数中去调用this.setState是错误的,因为一个纯函数不应该引起状态的变化。 componentWillMount和componentDidMount装载过程中,componentWillMount和componentDidMount分别在render之前和之后调用。 不过,通常不定义componentWillMount函数,因为顾名思义,它发生在将要装载的时候,这个时候一切都迟了,即使再调用this.setState()修改状态也不会引发重新绘制了。换句话说,所有可以在componentWillMount中做的事情,都可以提前到constructor中去做。可以认为这个函数存在的目的就是为了和componentDidMount对称。 而componentDidMount作用就大了。不过要注意的是,componentDidMount被调用时,前置render函数返回的东西必定已经完成了渲染,组件已经被“装载”到DOM树上了。 还是以ControlPanel为例,在ControlPanel中有三个Counter组件,我们修改Counter代码,让装载过程的所有生命周期函数都用console.log输出函数名和caption值,比如,componentWillMount函数如下: componentWillMount() { console.log('enter componentWillMount ' + this.props.caption); } 在浏览器的console里我们能看到: enter constructor: First enter componentWillMount First enter render First enter constructor: Second enter compomentWillMount: Second enter render Second enter constructor: Third enter componentWillMount Third enter render Third enter componentDidMount First enter componentDidMount Second enter componentDidMount Third 可以清楚的看到,由于渲染需要一定的时间,所以三个组件的componentDidMount是在最后才连在一起被调用的。 componentWillMount和componentDidMount还有一个区别,就是componentWillMount可以在服务端被调用,也可以在浏览器端被调用;而componentDidMount只能在浏览器端被调用。 componentDidMount中,可通过AJAX获取数据来填充组件内容。在componentDidMount被调用时,组件已经被装载到DOM树了,也可以放心的让React和其他库(如jQuery)配合工作了。 组件更新过程当组件被装载到DOM树上之后,用户在网页上看到了第一印象,但是要提供更好的交互体验,就要让组件可以随着用户操作改变展现的内容,当props或state被修改时,就会引发组件的更新过程。 更新过程依次调用以下生命周期函数: componentWillReceiveProps当组件的props发生改变时会被调用。父组件的render被调用时,被渲染的子组件也会经历更新过程,不管父组件传给子组件的props有没有改变,都会触发子组件的componentWillReceiveProps。 我们在Counter组件类里增加这个函数定义,并在console输出一些文字: componentWillReceiveProps(nextProps) { console.log('enter componentWillReceiveProps ' + this.props.caption) } 在ControlPanel组件的render函数中,也做如下修改: render() { console.log('enter ControlPanel render'); return ( <div style={style}> ... <button onClick={ () => this.forceUpdate() }> Click me to parent! </button> </div> ); } 除了在ControlPanel的render函数入口增加console输出,还增加了一个按钮,当这个按钮被点击时,调用this.forceUpdate(),每个React组件都可以通过forceUpdate()强行引发一次组件重绘。 在网页上点击父组件新增的重绘按钮,看到浏览器console输出: enter ControlPanel render enter componentWillReceiveProps First enter render First enter componentWillReceiveProps Second enter render Second enter componentWillReceiveProps Third enter render Third 可以看到,父组件引发重绘后,首先是父组件ControllPanel的render被调用,随后依次3个Counter子组件的componentWillReceiveProps和render函数被调用。 然尔,父组件传给三个子组件的props值一直没有变化,这就验证了componentWillReceiveProps并不只是当props值变化时才被调用,父组件render时,子组件的componentWillReceiveProps也会被调用。 在网页中,我们再尝试点击第一个Counter子组件的“+”按钮,可以看到浏览器console输出: enter render First 明显,只有第一个子组件Counter的render函数被调用,因为组件的this.setState()函数不会引发componentWillReceiveProps调用。 shouldComponentUpdate(nextProps,nextState)shouldComponentUpdate函数返回一个布尔值,告诉React库这个组件在这次更新过程中是否要继续。返回false会停止更新过程,就此结束,也不会引发后续的渲染了。 这个函数能够大大提升React组件的性能,不管React的组件渲染有多快,如果发现没有必要重新渲染,就干脆不要渲染。 修改Counter组件类增加shouldComponentUpdate函数的定义: shouldComponentUpdate(nextProps,nextState) { return (nextProps.caption !== this.props.caption) || (nextState.count !== this.state.count); } componentWillUpdate和componentDidUpdate如果组件的shouldComponentUpdate返回true,接下来会依次调用componentWillUpdate、render和componentDidUpdate函数。 在介绍componentDidMount函数时,说到可以利用componentDidMount函数执行其他UI代码库,比如jQuery代码。那么现在,组件被更新时,也需要在componentDidUpdate函数再次调用jQuery代码。 组件卸载过程React组件的卸载过程只涉及一个函数componentWillUnmount,这个函数适合做一些清理工作。这些清理工作往往和componentDidMount有关,比如你在componentDidMount中用非React的方法创造了一些DOM元素,如果撒手不管会造成内存泄漏,那就需要在componentWillUnmount中把这些DOM元素清理掉。 代码:https://github.com/zhutx/reac... React技术栈之React(一)初识React (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |