Vue生命周期函数(钩子)执行顺序
从上图可知主要为八大生命周期钩子:beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed。执行顺序为上图所示顺序。
验证生命周期钩子执行顺序:
new Vue({
el: '#app',
router,
store,
data: {
greet: 'hello world'
},
template: '
beforeCreate() {
console.log('------beforeCreate------')
},
created () {
console.log('------created------')
},
beforeMount () {
console.log('------beforeMount------')
},
mounted () {
console.log('------mounted------')
},
beforeUpdate () {
console.log('------beforeUpdate------')
},
updated() {
console.log('------updated------')
},
beforeDestroy() {
console.log('------beforeDestroy------')
},
destroyed() {
console.log('------destroyed------')
}
})
打印结果如下:
我们发现只打印出了四个钩子中的信息,即首次创建实例过程中,只执行四个生命周期钩子,beforeCreate、created、beforeMount、mounted,执行顺序与生命周期图一致,beforeUpdate与updated是在数据更新时候执行,而beforeDestroy与destroyed是在实例销毁的时候执行。在每个生命周期钩子执行期间或者之后都会进行一些相关的操作,以下分析这期间都做了什么工作。
生命周期函数(钩子)详解
结合生命周期图,进一步分析。
new Vue()
创建一个vue实例,然后init初始化event 和 lifecycle,期间分别调用了3个初始化函数(initLifecycle(), initEvents(), initRender()),初始化了生命周期,事件以及定义createElement函数。在初始化生命周期时,定义了一些属性,比如生命周期状态_isMounted ,_isDestroyed ,_isBeingDestroyed,表示keep-alive中组件状态的_inactive。初始化event,定义了off、on几个函数。createElement函数是在初始化render时定义的(调用了initRender函数)。
beforeCreate
beforeCreate执行结束后,数据初始化,定义data数据、方法及事件,并且通过Object.defineProperty()来实现数据劫持以及给组件实例配置watcher观察者实例(发布-订阅者模式),即实现数据双向绑定,后续当数据发生变化时,感知数据变化并完成页面渲染。
示例:
beforeCreate() {
console.log('------beforeCreate------')
console.log(this.greet)
console.log(this.$el)
}
created
该钩子中我们可以拿到data下的数据以及methods下的方法了。在这个钩子中,我们可以开始调用方法进行数据请求了。
created执行结束后,判断当前是否有el参数,如果有,继续判断是否有template参数。如果没有el,那么我们会等待调用$mount(el)方法(即手动挂载)。
确保有了el后,往下判断当有template参数时,将template模板转换成render函数(在此之前判断当前是否有render函数,如果有,则会直接去渲染当前的render函数,如果没有则查找是否有template模板),如果没有template,将直接获取到的el(也就是我们常见的#app)编译成template,然后在将这个template转换成render函数。
示例:
created () {
console.log('------created------')
console.log(this.greet)
console.log(this.$el)
}
beforeMount
在creted到beforeMount之间,最主要的工作就是将模板或者el转换为render函数。这里需要注意,不管是用el,还是用template,或者是.vue文件(如果是.vue文件,会先编译成template),最终都会被转换为render函数。
beforeMount执行后,开始渲染render函数了,此时先产生一个虚拟dom(用于后续数据发生变化时,新老虚拟dom对比diff算法),进行保存,然后再开始将render渲染成为真实的dom,替换掉原来的vm.el append到我们的页面内。基本流程走完。
示例:
beforeMount () {
console.log('------beforeMount------')
console.log(this.greet)
console.log(this.$el)
}
此时$el为“#app”中对应的元素:
之后向下检查到template,用其将#app替换,转换成render函数,渲染成真实dom后,替换了原来的$el。往下观察mounted打印信息。
mounted
执行mounted,将标识生命周期的一个属性_isMounted 置为true。在mounted钩子内,我们可以操作dom,因为这个时候dom已经渲染完成了。
示例:
mounted () {
console.log('------mounted------')
console.log(this.greet)
console.log(this.$el)
}
上面说到检查到template,转换成render函数,渲染成真实dom后,替换了原来的$el(#app)。
beforeUpdate、updated
最后
好了,这就是整理的前端从入门到放弃的学习笔记,还有很多没有整理到,我也算是边学边去整理,后续还会慢慢完善,这些相信够你学一阵子了。
做程序员,做前端工程师,真的是一个学习就会有回报的职业,不看出身高低,不看学历强弱,只要你的技术达到应有的水准,就能够得到对应的回报。
学习从来没有一蹴而就,都是持之以恒的,正所谓活到老学到老,真正懂得学习的人,才不会被这个时代的洪流所淘汰。