vue生命周期和react生命周期总结对比
vue框架和react框架虽然都是虚拟dom,组件化开发,其中的不同点还是蛮多的。首先vue的双向绑定而react则是单项数据流。react使用了jsx语法,让编程更组件话。除了这些他们的生命周期还是不一样的
总归他们都经历了 初始化阶段,运行阶段,销毁阶段。其中运行阶段又分渲染和数据更新两部分
先说下vue的生命周期相对比较简单:
初始化阶段:
1:new Vue(...) : 实例化、组件通过new Vue() 创建出来之后会初始化事件和生命周期,然后就会执行beforeCreate钩子函数,这个时候,数据还没有挂载呢,只是一个空壳,无法访问到数据和真实的dom,一般不做操作
2:beforeCreate,created :挂载数据,绑定事件等等,然后执行created函数,这个时候已经可以使用到数据,也可以更改数据,在这里更改数据不会触发updated函数,在这里可以在渲染前倒数第二次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取
运行阶段:
1:beforemounted:接下来开始找实例或者组件对应的模板,编译模板为虚拟dom放入到render函数中准备渲染,然后执行beforeMount钩子函数,在这个函数中虚拟dom已经创建完成,马上就要渲染,在这里也可以更改数据,不会触发updated,在这里可以在渲染前最后一次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取
2:render ,mounted,beforeupdate,update : 接下来开始render,渲染出真实dom,然后执行mounted钩子函数,此时,组件已经出现在页面中,数据、真实dom都已经处理好了,事件都已经挂载好了,可以在这里操作真实dom。
到这里还不算结束,如果在程序运行中,没有更新数据则无视,一旦有数据更新了,就会走以下两个钩子:beforeupdate,update
当组件或实例的数据更改之后,会立即执行beforeUpdate,然后vue的虚拟dom机制会重新构建虚拟dom与上一次的虚拟dom树利用diff算法进行对比之后重新渲染,当更新完成后,执行updated,数据已经更改完成,dom也重新render完成,可以操作更新后的虚拟dom
销毁阶段:
1:beforeDestroy:当经过某种途径调用$destroy方法后,立即执行beforeDestroy,一般在这里做一些善后工作,例如清除计时器、清除非指令绑定的事件等等
2:destroyed:组件的数据绑定、监听...去掉后只剩下dom空壳,这个时候,执行destroyed,在这里做善后工作也可以
总结起来无外乎就七个当然真实的流程要更细致复杂,有兴趣的可以自己研究源码,实际项目中用到这些完全够了:
newVue()实例化 => beforeCreate,created =>beforemounted,mounted =>(if data change){ beforeupdate,update } => beforedestroyed,destroyed
这里有几点要注意:
1:Vue的编译实际上是指Vue把模板编译成 render 函数的过程
2:render选项参数比template更接近Vue解析器!所以综合排列如下:
<div> <header> <h1>I'm a template!</h1> </header> <p v-if="message"> {{ message }} </p> <p v-else> No message. </p> </div> 会被渲染成: function anonymous() { with(this){return _c('div',[_m(0),(message)?_c('p',[_v(_s(message))]):_c('p',[_v("No message.")])])} }
4:在Vue中,数据更改会导致虚拟 DOM 重新渲染,并先后调用beforeUpdate钩子函数和updated钩子函数
重渲染(调用这两个钩子函数)的前提是被更改的数据已经被写入模板中!!(这点很重要)
var vm = new Vue({ el: '#app', data: { number: 1 }, template: '<div id="app"><p></p></div>', beforeUpdate: function () { console.log('调用了beforeUpdate钩子函数')//控制台没有打印 }, updated: function () { console.log('调用了updated钩子函数')//控制台没有打印 } }) vm.number = 2
// 在模板中使用number这个数据 template: '<div id="app"><p> {{ number }} </p></div>',//添加{{number}}
beforeUpdate: function () { console.log('调用了beforeUpdate钩子函数')//此时被打印出来了 }, updated: function () { console.log('调用了updated钩子函数')//此时被打印出来了
}
也就是说:只有Vue实例中的数据被“写入”到我们的模板中,它的改变才可以被Vue追踪,重渲染从而调用 beforeUpdate钩子函数和updated钩子函数
5:
constructor(props) {
super(props);//如果有父元素继承父元素的props
this.state = {
content:null,
}
}
执行阶段:
1:componentWillMount():这个函数是在render前执行一次,如果在这个函数中调用setState改变某些状态机,react会等待setState完成后再渲染组件
需要注意的是:如果有子组件,子组件也有此钩子函数,并且会等待父级的函数调用完成后才会调用子组件的componentWillMount
2:render():主要用来渲染挂载组件。也是组件的最核心函数,和其它钩子函数不一样(上一个钩子只执行一次)render函数是比较频繁被调用的:(1)初始化加载页面(2)状态机改变setState ( 3 ) 接收到新的props(父组件更新)
需要注意的是render钩子内不要改变状态机state
3:componentDidMount():render之后就会调用,它也和componentWillMount一样只调用一次。它的主要作用就是渲染挂组件可以使用refs了。(如果需要操作dom时)
需要注意的是子组件也有componentDidMount,不过和willMount不同的是子组件会在父组件调用前调用didMount
如果在该函数内修改state,render就会被再次调用。
如果不想多次渲染render,可以选择将setState放在willMount内。
它比较适合数据初始化后,再异步的请求后端接口或其它数据需要再次更新页面响应式的时候,请求的接口可以直接放在这里
数据更新监测阶段:(如果有数据改变的话):
1:componetWillReceiveProps():上面的是第一遍流程,当后期有新的props传入,react会调用willReceiveProps钩子,换句话说,父组件内state值改变了,就会重新渲染render,父组件一render,子组件的props就更新了,也就调用了此钩子
它的作用和didMount相似,也可以渲染挂在组件使用refs
需要注意的是:react初次渲染时,该函数并不会被触发,因此有时该函数需要和componentWillMount或componentDidMount组合使用;
使用该函数一定要加nextProps参数:componentWillReceiveProps(nextProps),首次使用了解的可以先打印结果(console.log(nextProps))
2:shouldComponentUpdate() : 每次执行setstate都会执行该函数,也就是说只要一改变状态,接收到新的state或props 就会调用此更新机制:它有默认的返回值 true,有两个参数:新的props,新的state:sholdComponentUpdate(nextprops,nextstate)
它的作用是:如果有些变化不需要重新render组件,可以在该函数中阻拦。
注意:该方法在初始化渲染的时候不会调用,在使用 forceUpdate 方法的时候也不会
3:componentWillUpdate():每次执行setstate后,如果setState跟新改变了props,state也就是说通过setstate改变为新的prop,state值,它就会被调用,注意是在重新render前,所以它作用也是在获取新的prop,state后,为下次render做准备工作
注意:不能再该函数中通过this.setstate再次改变状态机,如果需要,则在componentWillReceiveProps函数中改变
4:componentDidUpdate():重新渲染后调用,在初始化渲染的时候该方法不会被调用
作用:使用该方法可以在组件更新之后如果还想操作DOM 元素的话可以在此写入操作
最后是销毁阶段,这里只有一个componentWillUnmount()
在该方法中执行任何必要的清理,比如无效的定时器,或者清除在 componentDidMount 中创建的 DOM 元素。
1:当一个页面中存在子父组件时,要注意componentWillMount和componentDidMount的使用,如果需要先加载父组件(获取网路数据),父组件传值给子组件,再加载子组件(获取网路数据),那么不能同时在子父组件中使用componentDidMount获取网路数据,因为会先执行子组件的componentDidMount,会由于未得到父组件的传值而报错;解决方案:(1)父组件:componentWillMount,子组件:componentDidMount;(2)父组件:componentDidMount,子组件:componentWillMount;
他们的真确顺序应该是:父componentWillMount => 子componentDidMount=>父componentDidMount=>子componentWillMount
2:当一个页面中如要实现两个组件的联动效果,(比如:页面中包含componentA和componentB,单击componentA,componentB内容对应变化,componentA向componentB通过redux传参,那么componentB首次会通过componentDidMount接收,然后再通过componentWillReceiveProps接收)
需要额外注意的是:react17版本以后:有些生命周期基本弃用了(过时):不建议使用因为强制使用它们还是会有效
1:componentWillMount():建议在constructor()内初始化state,如果是订阅类建议在componentDidMount()内进行
2:componentWillReceiveProps():如果执行数据提取以响应props的更改,请改为componentDidupdate()生命周期,如果是为了在props更改后重置某些state,请考虑组件完全受控或使用key使组件不受控来代替
3:componentWillUpdate():不能在此调用setState(),通常情况下此方法替换成componentDidupdate()。如果想要读取dom信息(如保存滚动位置)可将逻辑移至getSnapshotBeforeUpdate()中
另外还有个生命周期是不常用的:shouldcomponentUpdate:只作为性能优化的方式存在,不要在这里做阻止渲染等操作会出现bug
注意,你不能此方法中调用 this.setState()
;在 UNSAFE_componentWillUpdate()
返回之前,你也不应该执行任何其他操作(例如,dispatch Redux 的 action)触发对 React 组件的更新
通常,此方法可以替换为 componentDidUpdate()
。如果你在此方法中读取 DOM 信息(例如,为了保存滚动位置),则可以将此逻辑移至 getSnapshotBeforeUpdate()
中。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!