Vue生命周期
Posted fiona-zhong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue生命周期相关的知识,希望对你有一定的参考价值。
Vue实例有一个完整的生命周期,即开始创建---》初始化数据---》编译模板---》挂载DOM---》渲染---》更新---》渲染---》销毁等一系列过程,这一系列过程我们称之为Vue实例的生命周期,钩子就是在某个阶段给你一个做某些处理的机会。
先上一张图来只管的感受一下Vue的生命周期:
Vue生命周期主要以下几个钩子函数:
1、beforeCreate():
我们在实例化Vue的时候(new Vue),会首先初始化事件和生命周期,然后会调用这个钩子函数,这个钩子函数我们一般不会使用它去做太多功能。
这个时候,数据data和el还没有挂载到Vue实例上,只是一个空壳,是无法访问到数据data和真实的dom挂载元素el的。
2、created():
在实例创建后,会挂载数据data和绑定事件。然后会调用created钩子函数,所以此时,实例已经完成了基本配置。
这里可以使用数据data,也可以修改数据data,且这里的修改数据是不会触发updated钩子函数的。
一般可以在这里做数据初始化的操作,不过如果请求过多且全部都是同步请求的话,可能会导致界面出现短暂的空白阻塞,所以是否在这里初始化请求数据,看个人需求。
但是dom还是没有挂载到界面,所以$el依旧是不可见的。
3、beforeMount():
实例基本配置完成后,会去判断实例是否有挂载el对象,如果有的话,就继续向下编译,如果没有的话,就停止编译,即意味着停止了生命周期,直到我们在该实例上手动挂载el,即调用vm.$mount("#app")
这个钩子函数,我们基本上也是不会去使用它的。
它的作用主要是用来检查,Vue实例中有没有自定义template参数选项,如果有的话,会将其作为模板template编译成虚拟dom放到render函数中准备渲染;但是如果我们已经自定义了render函数,会使用我们定义的render函数的返回值渲染到界面;如果都没有,就将挂载元素el的html作为模板template编译。
可以看到自定义render函数优先级 > 自定义template参数选项 > 挂载元素el的outer HTML
此時,我們就可以理解,为啥要先去判断是否有挂载el对象了,因为我们需要通过el找到对应的out template
找到实例或组件对应的模板,编译成虚拟dom放入到render函数中,准备渲染,然后会执行beforeMount钩子函数,这个函数中,虚拟dom已经创建完成,即将渲染。这里我们还可以修改data且不触发updated钩子函数,这将是我们不触发updated钩子函数去修改data的最后一次机会了,后面所有的修改都将触发updated钩子函数。
<div id=‘app‘>{{a}}</div> new Vue({ data(){ return { a:100, } }, template:"<h1>{{a}}</h1>", render(createElement){ return createElement("h2",{ attrs:{ id:"aaa" }, style:{ border:"1px solid red" }, on:{ click(){ alert(1) } } },‘this is a render fn‘) }, beforeMount(){ // 这里会去检查我们是否有自定义render(),有的话,会将render函数的返回值渲染到app中,如果没有render函数,会去查找是否有自定义template,有的话将template值渲染到app中 } })
4、mounted():
接下来render后,渲染出真实dom,然后执行mounted()钩子函数。
此时,组件已经出现在页面中,数据,真实dom都已经处理好了,事件也已经挂载好了,可以操作真实dom对象了。
这里修改数据data,会触发updated钩子,需要注意的是,vue中所有的数据渲染都是异步的,这里我们通过 this.$el.innerHTML 是拿不到更新后的内容的,需要通过vue.$nextTick 去获取
<div id=‘app‘>{{a}}</div> new Vue({ el:"#app", data(){ return { a:"hello" } }, mounted(){ this.a = 100; console.log(this.$el.innerHTML); this.$nextTick(()=>{
// 会在updated钩子函数之后执行 console.log("nextTick->",this.$el.innerHTML) }) } });
5、beforeUpdate() 和 updated():
当组件和实例中的数据发生变化后,会立即执行beforeUpdate钩子,然后vue的虚拟dom机制会重新创建新的虚拟dom,与上一次的虚拟dom树利用diff算法进行对比后,重新渲染组件。
更新完成后,会执行updated钩子,数据和组件都已经更新完成,这是可以操作更新后的dom
注意:updated()钩子函数中不能再修改数据,否则会造成死循环
7、beforeDestroy():
当经过某种途径调用$destroy()后(如组件销毁,路由切换或者手动调用vm.$destroy()),在实例销毁之前,会立即触发beforeDestroy钩子。
此时实例还是完全可用的。
一般在这里做一些清扫工作,如清除定时器,清除非指令绑定事件等等。
<div id="app"> <self-comp></self-comp> <div> <template> <div id="selfComp"> <button @click="destroy">销毁</button> <h1>{{count}}</h1> </div> </template> Vue.component("selfComp",{ template:"#selfComp", data(){ return { count:1, } }, timer:null, methods:{ destroy(){ this.$destroy(); } }, mounted(){ this.$options.timer = setInterval(function(){ this.count+=1; }.bind(this),1000); }, beforeDestroy(){ clearInterval(this.$options.timer); } }) new Vue({}).$mount("#app")
以上是关于Vue生命周期的主要内容,如果未能解决你的问题,请参考以下文章
在不存在的片段上调用片段生命周期和 onCreate 的问题