【vue系列-05】vue的生命周期(详解)
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
深入理解vue的生命周期
一vue的生命周期
在vue的官网中vue的生命周期如下图所示主要经历了如下几个阶段分别是 beforeCreatecreatedbeforeMountmountedbeforeUpdateupdatebeforeDestroydestroy 主要由这八个阶段组成。
这边的vue实例和java中的spring中的bean对象一样都有一套完成的加载流程以及一套完整的生命周期vue的生命周期的总览如下图接下来通过下面这张图片对每个阶段做一个具体的分析。
1创建流程
创建流程主要由两个阶段组成一个是beforeCreate另一个是created。这里的创建之前和创建之后指的是 数据监测和数据代理 的创建之前和创建之后而不是vm因为此时的vm还并没有创建出来。
1.1beforeCreate
在创建完这个Vue实例之后首先会进入一个初始化阶段此阶段初始化生命周期和事件但是在此阶段数据代理还并没有开始。在初始化阶段之后就会经历vue的 beforeCreate 阶段代码如下其函数在vue实例中和这个data是平级的。
<div id="root">
<h1>当前的值n为:{{n}}</h1>
<button @click = "add">点我+1</button>
</div>
new Vue({
el:'#root',
data:{n:1},
methods:{add(){ this.n++ }},
beforeCreate(){
console.log('beforeCreate');
console.log(this);
debugger;
}
})
其结果如下由于数据代理并未初始化因此这个阶段是拿不到vm对象以及_data数据的因此在第一个 beforeCreate 阶段中无法通过这个vm对象访到data中的数据和methods中方法。并且在下面的结果可以的得知是并没有 _data 的并且也没有data数据中的 n 值也没有add方法
1.2created
在beforeCreate之后还是处于一个初始化阶段即init Injections & reactivity 阶段。该阶段就是初始化这个数据监测和数据代理的这样就可以获取到代理对象解析模板了。
<div id="root">
<h1>当前的值n为:{{n}}</h1>
<button @click = "add">点我+1</button>
</div>
new Vue({
el:'#root',
data:{n:1},
methods:{add(){ this.n++ }},
...
created(){
console.log('created');
console.log(this);
debugger;
}
})
在初始化代理对象之后就可以进入这个 created 阶段了。通过控制台的打印可以得知已经可以加载这个_data对象由于初始化了这个数据监测所以这个 get和set的两个方法也有了由于初始化了这个数据代理因此这个data中的n和method中的add都可以加载成功了
此时是可以通过vm对象获取到 data 中的属性和method 中的方法的。
2挂载流程
在创建流程之后还会有一个阶段来解析这个Vue模板看下面的流程就是开始解析模板生成虚拟DOM到内存中此时页面还不能显示好解析的内容即还没有转成真实DOM。接下来就会进入两个挂载流程一个是beforeMount另一个是mounted。
接下来就是主要分析一下这两个挂载的流程以及所做的事情。
2.1beforeMount
在挂载的函数上打一debugger可以发现在执行到这这个 beforeMount 的时候对应的页面是并没有进行解析的因此可以初步确认这个挂载前的这个函数中的DOM元素是未经过Vue编译的因此所有对Dom的操作都是不能奏效的。实际上这个DOM元素是Vue已经解析完成的真实DOM但是此时的vue还没来的及将这些DOM向页面中存放。
<div id="root">
<h1>当前的值n为:{{n}}</h1>
<button @click = "add">点我+1</button>
</div>
new Vue({
el:'#root',
data:{n:1},
methods:{add(){ this.n++ }},
...
beforeMount(){
console.log('beforeMount');
console.log(this);
debugger;
}
})
通过这个debugger的断点此时的页面如下可以发现页面上的值是原生的html并不是经历过vue模板解析的值因此可以得知上面还没有vue解析出来的DOM同时也可以证明此时vue还没有来得及将编译的DOM存到页面中
2.2mounted
在经过这个 beforeMount 的阶段之后Vue会将el中的数据存放在 $el 上类似于做一个副本此时会将内存中的虚拟DOM转化为真实DOM存在页面中。
在将真实的DOM插入页面之后Vue就会开始调用这个 mounted 挂载的这个函数了。因为页面中已经呈现的是经过Vue编译的DOM了因此在这个函数中对DOM的操作均有效到此为止初始化阶段正式结束。
<div id="root">
<h1>当前的值n为:{{n}}</h1>
<button @click = "add">点我+1</button>
</div>
new Vue({
el:'#root',
data:{n:1},
methods:{add(){ this.n++ }},
...
mounted(){
console.log('mounted');
console.log(this);
//操作DOM元素
document.querySelector('h1').innerText = 'zhs'
}
})
通过上面的代码以及下面的结果可知在挂载阶段DOM元素已经是全部经过Vue解析的因此展示在页面的值都是解析后的值并且在这个阶段也可以有效的操作DOM元素。
在这个挂载函数中一般会进行这些操作:开启定时器发送网络请求订阅消息绑定自定义事件等操作
3更新流程
在挂载流程解释之后接下来会进入更新流程更新流程主要分为 beforeUpdate 和 updated 两个流程。
3.1beforeUpdate
就是说只要data中的数据发生改变那么就会触发这个钩子函数但是在这个阶段中页面上渲染的数据和被改变的数据没有保持同步就是页面还没有来得及展示被修改的值。
<div id="root">
<h1 id='h1'>当前的值n为:{{n}}</h1>
<button @click = "add">点我+1</button>
</div>
new Vue({
el:'#root',
data:{n:1},
methods:{add(){ this.n++ }},
...
beforeUpdate(){
//现在被修改的值
console.log("vue实例数据是:" + this.n);
debugger;
}
})
通过下面的代码和下面的结果可知vue实例中的数据和页面的数据是不一致的。
3.2updated
在这个beforeUpdate结束之后会经过一个 Virtual DOM re-render and patch 阶段在这个阶段就会生成新的虚拟DOM随后通过diff算法实现新旧的虚拟DOM的比较最终完成页面的更新。
此时这个数据是新的页面也是最新的并且数据和页面是保持一致的。
<div id="root">
<h1 id='h1'>当前的值n为:{{n}}</h1>
<button @click = "add">点我+1</button>
</div>
new Vue({
el:'#root',
data:{n:1},
methods:{add(){ this.n++ }},
...
updated(){
console.log(updated);
//现在被修改的值
console.log("vue实例数据是:" + this.n);
debugger;
}
})
通过上面的代码和下面的结果可知数据和页面是同步的
4销毁流程
接下来就进入最后一个流程销毁流程销毁用官网的话来说:清理它与其他实例的链接解绑他的全部指令以及时间监听器。主要是由两个部分组成分别是 beforeDestry 和 destroyed
4.1beforeDestry
销毁需要调用这个 this.$destroy() 方法来实现。在销毁 beforeDestry 的这个函数中销毁的实例中的所有的datamethods还有指令等等都是处于可用状态但是不能对实例中的具体的数据和方法进行一个操作。
<div id="root">
<button @click = "bey">点我销毁</button>
</div>
new Vue({
el:'#root',
data:{n:1},
methods:{
bey(){this.$destroy()}
},
...
beforeDestroy(){
console.log('beforeDestry');
}
})
4.2destroyed
在到了这个最终的销毁方法之后vue实例算是彻底的被销毁了但是页面上的数据是还在的但是不能操作上面的数据了。
...
destroyed(){
console.log('destroyed');
}
总代码如下
<!-- 一个容器,可以用于接收vue实力传来的数据然后展示 -->
<div id="root">
<h1 id="h1">当前的值n为:{{n}}</h1>
<button @click = "add">点我+1</button>
<button @click = "bey">点我销毁</button>
</div>
<script type="text/javascript" >
Vue.config.productionTip = false, //阻止vue启动时提示生产提示
new Vue({
el:'#root',
data:{n:1},
methods:{
add(){ this.n++ },
bey(){this.$destroy()}
},
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('beforeDestry');
console.log("vue实例准备销毁了");
},
destroyed(){
console.log('destry');
console.log("vue实例已经销毁了");
}
})
</script>
二vue的生命周期总结
常用的生命周期钩子:
1mounted:发送ajax、启动定时器、绑定自定义事件、消息订阅等初始化操作
2beforeDestroy:清除定时器、解绑自定义事件、取消消息订阅等
销毁vue实例之后
1借助vue开发者工具是看不到任何消息的
2销毁后自定义事件会失效但是原生的DOM事件依然有效
3一般不要在beforeDestory中操作数据因为该钩子并不会触发更新流程