react生命周期
本文整理了有关react生命周期的相关知识,尽量详细而又简单易懂。
一、react生命周期函数?
生命周期函数(钩子函数)就是在某一时刻会被自动的调用执行的函数.
tips:
(1)什么是钩子函数?
百度百科一番:钩子函数是Windows消息处理机制的一部分,通过设置“钩子”,应用程序可以在系统级对所有消息、事件进行过滤,访问在正常情况下无法访问的消息。钩子的本质是一段用以处理系统消息的程序,通过系统调用,把它挂入系统。
总的说,钩子函数是一段程序,是用来处理系统消息的。它的名称是确定的,在系统消息触发时被系统调用,并不是用户自己触发的。如,react的componentDidMount()函数,我们只需要写它的函数体,在组件挂载之后会自动调用此函数。
(2)常见的钩子函数有:react生命周期函数、vue生命周期函数
二、生命周期具体有哪几个阶段?每个阶段都能做什么?
1.constructor(props)
在组件初始化时被调用,可以设置组件的一些初始化的状态以及绑定类方法。
作用:用来初始化状态,如果既不初始化状态也不绑定方法,那就没必要实现该方法了。
tips:
(1)ES6 - class类的继承机制是:先将父类实例的属性、方法加到this上,然后再用子类的构造函数修改this.
(2)子类必须在constructor方法中调用super方法,否则新建一个实例时会报错,因为super在子类中是用来创建父类的this对象,子类的this通过父类构造函数塑造,得到和父类一样的实例属性和方法。简言之,不调用super,子类就得不到this.
(3)若子类中没有constructor,会被默认添加。
2.componentWillMount()
它在render()方法之前被调用,so,也可以用来设置组件内部的状态,因为它不会再次触发组件的渲染。(但是一般还是推荐在constructor中去初始化状态)
3.render()
生命周期中必须有的方法,它把组件的属性和状态作为输入并返回需要渲染的元素,这个元素可以是原生的DOM组件(如div),也可以是一个自定义的组件。
tips:
在此函数中,不能使用setState()方法,否则会造成死循环;
4.componentDidMount()
在组件挂载之后执行一次,这个时候最适合去异步请求API获取数据,将获取到的数据保存在内部组件的状态中使用。
作用:放置必要的DOM节点,可以网络请求、设置定时器、设置状态以致重渲染等
5.componentWillReceiveProps(nextProps)
在一个更新生命周中被调用。新的属性作为它的输入,可以用this.props与之对比之前之后的属性,基于对比结果去实现不同的行为,或是基于新的属性来设置组件的状态。
tips:
(1)componentWillReceiveProps(nextProps)方法的参数nextProps是一个对象,是在更新时父组件传递过来的props;而在这个方法中的nextProps和子组件中每次传递过来的this.props一样都是最新的;
(2)在更新子组件时,componentWillReceiveProps是最先执行的,可以在其内设置setState(),使得render中的值是最新的state值
reactapp中加一个button,值是test,测试componentWillReceiveProps方法
6.shouldComponentUpdate(nextProps, nextState)
每次组件 因为状态或属性更改而 更新时,就会被调用,此时可以执行某些操作,以控制组件是否需要重新render。
tips:
(1)若在父组件state变化,而不想让子组件重新render,可以在此方法中阻止;
(2)如(1)所说,使用shouldComponentUpdate可以避免不必要的render,它是默认返回true(更新)的;当子组件很多且不是每一个子组件都需要重新render时,不可能一个个组件去写阻止的操作,这时可以涉及到React.PureComponent,它是通过props和state的浅对比去实现shouldComponentUpdate(),若对比发现不一致就会update;反之,不会update。
(React.PureComponent是另外的优化性能的知识点了,还得研究研究…)
常用写法:
shouldComponentUpdate(nextProps, nextState) {
return nextProps.data !== nextState.data;
}
7.componentWillUpdate(nextProps, nextState)
在render()执行之前的最后一个方法,此时已经拥有新的属性和状态,可以进行所需操作,在render渲染之前进行最后的准备呀。
tips:
此方法不要再触发this.setState(),以免造成死循环,如果想要使用新的state更新组件的状态,应该在componentWillReceiveProps中进行相关操作。
8.componentDidUpdate(prevProps, prevState)
在render之后立即调用,可以在这时候进行DOM操作,或是执行更多的异步请求。
tips:
与componentWillUpdate一样,不要在此方法中使用setState()
9.componentWillUnmount()
在组件销毁之前被调用,可以在这时候去执行任何的清理任务。
tips:
(1)销毁组件就是销毁和这个组件有关的状态、事件;
(2)组件内部的状态会随着组件的销毁自动初始化,但是若state保存在redux中,在组件销毁时也要手动销毁state.
三、react生命周期的整体流程是怎样的?执行顺序?
react组件的生命周期总的来说有三个阶段:加载(mount)、更新(update)、卸载(unmount);而每个阶段又有不同的方法,一般地,带有Will字眼的表示该阶段之前发生,带有Did表示在该阶段之后被调用。
1.mount阶段
此阶段表示一个组件实例被创建了,并且插入到DOM中。
在此阶段的方法有:(按顺序调用)
(1)constructor(props):在组件加载之前被调用。
constructor是一个组件类的默认方法,在生成组件实例时会被自动调用
(2)componentWillMount():在组件加载之前被调用。
(3)render():返回一个需要渲染的react元素,这个方法是必须要有的。
(4)componentDidMount():在组件挂载之后被调用。
2.update阶段
此阶段表示一个组件的状态或属性改变了,导致组件重渲染。
此阶段方法有:(按顺序调用)
(1)componentWillReceiveProps():在组件加载完之后,收到新的状态后被调用。
(2)shouldComponentUpdate():组件接收新的属性后调用。
(3)componentWillUpdate():render渲染之前的最后一个方法。
(4)render():同mount阶段的render,只不过在shouldComponentUpdate方法中如果返回false,就不会执行了。
(5)componentDidUpdate():render之后立即调用。
3.unmount阶段
此阶段表示该组件将从DOM中移除。
此阶段的方法有:
componentWillMount():在组件被销毁前调用。
整体流程:
组件第一次渲染之后:
改变父组件state,子组件也会重新渲染:
只是改变子组件A:
销毁子组件A,渲染子组件B:
四、有什么注意点?
1.不会执行的方法:根组件的componentWillReceiveProps()(因为没有父组件给它传递props,更何况props改变呢);
2.只执行一次的方法:constructor(props)、componentWillmount()、componentDidMount();(也就是mount只会在首次渲染时进行,后面组件状态改变也只会执行update的相关方法)
3.可以执行多次的方法:render()、子组件的componentWillReceiveProps()、componentWillUpdate()、componentDidUpdate();
4.父组件updata,它的子组件也会跟着update(除非在shouldComponentUpdate中return false阻止了,子元素不会重新渲染);子组件update,其父组件不需要update;
5.react会限制嵌套更新的次数,以防止无限循环,so,不要在componentWillUpdate和componentDidUpdate中进行setState操作。
五、容易混淆的周期有哪些?
1.constructor(props)与componentWillMount()
两者都是在组件挂载前被调用,都可以用来设置组件的状态,只不过状态一般在前者中初始化,在后者中可以同步设置状态,也不会触发重渲染。
2.componentDidUpdate 与 componentWillReceiveProps?
componentWillReceiveProps(nextProps) {
if(nextProps.count !== this.props.count) {
// doSomething
}
}
componentDidUpdate(prevProps) {
if(prevProps.count !== this.props.count) {
this.setState({ count: this.props.count })
}
}
主要区别:在react生命周期中的调用时机、更新state的方式(同步还是异步)
componentWillReceiveProps:在组件接收新的props之前触发;在props更改时同步更新组件状态
componentDidUpdate:在组件接收新的props(render)之后触发;更新组件状态是异步的
应用场景:当你希望只有在接收到新props时做一些逻辑时,请使用componentWillReceiveProps,如:根据父组件传入的数据初始化或重置某些内部状态。若希望无论props更改还是组件内容状态更改都能触发一些逻辑,那么请使用componentDidUpdate。
总结:虽然知道有哪些周期,什么时候用,怎么用,但是在真正开发过程中,还是想着要查验一番再着手开发。写此文章一是梳理、总结react生命周期函数相关知识,二是鞭策自己实实在在地掌握好一个知识点。
本文纯属自己查找资料学习和通过项目实践练习完善的,如有哪点不当,请不吝指正呀~