vue生命周期详解
发布时间:2022-05-06, 01:30:08 分类:Vue | 编辑 off 网址 | 辅助
图集1/8
正文 4652字数 395,603阅读
我们可以看到在Vue实例的整个生命周期中,会有八个生命周期钩子函数提供给我们,方便我们在不同时期进行不同操作,八个钩子函数如下:
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestroy
destroyed
Run code
Cut to clipboard
先一起来看看下面代码的打印结果:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">{{title}}</div>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
data:{
title:"第一个例子"
},
beforeCreate(){
console.log("beforeCreate $el",this.$el) /*beforeCreate $el undefined*/
console.log("beforeCreate $data",this.$data) /*beforeCreate $data undefined*/
console.log("beforeCreate title",this.title) /*beforeCreate title undefined*/
},
created(){
console.log("created $el",this.$el) /* created $el undefined */
console.log("created $data",this.$data) /* created $data {__ob__: Observer} */
console.log("created title",this.title) /* created title 第一个例子 */
},
beforeMount(){
console.log("beforeMount $el",this.$el) /* beforeMount $el <div id="app">{{title}}</div> */
console.log("beforeMount $data",this.$data)/* beforeMount $data {__ob__: Observer} */
console.log("beforeMount title",this.title) /* beforeMount title 第一个例子 */
},
mounted(){
console.log("mounted $el",this.$el) /* mounted $el <div id="app">第一个例子</div> */
console.log("mounted $data",this.$data) /* mounted $data {__ob__: Observer} */
console.log("mounted title",this.title) /* mounted title 第一个例子 */
},
beforeUpdate() {
console.log("beforeUpdate $el",this.$el.innerHTML)
console.log("beforeUpdate $data",this.$data)
console.log("beforeUpdate title",this.title)
},
updated() {
console.log("updated $el",this.$el.innerHtml)
console.log("updated $data",this.$data)
console.log("updated title",this.title)
},
beforeDestroy(){
console.log("beforeDestroy $el",this.$el)
console.log("beforeDestroy $data",this.$data)
console.log("beforeDestroy title",this.title)
},
destroyed() {
console.log("destroyed $el",this.$el)
console.log("destroyed $data",this.$data)
console.log("destroyed title",this.title)
}
})
</script>
</body>
</html>
Run code
Cut to clipboard
打印结果如下:
1. 在beforeCreate之前
进行了以下操作:(对于浏览器来说整个渲染还没开始或者说准备开始, el 和 data 并未初始化 ,代码中均打印的是undefined)
处理该实例的初始化选项:vm.$options
初始化生命周期:initLifecycle
初始化事件:initEvents
初始化render函数:initRender
beforeCreate()在这个函数中无法访问el、data、method,因为还未初始化。
2. beforeCreate和created之间
在这个期间对事件初始化、对数据进行观测。通过代码的打印结果我们可以看到,这期间data完成初始化,而el还不存在。所以我们对data进行赋值等其他操作时、或者调用method中的方法,最早只能在created()钩子函数中!
3. created和beforeMount之间
根据流程图,我们可以看到,先判断vm实例中是否有el选项?
如果有:再判断是否有template选项;
如果没有:停止编译(停止生命周期),直到调用vm.$mount(el)函数;
我们可以再之前的代码上注释掉:
el:'#app',
这一行,看到控制台打印结果如下:生命周期在created之后就停止了,不往下执行!
我们在代码中加上一行:
vm.$mount("#app")
打印结果如下:生命周期正常执行
以上是判断是否存在el部分;如果存在el继续判断Vue实例中是否存在template选项:
如果有:将template作为模板编译成render函数;
如果没有:将外部HTML作为模板编译;(上面的代码例子中就未给出template属性)
模板已经在内存中编译好,但是未挂载到页面中!
通过代码打印我们可以看到,这个期间我们的el不再不存在,而是关联到了我们指定的DOM上(打印出:< div id=“app”>{{title}})。
4. beforeMount和mounted之间
在这个期间,Vue实例在内存中创建了一个vm.e l , 然 后 原 本 的 e l 被 新 创 建 的 v m . el,然后原本的el 被新创建的 vm.el,然后原本的el被新创建的vm.el 替换,其实就是将内存中编译好的模板替换到页面上,之后调用mounted钩子函数,所以我们在mounted函数中打印出来的el是:< div id=“app”>第一个例子 页面上的内容也随之发生了变化!
显然,如果我们要对页面上的DOM进行操作时,最早只能在mounted()钩子函数中进行。
当mounted()运行完后,整个实例的初始化阶段结束,下面进入运行阶段。
5. beforeUpdate钩子函数和updated钩子函数间的生命周期
当我们Vue实例中的data数据发生变化时就会触发这两个钩子函数,如下:我们在控制台输入vm.title="121"来更改data数据,可以看到,在beforeUpdate时data中的数据已经修改为了”121“(如果数据不改变,根本就不会触发这两个钩子函数!!),但是我们的DOM中并未更新,而在updated时DOM已经更新了,页面中已经显示为了”121“。
6. beforeDestroy和destroyed钩子函数间的生命周期
beforeDestroy钩子函数在实例销毁之前调用,这时,实例仍然完全可用。 destroyed钩子函数在Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。我们使用vm.$destroy来销毁实例如下:
但是页面中的相应DOM并没有变化,想要清除页面的 DOM,需要使用 v-if="false"来手动销毁实例 !
详情可以参考官方文档: 官方文档
(支付宝)给作者钱财以资鼓励 (微信)→
有过 1 条评论 »
报错的使用场景
在vue3的项目中,不免会遇到v-if和v-for一起使用,但我们知道,这两个是不可以一起使用的,v-for 具有比 v-if 更高的优先级,所以我们需要把v-for写到template中,但是控制台会提示:
'<template v-for>' cannot be keyed. Place the key on real elements instead
解决方法
在 Vue 2中,<template> 标签不能拥有 key,不过,你可以为其每个子节点分别设置 key
<template v-for="i in list">
<div :key="'index-' + i.id"></div>
</template>
在 Vue 3 中,key 则应该被设置在 <template> 标签上
<template v-for="(i, index) in list" :key="index">
<div>...</div>
<span>...</span>
</template>
但是我在使用的时候VScode总是一直报错冒红,但是程序是可以运行的,但总看着不舒服,可以尝试将:key="index"写在我们循环的节点上面,程序也是可以运行的。
<template v-for="i in list">
<div v-if="true" :key="item.id"></div>
<span v-else></span>
</template>
按照官网说的key 则应该被设置在 <template> 标签上的话,可以修改.eslintrc.js的配置,在rules的规则上添加:
'vue/no-v-for-template-key': 'off'
或者将将template标签改为div等其他标签,这样的话会多出一个多余的div标签。