内容简介:所谓生命周期根据上面的三个阶段,本人总结为:后续会根据这三大周期,分别说明生命周期函数。
Vue 组件生命周期钩子函数
所谓 生命周期钩子函数 (简称 生命周期函数 ),指的是组件的 创建 、 更新 、 销毁 三个阶段所触发执行的函数。根据每个阶段触发的钩子函数,我们可以相应的做一些操作,如获取后端接口数据、监听事件、执行事件、执行定时器、移除事件、清理定时器等等。
生命周期根据上面的三个阶段,本人总结为:
-
实例化期
组件创建
-
存在期
组件更新
-
销毁期
组件销毁
后续会根据这三大周期,分别说明生命周期函数。
为了方便理解,本人在 http://jsrun.net 上编写了例子。(一个跟 jsfiddle 差不多的网站,国内 jsfiddle 被墙了)
生命周期示意图
首先看下官网的生命周期示意图,这里的生命周期函数都是针对浏览器端的,服务端目前只支持 beforeCreate 和 created 这两个生命周期函数。
其中官网并没有把 render 、 renderError 函数归纳为生命周期钩子函数。
其中 Has "el" option 对比如下:
有 el
// 有el属性的情况下
new Vue({
el: "#app",
beforeCreate: function() {
console.log("调用了beforeCreate");
},
created: function() {
console.log("调用了created");
},
beforeMount: function() {
console.log("调用了beforeMount");
},
mounted: function() {
console.log("调用了mounted");
}
});
// 输出结果
// 调用了beforeCreate
// 调用了created
// 调用了beforeMount
// 调用了mounted
无 el
// 有el属性的情况下
const vm new Vue({
beforeCreate: function() {
console.log("调用了beforeCreate");
},
created: function() {
console.log("调用了created");
},
beforeMount: function() {
console.log("调用了beforeMount");
},
mounted: function() {
console.log("调用了mounted");
}
});
// 输出结果
// 调用了beforeCreate
// 调用了created
无 el 时,如果需要挂载,可以这样处理: vm.$mount('#app') 。效果一样了,本质上没区别,只是用法更灵活。
实例化期
实例化期会涉及到以下生命周期函数(执行顺序自上而下):
- beforeCreate
- created
- beforeMount
- mouted
其中 beforeCreate 和 created 中间会触发 render 函数,如果有 template 会转换为 render 函数进行渲染。(当然如果组件的 定义了 render 函数,那么 render 函数优先级更高)
详细的例子请看 http://jsrun.net/LZyKp/edit
// 输出请看 右下角 Console 命令行工具
new Vue({
el: '#dynamic-component-demo',
data: {
num: 2,
},
beforeCreate(){
console.log("beforeCreate",this.num,this.a);
// 输出为 befoerCreate,,
// this.num 数据还没监测,this.a 方法未绑定
},
created(){
console.log("created",this.num,this.a,this.$el);
// 输出为 created, 2, function () { [native code] }
},
beforeMount(){
console.log(this.$el.innerText);
// 输出 {{ num }},还是原来的 DOM 内容
},
mounted(){
console.log(this.$el.innerText);
// 输出 2,已经是 vue 渲染的 DOM 内容
},
methods: {
a(){}
}
})
beforeCreate
在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
created
在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始, $el 属性目前不可见。
beforeMount
在挂载开始之前被调用:相关的 render 函数首次被调用。 $el 属性已经可见,但还是原来的 DOM,并非是新创建的。
mounted
el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。
注意 mounted 不会 承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted :
mounted: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been rendered
})
}
存在期
存在期会涉及到以下生命周期函数:
- beforeUpdate
- updated
Vue 需要改变数据才会触发组件重新渲染,才会触发上面的存在期钩子函数。其中 beforeUpdate 和 updated 中间会触发 render 函数。
例子请看 http://jsrun.net/8ZyKp/edit 。
// 需要点击更新按钮
// 连续点击更新按钮,都会是 2 秒后不点击更新才会输出 “2 秒没更新了”
// 输出请看 右下角 Console 命令行工具
new Vue({
el: '#dynamic-component-demo',
data: {
num: 2,
},
beforeUpdate(){
clearTimeout(this.clearTimeout);
this.clearTimeout = setTimeout(function(){
console.log("2 秒没更新了");
},2000);
console.log("beforeUpdate",this.num,this.$el.innerText);
// 第一次点击更新,输出为 beforeUpdate,3,点击更新 2
},
updated(){
console.log("updated",this.num,this.$el.innerText);
// 第一次点击更新,输出为 updated,3,点击更新 3
},
methods: {
updateComponent(){
this.num++;
}
}
})
beforeUpdate
数据更新时,虚拟 DOM 变化之前调用,这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
请不要在此函数中更改状态,否则会触发死循环。
updated
数据更新和虚拟 DOM 变化之后调用。
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用 计算属性 或 watcher 取而代之。
和 mounted 一样, updated 不会 承诺所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以用 vm.$nextTick 替换掉 updated :
updated: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been re-rendered
})
}
请不要在此函数中更改状态,否则会触发死循环。
销毁期
销毁期会涉及到以下生命周期函数:
- beforeDestroy
- destroyed
例子请看 http://jsrun.net/QZyKp/edit 。
// 切换 tab,看右下角 console 输出
Vue.component('tab-home', {
template: '<div>Home component</div>',
beforeDestroy(){
console.log("tab-home","beforeDestroy");
},
destroyed(){
console.log("tab-home","destroyed");
},
})
Vue.component('tab-posts', {
template: '<div>Posts component</div>',
beforeDestroy(){
console.log("tab-posts","beforeDestroy");
},
destroyed(){
console.log("tab-posts","destroyed");
},
})
Vue.component('tab-archive', {
template: '<div>Archive component</div>',
beforeDestroy(){
console.log("tab-archive","beforeDestroy");
},
destroyed(){
console.log("tab-archive","destroyed");
},
})
new Vue({
el: '#dynamic-component-demo',
data: {
currentTab: 'Home',
tabs: ['Home', 'Posts', 'Archive']
},
computed: {
currentTabComponent: function () {
return 'tab-' + this.currentTab.toLowerCase()
}
}
})
beforeDestroy
实例销毁之前调用,在这一步,实例仍然完全可用。一般在这里移除事件监听器、定时器等,避免内存泄漏
destroyed
Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
所以如果需要用到 Vue 实例指示的所用绑定的东西,需要在 beforeDestroy 中使用。这么说,destroyed 函数能做的事,在 beforeDestroy 也能做,所以没必要在 destroyed 函数中处理。
其他不常用的生命周期函数
- activated
当组件激活的时候调用,可以参考 构建组件 - keep-alive
- deactivated
当组件停用的时候调用,可以参考 构建组件 - keep-alive
- errorCaptured
这个生命钩子详细请看 官网 ,2.5.0 新增的,当捕获一个来自子孙组件的错误时被调用。
使用注意
生命周期函数请不要使用 ES6 箭头函数,否则 this 指向会有问题。
请看这个例子 http://jsrun.net/cZyKp/edit 。
// 输出请看 右下角 Console 命令行工具
new Vue({
el: '#dynamic-component-demo',
data: {
num: 2,
},
created: ()=>{
console.log("created",this);
// 输出为 created,[object Window]
// this 指向不是 Vue 实例而是父级 this
}
})
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 初探 Vue 生命周期和钩子函数
- Vue的路由及路由钩子函数
- vue笔记1 数据绑定,生命周期的钩子函数
- 基于Vue2.X的路由和钩子函数详解
- webpack 4.0 Tapable 类中的常用钩子函数源码分析
- 队列与钩子
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
在你身边,为你设计
腾讯公司用户研究与体验设计部 / 电子工业出版社 / 2013-1 / 69.00元
设计属于所有人,也意在为所有人使用,这既是设计的价值,也是设计的责任。本书内容包括:设计理念、设计方法、用户研究、体验设计、设计流程和工具,以及团队成长与管理等方面的知识与经验分享。一起来看看 《在你身边,为你设计》 这本书的介绍吧!