React入门--------组件的声明周期
Posted 尹丹
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React入门--------组件的声明周期相关的知识,希望对你有一定的参考价值。
- Mounting/组件挂载相关:
componentWillMount
componentDidMount
- Updating/组件更新相关:
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
- Unmounting/组件移除相关:
componentWillUnmount
一、Mounting/组件挂载相关
componentWillMount
在组件挂载之前执行,但仅执行一次,即使多次重复渲染改组件,或者改变了组件的state。若希望该回到能执行多次,可以使用ReactDOM.unmountComponentAtNode移除掉已有的组件,然后再重新render。
var diva = document.getElementById(\'a\'); var divb = document.getElementById(\'b\'); var i=0; var Component1 = React.createClass({ componentWillMount:function(){ console.log(++i) }, render: function() { console.log(Date.now()); return <div name={this.props.name}>我只是一个安静的div</div> } });
//触发componentWillMount,render ReactDOM.render( <Component1 />, diva );
//未触发componentWillMount,触发render ReactDOM.render( <Component1 />, diva );
//触发componentWillMount,render ReactDOM.render( <Component1 />, divb );
//未触发componentWillMount,未触发render ReactDOM.render( <Component1 />, divb );
componentDidMount
在组件挂载之后执行,同componentWillMount一样,同一个组件重复渲染只执行一次,卸载组件后重新渲染可以重新触发一次。
二、Updating/组件更新相关
componentWillReceiveProps
在组件接收到props的时间点之前调用,注意组件初始化渲染时不会调用。
var i = 0; var div = document.getElementById(\'a\'), var div2 = document.getElementById(\'b\'); var Component1 = React.createClass({ componentWillReceiveProps: function(){ console.log(i++) }, clickCb: function() { React.render( <Component1 />, div2 ); }, render: function() { return <div onClick={this.clickCb}>点我给下一个div挂载组件</div> } }); React.render( <Component1 />, div //初始化不会触发componentWillReceiveProps ); React.render( <Component1 />, div //重复渲染会触发componentWillReceiveProps ); React.unmountComponentAtNode(div); //移除掉已有组件 React.render( <Component1 />, div //初始化不会触发componentWillReceiveProps );
运行结果如下:
该接口带有一个参数nextProps,可以利用它来获取新的props的值(this.props获取到的是当前的,也就是旧的props)
var i = 0; var div = document.getElementById(\'a\'); var render = function(){ React.render( <Component1 i={i++} />, div ); }; var Component1 = React.createClass({ componentWillReceiveProps: function(nextProps){ console.log(this.props.i, nextProps.i) }, render: function() { return <div onClick={render}>props.i的值是:{this.props.i}</div> } }); render();
运行结果如下
shouldComponentUpdate
该接口实际是在组件接收到了新的props或者新的state的时候会立即调用,然后通过返回值来决定是否要重新渲染当前的组件。
接口带两个参数,第一个参数表示新的props,第二个参数表示新的state。
var div = document.getElementById(\'a\'); var Component1 = React.createClass({ getInitialState: function(){ return { i : 0 } }, shouldComponentUpdate: function(nextProps, nextState){ console.log( this.state.i, nextState.i ); return nextState.i > 3 ? true : false; //返回true才会渲染组件 }, clickCb: function(){ this.setState({ i : this.state.i + 1 }) }, render: function() { return <div onClick={this.clickCb}>state.i的值是:{this.state.i}</div> } }); ReactDOM.render( <Component1 />, div );
点击第四次之后才会渲染组件,在div里显示正确的新state.i
componentWillUpdate
同shouldComponentUpdate一样,在组件收到新的props或者state的时候会调用,而且也有着两个参数来获取新的props和state。
不过本接口仅在shouldComponentUpdate执行并返回了true的时候才会被调用。
在上一个代码实例中做点改动
componentWillUpdate: function(nextProps, nextState){ console.log( \'yoyoyo\', this.state.i, nextState.i ); },
componentDidUpdate
在组件更新,重新渲染完毕之后调用,它和componentWillUpdate一样有着两个参数来获取新的props和state
var div = document.getElementById(\'a\'); var Component1 = React.createClass({ getInitialState: function(){ return { i : 0 } }, shouldComponentUpdate: function(nextProps, nextState){ console.log( this.state.i, nextState.i ); return nextState.i > 3 ? true : false; //返回true才会执行componentWillUpdate并重新渲染组件 }, componentDidUpdate: function(nextProps, nextState){ console.log( \'已经渲染完毕咯\', this.state.i, nextState.i ); }, componentWillUpdate: function(nextProps, nextState){ console.log( \'还没渲染哦\', this.state.i, nextState.i ); }, clickCb: function(){ this.setState({ i : this.state.i + 1 }) }, render: function() { return <div onClick={this.clickCb}>state.i的值是:{this.state.i}</div> } }); ReactDOM.render( <Component1 />, div );
运行结果如下:
三、Unmounting/组件移除相关:
var div = document.getElementById(\'a\'); var div2 = document.getElementById(\'b\'); var Component1 = React.createClass({ DOMArr : [], getInitialState: function(){ return { i : 0 } }, componentDidUpdate: function(nextProps, nextState){ var dom = document.createElement(\'p\'); dom.innerText = this.state.i; div2.appendChild(dom); this.DOMArr.push(dom); }, componentWillUnmount: function(){ if(!this.DOMArr.length) return; var i = 0; while(i < this.DOMArr.length){console.log(i); div2.removeChild(this.DOMArr[i++]); //移除componentDidUpdate里添加过的DOM } }, clickCb: function(){ this.setState({ i : this.state.i + 1 }) }, render: function() { return <div onClick={this.clickCb}>state.i的值是:{this.state.i}</div> } }); ReactDOM.render( <Component1 />, div ); div2.addEventListener(\'click\',function(){ ReactDOM.unmountComponentAtNode(div) //点击div2则卸载掉第一个div里的组件 }, false)
运行结果如下:
四、getDefaultProps和getInitialState
getDefaultProps
该方法是所有我们提及的方法中最先触发的,可以在该方法里return 一个对象来作为组件默认的props值(如果父组件传进来了props,以父组件为主),它只在组件初次挂载到页面上时触发,即使你重新挂载了组件。
getInitialState
用于给组件初始化state的值,调用该方法要求必须return 一个对象或者null,否则报错。该方法在组件每次实例化的时候都会触发。
var diva = document.getElementsByTagName(\'div\')[0], divb = document.getElementsByTagName(\'div\')[1]; var Component1 = React.createClass({ getDefaultProps: function(){ console.log(\'getDefaultProps\'); return { name : Date.now() } }, getInitialState: function(){ console.log(\'getInitialState\'); return null; //必须返回一个null或对象,否则会报错 }, render: function() { console.log(Date.now()); return <div name={this.props.name}>我只是一个安静的div</div> } }); ReactDOM.render( {/* 触发一次 getDefaultProps 和 getInitialState */} <Component1 />, diva ); ReactDOM.render( {/* getDefaultProps 和 getInitialState都不触发 */} <Component1 />, diva ); ReactDOM.unmountComponentAtNode(diva); ReactDOM.render( {/* 触发一次getInitialState */} <Component1 name="a"/>, diva ); ReactDOM.render( {/* 触发一次getInitialState */} <Component1/>, divb );
五、总结
上面是9个周期接口,它们被触发的顺序?
var Component1 = React.createClass({ getDefaultProps: function(){ console.log(\'getDefaultProps\') }, getInitialState: function(){ console.log(\'getInitialState\'); return null }, componentWillMount: function(){ console.log(\'componentWillMount\') }, componentDidMount: function(){ console.log(\'componentDidMount\') }, componentWillReceiveProps: function(){ console.log(\'componentWillReceiveProps\') }, shouldComponentUpdate: function(){ console.log(\'shouldComponentUpdate\'); return true; }, componentWillUpdate: function(){ console.log(\'componentWillUpdate\') }, componentDidUpdate: function(){ console.log(\'componentDidUpdate\') }, componentWillUnmount: function(){ console.log(\'componentWillUnmount\') }, render: function() { return <div>我只是一个安静的div</div> } }); ReactDOM.render( <Component1 />, document.body ); ReactDOM.render( <Component1 />, document.body ); ReactDOM.unmountComponentAtNode(document.body)
结果如下:
以上是关于React入门--------组件的声明周期的主要内容,如果未能解决你的问题,请参考以下文章
React简介虚拟DOMDiff算法创建React项目JSX语法组件组件声明方式组件传值props和state组件的生命周期