1 生命周期
1) 什么是生命周期
一个Vue实例从创建到销毁的整个过程. Vue组件也可看成一个Vue实例

2) 生命周期函数(钩子)
在生命周期中, 特定的时间点会被自动执行的函数
- beforeCreate()
- created()
- beforeMount()
- mounted()
- beforeUpdate()
- updated()
- beforeDestroy()
- destroyed()
3) Vue实例到底做了一件什么事
Vue实例的最主要的工作是
将模板内容编译, 替换掉原有的html节点
- 模板内容: 由
template选项确定 - 编译: 由
render()方法, 将模板编译成在真实的DOM, 渲染在html文件中 - 原有的html节点: 由
el选项确定
示例
<div id="app"></div><script>const vm = new Vue({el: '#app',template: '<div>hello</div>',})</script>
vue实例最终就是将<div>hello</div>替换掉了原有的html中<div id="app"></div>节点
示例
const vm = new Vue({el: '#app',data: {msg: 'hello',},template: '<div>{{msg}}</div>',})
这里, 会难一点点, 流程是:
- 先解析
template中的内容, 将{{msg}}替换成hello(这个过程叫作编译) - 将编译的结果
<div>hello</div>替换掉了原有的html中<div id="app"></div>节点
在这个过程中, 会有一些时间点, 在这些时间点会自动调用一些函数. 这些就是生命周期函数
示例
const vm = new Vue({el: '#app',data: {msg: 'hello',},template: '<div>{{msg}}</div>',beforeCreate() {console.log(this, 'beforeCreate')},created() {console.log(this, 'created')},beforeMount() {console.log(this, 'beforeMount')},mounted() {console.log(this, 'mounted')},beforeUpdate() {console.log(this, 'beforUpdate')},updated() {console.log(this, 'updated')},beforeDestroy() {console.log(this, 'beforeDestroy')},destroyed() {console.log(this, 'destroyed')},})
我们发现, 有4个函数被执行了
- beforeCreate()
- created()
- beforeMount()
- mounted()
这四个函数在整个生命周期中只执行一次
4) 生命周期函数
create相关函数
create相关的生命周期函数有两个:
- beforeCreate()
- created()
beforeCreate和created的相同点
都是在Vue实例创建时被调用, 只执行一次
beforeCreate和created的不同点
要搞清楚这个问题, 我们需要知道在beforeCreate和created之间, 做了什么事
示例
beforeCreate() {console.dir(this.$data) // undefinedconsole.log(this, 'beforeCreate')},created() {console.dir(this.$data) // object// 跟数据相关, 放在created中console.log(this, 'created')}
我们发现, 在beforeCreate中$data是undefined, 而created中$data是有值的
因此, 我们得出一个重要结论
重要结论
如果要处理跟数据相关的逻辑, 最早在created函数中处理
一句话总结
在beforeCreate和created之间, 完成$data的代理
场景
- 如果发送ajax请求从后台拿数据, 建议放到created里
- 如果要完成data数据的初始化, 建议放到created里
mount相关函数
mount相关的生命周期函数有两个:
- beforeMount()
- mounted()
create和mount的不同
created结束时还不能操作DOM, mounted结束时才可以操作DOM
示例
created() {console.dir(this.$data)// 跟数据相关, 放在created中console.log(this.$el, 'created') // undefined},beforeMount() {console.log(this.$el, 'beforeMount') // <div id="app"></div>},mounted() {// 跟DOM操作相关, 放在mounted中console.log(this.$el, 'mounted') // <div>hello</div>},
created表示实例创建完成, 而mounted表示挂载完成, 是new Vue时的两个步骤
怎么将这两个步骤分开呢
示例
const vm = new Vue({// 第一步: 注释掉el// el: '#app',data: {msg: 'hello',},template: '<div>{{msg}}</div>',beforeCreate() {console.dir(this.$data)console.log(this.$el, 'beforeCreate')},created() {console.dir(this.$data)// 跟数据相关, 放在created中console.log(this.$el, 'created')},beforeMount() {console.log(this.$el, 'beforeMount')},mounted() {// 跟dom操作相关, 放在mounted中console.log(this.$el, 'mounted')},beforeUpdate() {console.log(this, 'beforUpdate')},updated() {console.log(this, 'updated')},beforeDestroy() {console.log(this, 'beforeDestroy')},destroyed() {console.log(this, 'destroyed')},})// 第二步: 调用$mount方法, 手动挂载vm.$mount('#app')
如果不指定el选项: 不会执行mount相关的生命周期
手动调用$mount方法挂载时, 发现mount相关的生命周期被调用了
mount是把什么挂载到什么上
mounted结束时, 将编译之后的模板挂载到了html上, 替换原有的节点.
通过上面的分析, 我们知道了:
Vue实例化过程中最主要两步是
- 编译
- 挂载
beforeMount和mounted的不同点
要搞清楚这个问题, 我们需要知道在beforeMount和mounted之间, 做了什么事
示例
beforeMount() {console.log(this.$el, 'beforeMount') // <div id="app"></div>},render(h) {console.log('render in invoked')return h('div', {}, this.msg)},mounted() {// 跟dom操作相关, 放在mounted中console.log(this.$el, 'mounted') // <div>hello</div>},
在beforeMount和mounted之间, 调用了render方法, 将模板编译成了html
update相关函数
update相关的生命周期函数有两个:
- beforeUpdate()
- updated()
beforeUpdate和updated的相同点
都是在Vue的data中的数据发生改变时调用, 可以执行N次(N>=1)
beforeUpdate和updated的不同点
- beforeUpdate中: 数据是新的, 页面还是旧的, 还没有更新页面, 此时页面和数据是不同步的
- updated中: 数据是新的, 页面也是新的. 此时已经完成了re-render(页面的重新渲染)
destroy相关的函数
在destroy相关的函数有两个:
- beforeDestroy(): 临死前
- desstroyed(): 死透了
比较常用的是beforeDestroy, 在这个函数中, 释放不属于vue的一些资源(定时器)和解绑一些事件
5) 常用的生命周期函数
- created: 完成data的初始化
- mounted: 操作DOM
- beforeDestory: 回收资源, 解绑事件
