推荐:Vue汇总
Vue - Vue生命周期钩子
官网
下图展示了Vue实例的生命周期。
beforeCreate
在Vue实例初始化之后,数据观测 (data observer
) 和 event/watcher
事件配置之前被调用。
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LifeCyCle</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="div">
<p>Hello Kaven</p>
</div>
</body>
</html>
<script>
var vue = new Vue({
el: '#div',
beforeCreate: function () {
console.log('beforeCreate');
}
})
</script>
效果:
created
在Vue实例创建完成后被立即调用。在这一步,实例已完成以下配置:数据观测 (data observer
),property
和方法的运算,watch/event
事件回调。然而,挂载阶段还没开始,$el property
目前尚不可用。
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LifeCyCle</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="div">
<p>Hello Kaven</p>
</div>
</body>
</html>
<script>
var vue = new Vue({
el: '#div',
beforeCreate: function () {
console.log('beforeCreate');
},
created: function () {
console.log('created');
console.log(this.$el);
}
})
</script>
效果:
可以看到$el property
目前尚不可用。
beforeMount
在挂载开始之前被调用:相关的 render
函数首次被调用。该钩子在服务器端渲染期间不被调用。
什么是服务器端渲染?
下图页面没使用服务器端渲染,当请求user
页面时,返回的body
为空,之后执行js
将html
结构注入到body
里,结合css
显示出来。
下图页面使用了服务器端渲染,当请求user
页面时,返回的body
里已经有了页面的html
结构,之后结合css
显示出来即可。
由于没有动态更新,所有的生命周期钩子函数中,只有 beforeCreate
和 created
会在服务器端渲染 (SSR) 过程中被调用。这就是说任何其他生命周期钩子函数中的代码(例如 beforeMount
或 mounted
),只会在客户端执行。
此外还需要注意的是,你应该避免在 beforeCreate
和 created
生命周期时产生全局副作用的代码,例如在其中使用 setInterval
设置 timer
。在纯客户端 (client-side only
) 的代码中,我们可以设置一个 timer
,然后在 beforeDestroy
或 destroyed
生命周期时将其销毁。但是,由于在 SSR 期间并不会调用销毁钩子函数,所以 timer
将永远保留下来。为了避免这种情况,请将副作用代码移动到 beforeMount
或 mounted
生命周期中。
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LifeCyCle</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="div">
<p>{{text}}</p>
</div>
</body>
</html>
<script>
var vue = new Vue({
el: '#div',
data: {
text: 'Hello Kaven'
},
beforeCreate: function () {
console.log('beforeCreate');
},
created: function () {
console.log('created');
console.log(this.$el);
},
beforeMount: function () {
console.log('beforeMount');
console.log(this.$el);
}
})
</script>
效果:
可以看到$el property
目前可用,但{{text}}
还没有被替换成Hello Kaven
。
mounted
实例被挂载后调用,这时 el
被新创建的 vm.$el
替换了。如果根实例挂载到了一个文档内的元素上,当 mounted
被调用时 vm.$el
也在文档内。
注意 mounted
不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在 mounted
内部使用 vm.$nextTick
:
mounted: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been rendered
})
}
vm.$nextTick
:在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LifeCyCle</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="div">
<p>{{text}}</p>
</div>
</body>
</html>
<script>
var vue = new Vue({
el: '#div',
data: {
text: 'Hello Kaven'
},
beforeCreate: function () {
console.log('beforeCreate');
},
created: function () {
console.log('created');
console.log(this.$el);
},
beforeMount: function () {
console.log('beforeMount');
console.log(this.$el);
},
mounted: function () {
console.log('mounted');
console.log(this.$el);
}
})
</script>
效果:
{{text}}
已经被替换成Hello Kaven
了。
beforeUpdate
数据更新时调用,发生在虚拟DOM打补丁之前。这里适合在更新之前访问现有的DOM,比如手动移除已添加的事件监听器。
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LifeCyCle</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="div">
<button @click="click">{{count}}</button>
</div>
</body>
</html>
<script>
var vue = new Vue({
el: '#div',
data: {
count: 0
},
methods: {
click() {
this.count++;
}
},
beforeCreate: function () {
console.log('beforeCreate');
},
created: function () {
console.log('created');
console.log(this.$el);
},
beforeMount: function () {
console.log('beforeMount');
console.log(this.$el);
},
mounted: function () {
console.log('mounted');
console.log(this.$el);
},
beforeUpdate: function () {
console.log('beforeUpdate');
console.log(this.$el);
}
})
</script>
效果:
updated
由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子。
当这个钩子被调用时,组件DOM已经更新,所以你现在可以执行依赖于DOM的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或watcher
取而代之。
注意 updated
不会保证所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以在 updated
里使用 vm.$nextTick
:
updated: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been re-rendered
})
}
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LifeCyCle</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="div">
<button @click="click">{{count}}</button>
</div>
</body>
</html>
<script>
var vue = new Vue({
el: '#div',
data: {
count: 0
},
methods: {
click() {
this.count++;
}
},
beforeCreate: function () {
console.log('beforeCreate');
},
created: function () {
console.log('created');
console.log(this.$el);
},
beforeMount: function () {
console.log('beforeMount');
console.log(this.$el);
},
mounted: function () {
console.log('mounted');
console.log(this.$el);
},
beforeUpdate: function () {
console.log('beforeUpdate');
console.log(this.$el);
},
updated: function () {
console.log('updated');
console.log(this.$el);
}
})
</script>
效果:
beforeDestroy
实例销毁之前调用。在这一步,实例仍然完全可用。
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LifeCyCle</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="div">
<button @click="click">{{count}}</button>
</div>
</body>
</html>
<script>
var vue = new Vue({
el: '#div',
data: {
count: 0
},
methods: {
click() {
this.count++;
}
},
beforeCreate: function () {
console.log('beforeCreate');
},
created: function () {
console.log('created');
console.log(this.$el);
},
beforeMount: function () {
console.log('beforeMount');
console.log(this.$el);
},
mounted: function () {
console.log('mounted');
console.log(this.$el);
},
beforeUpdate: function () {
console.log('beforeUpdate');
console.log(this.$el);
},
updated: function () {
console.log('updated');
console.log(this.$el);
},
beforeDestroy: function () {
console.log('beforeDestroy');
console.log(this.$el);
}
})
</script>
效果:
destroyed
实例销毁后调用。该钩子被调用后,对应Vue实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LifeCyCle</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="div">
<button @click="click">{{count}}</button>
</div>
</body>
</html>
<script>
var vue = new Vue({
el: '#div',
data: {
count: 0
},
methods: {
click() {
this.count++;
}
},
beforeCreate: function () {
console.log('beforeCreate');
},
created: function () {
console.log('created');
console.log(this.$el);
},
beforeMount: function () {
console.log('beforeMount');
console.log(this.$el);
},
mounted: function () {
console.log('mounted');
console.log(this.$el);
},
beforeUpdate: function () {
console.log('beforeUpdate');
console.log(this.$el);
},
updated: function () {
console.log('updated');
console.log(this.$el);
},
beforeDestroy: function () {
console.log('beforeDestroy');
console.log(this.$el);
},
destroyed: function () {
console.log('destroyed');
console.log(this.$el);
}
})
</script>
效果:
虽然还可以输出$el
,但点击按钮已经没有反应了,说明按钮的点击事件监听器被移除了。
Vue生命周期钩子就介绍到这里。
写博客是博主记录自己的学习过程,如果有错误,请指正,谢谢!
参考