组件生命周期:组件从被创建到挂载到页面中运行,再到组件不用时卸载的过程。
钩子函数,使开发者的代码可以在固定阶段执行。
注意:只有类组件才有生命周期。函数组件每次都是重新运行函数,旧的组件即刻被销毁。
React
组件的生命周期组件的生命周期主要包括三阶段
- 挂载阶段
- 更新阶段
- 卸载阶段
挂载阶段:组件被创建,执行初始化,并被挂载到DOM中,完成组件的第一次渲染(已经插入真实DOM)
更新阶段:组件被挂载到DOM之后,props
和state
都可以引起组件的更新(重新渲染)
卸载阶段:在组件被卸载前调用(已经移出真实DOM)
constructor()
ES6
中class
的构造方法,组件被创建时会首先调用组件的构造方法
初始化state
,以及为事件处理程序绑定this
componentWillMount() 不建议使用,已经废用了,是在组件被挂载在DOM之前调用,而且只会被调用一次
render()
根据组件的props
和state
返回一个React
元素
渲染UI
注意:在render()
里面不能调用setState()
实际上是调用React.creatElement()
componentDidMount()
在组件被挂载在DOM之后调用,而且只会被调用一次。
可以调用 setState()
向服务器端发送网络请求,以及处理依赖DOM节点的操作
- 父组件调用
render
方法- 组件调用
this.setState
componentWillReceiveProps()
props
引起的组件更新过程中被调用state
引起的组件更新并不会触发该方法的执行shouldComponentUpdate()
用于决定组件是否继续执行更新过程,默认值为true
可以用来减少组件不必要的渲染,从而优化组件的性能
对比前后两个props
和state
是否相同
componentWillUpdate()
组件初始化时不调用
只有在组件将要更新时才调用,此时可以修改state
render()
根据组件的props
和state
返回一个React
元素
渲染UI
注意:在render()
里面不能调用setState()
实际上是调用React.creatElement()
componentDidUpdate()
componentWillUnmount()
componentDidCatch(error, errorInfo)在子组件发生错误是被调用。
error
和errorInfo
两个参数, error
表示抛出的错误errorInfo
带有 componentStack key
的对象,其中包含有关组件引发错误的栈信息简记,容易记住的生命周期方法
单组件初始化
constructor
-> componentWillMount
-> render
-> componentDidMount
常用 constructor
-> render
-> componentDidMount
单组件更新state
shouldComponentUpdate
-> componentWillUpdate
-> render
-> componentDidUpdate
单组件卸载
componentWillUnmount
父子组件初始化
父组件constructor
-> 父组件componentWillMount
-> 父组件render
-> 子组件constructor
-> 子组件componentWillMount
-> 子组件render
-> 子组件componentDidMount
-> 父组件componentDidMount
父组件更新state
父组件shouldComponentUpdate
-> 父组件componentWillUpdate
-> 父组件render
-> 子组件componentWillReceiveProps
-> 子组件shouldComponentUpdate
-> 子组件componentWillUpdate
-> 子组件render
-> 子组件componentDidUpdate
-> 父组件componentDidUpdate
子组件更新state
子组件shouldComponentUpdate
-> 子组件componentWillUpdate
-> 子组件render
-> 子组件componentDidUpdate
父子组件卸载
父组件componentWillUnmount
-> 子组件componentWillUnmount
React
组件的生命周期(新版)新版本主要是React 16.3+
新版本的
react
生命周期函数主要变化
- 去除了三个不安全函数
componentWillMount
、componentWillReceiveProps
、componentWillUpdate
- 新增了三个生命周期函数
static getDerivedStateFromProps
、getSnapshotBeforeUpdate
、static getDerivedStateFromError
版本说明
componentWillMount
,componentWillReceiveProps
,componentWillUpdate
表示使用这些生命周期的代码,有可能在未来的 React 版本中存在缺陷,可能会影响未来的异步渲染。
React 16.3
版本:为不安全的生命周期引入别名 UNSAFE_componentWillMount,UNSAFE_componentWillReceiveProps 和 UNSAFE_componentWillUpdate。(旧的生命周期名称和新的别名都可以在此版本中使用)
React 16.3
之后的版本:为 componentWillMount,componentWillReceiveProps 和 componentWillUpdate 启用弃用警告。(旧的生命周期名称和新的别名都可以在此版本中使用,但旧名称会记录DEV模式警告)
React 17.0
版本:推出新的渲染方式—异步渲染( Async Rendering),提出一种可被打断的生命周期(实际 dom 挂载之前的虚拟 dom 构建阶段),去掉的三个生命周期 componentWillMount,componentWillReceiveProps 和 componentWillUpdate。(从这个版本开始,只有新的“UNSAFE_”生命周期名称将起作用)
constructor -> getDerivedStateFromProps -> render -> componentDidMount
- componentWillMount 不再使用
- getDerivedStateFromProps 替换 componentWillMount
static getDerivedStateFromProps(props, state) 在组件初始化和组件更新时都会被调用
接收state
和props
两个参数
state
null
来表示接收到的props
没有变化,不需要更新 state静态方法,所以该生命周期钩子函数内部没有this
将父组件传递过来的props
映射到子组件的state
上
注意:子组件通过 setState 更新自身状态时,不会改变父组件的 props
getDerivedStateFromProps -> shouldComponentUpdate -> render -> getSnapshotBeforeUpdate -> componentDidUpdate
- 新增 getDerivedStateFromProps
- 替换 componentWillUpdate 为 getSnapshotBeforeUpdate
getSnapshotBeforeUpdate(prevProps, prevState) 在组件更新时被调用。被调用于 render之后、更新 DOM 和 refs 之前。
必须有返回值,返回值将作为 componentDidUpdate 函数方法的第三个参数。
通过this.props
和this.state
是最新的数据,函数的参数prevProps
和prevState
是更新前的数据。可以通过比较,做逻辑处理。
componentWillUnmount
无变化
static getDerivedStateFromError(error) 在后代组件抛出错误后被调用。 它将抛出的错误作为参数,并返回一个值以更新 state。
在渲染DOM之前调用,当我们遇到子组件出错的时候可以渲染备用UI,常用作错误边界。
componentDidCatch
是在DOM渲染完后才会调用,可以用来输出错误信息或上传一些错误报告。
React
生命周期函数调用顺序单组件初始化
constructor
-> getDerivedStateFromProps
-> render
-> componentDidMount
单组件更新state
getDerivedStateFromProps
-> shouldComponentUpdate
-> render
-> getSnapshotBeforeUpdate
-> componentDidUpdate
单组件卸载
componentWillUnmount
父子组件初始化
父组件constructor
-> 父组件getDerivedStateFromProps
-> 父组件render
-> 子组件constructor
-> 子组件getDerivedStateFromProps
-> 子组件render
-> 子组件componentDidMount
-> 父组件componentDidMount
父组件更新state
父组件getDerivedStateFromProps
-> 父组件shouldComponentUpdate
-> 父组件render
-> 子组件getDerivedStateFromProps
-> 子组件shouldComponentUpdate
-> 子组件render
-> 子组件getSnapshotBeforeUpdate
-> 父组件getSnapshotBeforeUpdate
-> 子组件componentDidUpdate -> 父组件componentDidUpdate子组件更新state
子组件getDerivedStateFromProps
-> 子组件shouldComponentUpdate
-> 子组件render
-> 子组件getSnapshotBeforeUpdate
-> 子组件componentDidUpdate
父子组件卸载
父组件componentWillUnmount
-> 子组件componentWillUnmount
VUE@2
组件的生命周期组件的生命周期
- 初始化阶段
- 编译阶段
- 挂载阶段
- 更新阶段
- 销毁阶段
beforeCreate
在实例初始化之后,进行数据侦听和事件/侦听器的配置之前同步调用。
实例的data
和methods
等配置还未初始化,无法调用,只能使用一些默认事件。
created
在实例创建完成后被立即同步调用。
实例已完成对选项的处理,意味着以下内容已被配置完毕:数据侦听、计算属性、方法、事件/侦听器的回调函数。
挂载阶段还没开始,且 $el.property 目前尚不可用。
模板还没有编译,不能获取到DOM。
VUE对象是否指定el
VUE对象是否指定template
将编译到
render
函数中
beforeMounted
挂载开始之前被调用,相关的 render 函数首次被调用。
函数在模板渲染之前调用,也就是DOM节点挂载到真实DOM树之前调用。
此模板进行编译,会调用render
函数生成虚拟DOM
,同样无法获取DOM节点(此时只存在虚拟DOM
,还在JS级别)。
mounted
实例被挂载后调用,这时 el 被新创建的 vm.$el 替换。
注意:mounted
不会保证所有的子组件也都被挂载完成。
执行该钩子函数时,模板编译完成,而且挂载到真实DOM树上面去了,也就是页面可以显示了。(该钩子在服务器端渲染期间不被调用)
单组件初始化
单组件更新
单组件卸载
父子组件初始化
父组件更新data,此data没传递给子组件
父组件更新data,此data传递给了子组件
子组件更新data
父子组件卸载
beforeUpdate
在数据发生改变后,DOM 被更新之前被调用。
这里适合在现有 DOM 将要被更新之前访问它,比如移除手动添加的事件监听器。
该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务器端进行。
该钩子函数在data数据发生变化之后调用,data
里面的数据已经是最新的了,但是页面上DOM还没有更新最新的数据。
updated
在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用。
当这个钩子被调用时,组件 DOM 已经更新,可以执行依赖于 DOM 的操作。要相应状态改变,通常最好使用计算属性或 watcher 取而代之。
注意,updated 不会保证所有的子组件也都被重新渲染完毕。如果你希望等到整个视图都渲染完毕,可以在 updated 里使用 vm.$nextTick
该钩子函数会在data数据更新之后执行,而且此时页面也渲染更新完成了,显示的就是最新的数据。
注意:不要在updated
中修改data
数据,很容易造成死循环。
beforeDestroy
实例销毁之前调用。实例仍然完全可用。
在这个钩子函数里面解除一些全局或者自定义事件。
destroyed
实例销毁后调用。
该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。
VUE@2生命周期
{{ message }}
{{ msg }}
errorCaptured
在捕获一个来自后代组件的错误时被调用。
钩子函数的三个参数:错误对象、发生错误的组件实例、一个包含错误来源信息的字符串。
该钩子函数可以返回 false 以阻止该错误继续向上传播。
activated
deactivated
VUE@3
组件的生命周期setup() : 开始创建组件之前,在 beforeCreate 和 created 之前执行,创建的是 data 和 method
onBeforeMount() : 组件挂载到节点上之前执行的函数;
onMounted(): 组件挂载完成后执行的函数;
onBeforeUpdate(): 组件更新之前执行的函数;
onUpdated(): 组件更新完成之后执行的函数;
onBeforeUnmount(): 组件卸载之前执行的函数;
onUnmounted(): 组件卸载完成后执行的函数;
onActivated(): 被包含在
中的组件,会多出两个生命周期钩子函数,被激活时执行;
onDeactivated(): 比如从 A 组件,切换到 B 组件,A 组件消失时执行;
onErrorCaptured(): 当捕获一个来自子孙组件的异常时激活钩子函数。
生命周期函数的运行基本顺序是
setup
->beforeCreate
->created
单组件初始化
setup
-> created
-> onBeforeMount
-> onRenderTracked
-> onMounted
单组件更新
onRenderTriggered
-> onBeforeUpdate
-> onUpdated
单组件卸载
onBeforeDestroy
-> onDestroyed
父子组件初始化
父组件更新data,此data没传递给子组件
父组件更新data,此data传递给了子组件
子组件更新data
父子组件卸载
VUE@2
与VUE@3
对比vue@2 | vue@3 |
---|---|
beforeCreate | setup(()=>{}) |
created | setup(()=>{}) |
beforeMount | onBeforeMount(()=>{}) |
mounted | onMounted(()=>{}) |
beforeUpdate | onBeforeUpdate(()=>{}) |
updated | onUpdated(()=>{}) |
beforeDestroy | onBeforeUnmount(()=>{}) |
destroyed | onUnmounted(()=>{}) |
activated | onActivated(()=>{}) |
deactivated | onDeactivated(()=>{}) |
errorCaptured | onErrorCaptured(()=>{}) |
Vue@2
和Vue@3
钩子变化不大,使用setup()
钩子来替代 beforeCreate、created
两个钩子函数。VUE
与React
生命周期对比对比的目的在于处理相同与不同
Vue
、React
生命周期函数基本类似,组件的创建、更新、卸载都有对应的函数方法调用。
单组件、父子组件渲染类似。
参数比较:
Vue
生命周期函数除了 errorCaptured 都是没有参数的。React
生命周期函数都有参数并且能访问到旧的或新的props和state。组件更新
React
父组件更新,子组件一定都会更新渲染,除非自己手动优化(继承PureComponent
或者实现shouldComponent
方法)。Vue
中除非子组件依赖父组件的数据改变了,否则子组件是不会重新渲染的。组件更新处理
Vue
数据改变就一定会重新渲染,无法阻止。React
能通过 shouldComponent
方法来决定是否需要渲染。错误处理
Vue
在组件报错的时候页面还是会渲染,只是引发出错的地方可能数值不对。React
组件报错的时候会导致页面空白,编译报错将提示信息到浏览器(getDerivedStateFromError 做边界处理)。生命周期影响
React
的生命周期函数,大多都在处理当前的props
与state
VUE
相比较多了缓存的生命周期函数 activated、deactivated 和用于开发调试的renderTracked、renderTriggered生命周期函数。