-
Notifications
You must be signed in to change notification settings - Fork 0
Description
1. Vue 实例化过程
结合源码,我们看下通过 new Vue() 实例化的过程
Vue.prototype._init = function (options?: Object) {
// ... 以上代码省略
initLifecycle(vm)
initEvents(vm)
initRender(vm)
callHook(vm, 'beforeCreate')
initInjections(vm) // resolve injections before data/props
initState(vm)
initProvide(vm) // resolve provide after data/props
callHook(vm, 'created')
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
vm._name = formatComponentName(vm, false)
mark(endTag)
measure(`vue ${vm._name} init`, startTag, endTag)
}
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
}Vue 初始化过程顺序如下:
- 初始化生命周期、初始化事件、初始化渲染
- 抛出
beforeCreate钩子 - 初始化 injections、state、provide。其中初始化 State 包括了 props、data、methods、computed 和 watch
- 抛出
created钩子 - 判断实例是否有 el 属性,有则调用
vm.$mount方法挂载 vm
2. 生命周期钩子
2.1 生命周期钩子函数
mounted: function() {}
// 或者
mounted() {}
// ------分割线------
// 错误写法
mounted: () => {}Vue 的生命周期函数是自动绑定 this 到实例上,使用箭头函数会出现 this 指向父级作用域,会报错
2.2 生命周期钩子详解
接下来会通过在每个生命周期钩子中打印某些信息,来得知当前钩子节点做了什么事情
1. beforeCreate
在 Vue 初始化实例方法调用之后,抛出 beforeCreate 钩子之前,Vue 初始化了生命周期、事件和渲染,此时所有的数据在这个节点还不能拿到
beforeCreate() {
console.log('--- beforeCreate 钩子 ---');
console.log('el: ', this.$el); // undefined
console.log('data: ', this.$data); // undefined
},2. created
beforeCreate 到 created 的生命周期之间发生了什么?

在这期间初始化了事件,进行数据监测。初始化了 Injections、State(包括了 props、data、methods、computed 和 watch) 和 Provide。此时已经可以访问到 data、props 等数据,但还是没有 el 选项
created() {
console.log('--- created 钩子 ---');
console.log('el: ', this.$el); // undefined
console.log('data: ', this.$data); // 有值
},3. beforeMount
created 到 beforeMount 的生命周期之间发生了什么?

首先判断对象上是否有 el 选项,如果有就继续往下变异,如果没有,则停止停止生命周期,知道在该 Vue 实例上调用 vm.$mount(el),生命周期才继续执行。
// 在没有el属性的情况下,没有vm.$mount
new Vue({
beforeCreate: function() {
console.log('调用了beforeCreate')
},
created: function() {
console.log('调用了created')
},
beforeMount: function() {
console.log('调用了beforeMount')
},
mounted: function() {
console.log('调用了mounted')
}
})
// 输出 调用了beforeCreate
// 输出 调用了created
// 后续的钩子节点不执行如果我们在后面调用 vm.$mount(el),则生命周期继续执行
vm.$mount(el);
// 输出 调用了beforeMount
// 输出 调用了mounted接着判断是否有 template 属性,template 属性对生命周期的影响况:
- Vue 实例如果有 template 属性,则调用 render 函数去渲染
- Vue 实例没有 template 属性,则调用外部的 html。实例内部的 template 属性比外部的 html 优先级高
- 实际上 Vue 对象中还有一个 render 函数,它是以 createElement 作为参数,然后做渲染操作,优先级高于其他
- 优先级排序:render 函数 > template 属性 > outerHTML
注意,在这个生命周期中,相关的 render 函数首次被调用,但还不能访问到 $el
beforeMount() {
console.log('--- beforeMount 钩子 ---');
console.log('el: ', this.$el); // undefined
console.log('data: ', this.$data); // 有值
},4. mounted
beforeMount 到 mounted 的生命周期之间发生了什么?

Vue 实例对象创建 $el 成员,并且替换掉挂在的 DOM 元素。因为在之前 console 中打印的结果可以看到 beforeMount 之前 $el 还是 undefined
5. beforeUpdate 和 updated
当一个数据发生改变时,你的视图也将随之改变,整个更新的过程是:数据改变 —— 导致虚拟 DOM 的改变 —— 调用这两个生命钩子去改变视图
这个数据只有和模版中的数据绑定了才会发生更新
6. beforeDestory 和 destoryed
在 beferoDestory 生命钩子调用之前,所有实例都可以用,但是当调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
7. 不常用的生命钩子
- activated:当组件在
keep-alive中激活的时候调用 - deactivated:当组件在
keep-alive中停用的时候调用 - errorCaptured:这个生命钩子可以看官网,2.5.0之后才有的。当捕获一个来自子孙组件的错误时被调用。


