- 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
这里对Vue生命周期做了超详细解读,一步一步解析,有什么不足之处希望指出。
一、生命周期函数图
二、具体介绍
1、挂载阶段
-
new Vue()
- 创建Vue实例
- Init Events & Lifecycle 初始化生命周期和事件(但是数据代理还未开始,vm._data还没有,vm中也没有data数据、methods)
-
beforeCreate
- 生命周期钩子(此时:无法通过vm访问到data中的数据、methods中的方法)
// 在beforeCreate中打印vm
beforeCreate() {
console.log("beforeCreate", this);
debugger;
},
- Init injections & reactivity 初始化数据监测、数据代理
-
created
- (此时可以通过vm访问到data中的数据、methods中配置的方法)
created() {
console.log("created", this);
debugger;
},
- Has "el" option? 存在el配置项吗?
- YES
new Vue({
//存在el配置项
el: "#root",
....
- NO
- when vm.$mount(el) is called 等vm.$mount(el)调用时再继续
vm.$mount("root")
// 如果为调用也无el配置那么Vue进行到这一步就终止了,模板也为解析
- Has "temoplate" option ? 存在temoplate配置项吗?
- YES
- 如果写了这个配置项,意味着直接将template模板中的dom替换#root配置项
- YES
<div id="root" :x="n">
<h2 v-text="n"></h2>
<h2>当前的n值是:{{n}}</h2>
<button @click="add">点我n+1</button>
<button @click="bye">点我销毁vm</button>
</div>
new Vue({
el: "#root",
// 存在temoplate配置项,注意temoplate配置项必须包含一个根元素,且根元素不能是<temoplate></temoplate>
template:`
<div>
<h2>当前的n值是:{{n}}</h2>
<button @click="add">点我n+1</button>
</div>
`,
....
}
- NO
- Compile el's outerHTML as template * 解析el配置项的整个dom,如 el: "#root",
<div id="root" :x="n">
<h2 v-text="n"></h2>
<h2>当前的n值是:{{n}}</h2>
<button @click="add">点我n+1</button>
<button @click="bye">点我销毁vm</button>
</div>
-
beforeMount
- 挂载前钩子 (此时:所呈现页面的是未经Vue编译的DOM结构,此时虽未转化为真实dom,但上一步已经转化好虚拟dom,下一步直接拿上方的虚拟dom生成真实dom,所以对DOM的操作,最终都不奏效)
- Create vm.$el and replace "el" with it 创建一个$el替代 el 配置项,这时将内存中的虚拟dom转化为真实dom,并且vue在$el中储存了一份真实dom元素。
-
mounted
挂载完成钩子此时:
1.页面中呈现的是经过Vue编译的DOM。
2.对DOM的操作均有效((尽可能避免)。至此初始化过程结束,一般在此进行:开启定时器、发送网络请求、订阅消息、绑定自定义事件、等初始化操作。
2.更新阶段
- when data changes 当数据改变时
-
beforeUpdate
更新前,此时数据是新的,但是页面是旧的,即:页面和数据尚未同步
例子:点击n+1按钮
<div id="root" :x="n">
<h2 v-text="n"></h2>
<h2>当前的n值是:{{n}}</h2>
<button @click="add">点我n+1</button>
<button @click="bye">点我销毁vm</button>
</div>
beforeUpdate() {
console.log("beforeUpdate", this.n);
debugger;
},
- Virtual DOM re-render and patch
- 虚拟dom重新生成和新旧dom比较
- 根据新数据,生成新的虚拟DOM,随后与旧的虚拟DOM进行比较,最终完成页面更新,即:完成了Model View的更新
-
updated
- 更新完成,此时数据和界面同步,都是新的
<div id="root" :x="n">
<h2 v-text="n"></h2>
<h2>当前的n值是:{{n}}</h2>
<button @click="add">点我n+1</button>
<button @click="bye">点我销毁vm</button>
</div>
beforeUpdate() {
console.log("beforeUpdate", this.n);
debugger;
},
updated() {
console.log("updated", this.n);
},
3、销毁阶段
- when vm.$destroy() is called
- 当 vm.$destroy() 官方参考 被调用时才开始执行销毁阶段
- 注意官方中 vm.$destroy() 完全销毁一个实例。清理它与其它实例的连接,解绑它的全部指令及事件监听器(这里的事件监听器指的是自定义事件,不包括原生事件)
-
beforeDestroy
- 此时: vm中所有的: data、methods、指令等等,都处于可用状态,马上要执行销毁过程,一般在此阶段:关闭定时器、取消订阅消息、解绑自定义事件等收尾操作
- 注意:这里虽然data、methods、指令等等,都处于可用状态,但是再这里执行修改data数据的操作会执行,但是不会再触发更新操作了,也不会再改变data中的数据了
- 如下案例:
<div id="root" :x="n">
<h2 v-text="n"></h2>
<h2>当前的n值是:{{n}}</h2>
<button @click="add">点我n+1</button>
<button @click="bye">点我销毁vm</button>
</div>
methods: {
add() {
console.log("add");
this.n++;
},
bye() {
console.log("bye");
this.$destroy();
},
},
beforeDestroy() {
console.log("beforeDestroy");
console.log("当前n值为", this.n);
this.n = 2;
},
- 可以访问data数据,但是改不了值了
- 调用方法同上代码
beforeDestroy() {
console.log("beforeDestroy");
console.log("当前n值为", this.n);
this.add()
},
- Teardown watchers, child components and event listeners
- 销毁移除watchers,子组件和自定义事件监听器(原生事件监听未取消)
-
destroyed
- 这是实例已经被移除
总结
生命周期钩子虽多,常用的也就几个
常用的生命周期钩子:
1.mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。 2.beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。
关于销毁Vue实例
1.销毁后借助Vue开发者工具看不到任何信息。
2.销毁后自定义事件会失效,但原生DOM事件依然有效。
3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。