vue2之生命周期
生命周期
生命周期是指组件从创建,运行到销毁的阶段。而生命周期函数(也叫生命周期钩子)是vue在关键的时刻帮我们调用的一些特殊名称的函数,会根据生命周期的阶段,依次执行。
从上图可以看出,vue的生命周期分为以下几个阶段:
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- beforeDestroy
- destroyed
vue的具体生命周期如下图所示:
其中生命周期函数的名字不可更改,但是函数里面的内容可以自定义编写。 所有的钩子中的this上下文都是自动指向vm实例的,因此在使用钩子函数的时候最好不要使用箭头函数。
组件初始化和挂载
组件初始化和挂载主要是beforeCreate -> created -> beforeMount -> mounted这几个钩子,现在我们要详细地介绍一下这块的流程。
beforeCreate
在实例初始化之后,进行数据侦听和事件侦听器的配置之前同步调用。 下面我们来看一下这个流程。
注意:所有测试效果都必须打断点查看哦
<template>
<div class="test-wrapper">
<div>number的值: {{number}}</div>
<button @click="addNumber">增加number</button>
</div>
</template>
data () {
return {
number: 1
};
},
beforeCreate() {
console.log('beforeCreate')
console.log(this)
},
methods: {
addNumber() {
this.number++;
}
}
效果如下:
此时页面上没有加载出任何内容,无法通过vm访问到data中的数据、methods中的方法
created
在实例创建完成后被立即同步调用。这一步中,实例已经完成对选项的处理,意味着一下内容已被配置完毕:数据侦听、计算属性、方法、事件/侦听器的回调函数。但是这一步挂载阶段还没开始,且$el property目前尚不可用。
<template>
<div class="test-wrapper">
<div>number的值: {{number}}</div>
<button @click="addNumber">增加number</button>
</div>
</template>
data () {
return {
number: 1
};
},
beforeCreate() {
console.log('beforeCreate')
},
created() {
console.log('created');
console.log(this);
},
methods: {
addNumber() {
this.number++;
}
}
效果如下:
可以通过vm访问到data中的数据、methods中的方法
如果请求不需要处理DOM节点,其实请求也可以放到这个钩子中完成,这是最早的时间。
beforeMount
在挂载开始之前被调用:相关的render函数首次被调用。需要注意的是该钩子在服务器渲染期间不被调用。
<template>
<div class="test-wrapper">
<div>number的值: {{number}}</div>
<button @click="addNumber">增加number</button>
</div>
</template>
data () {
return {
number: 1
};
},
beforeCreate() {
console.log('beforeCreate')
},
created() {
console.log('created');
},
beforeMount() {
console.log('beforeMount');
console.log(document.querySelector('.test-wrapper'));
},
methods: {
addNumber() {
this.number++;
}
}
效果如下:
1.页面呈现的是未经Vue编译的DOM结构
2.所有对DOM的操作都不奏效
mounted
实例被挂载后调用,这时el被新创建的vm.el替换了。如果根实例挂载到了一个文档内的元素上,当mounted被调用时vm.el替换了。如果根实例挂载到了一个文档内的元素上,当mounted被调用时vm.el替换了。如果根实例挂载到了一个文档内的元素上,当mounted被调用时vm.el也在文档内。需要注意的是mounted不能保证所有的子组件也都被挂载完成。如果你希望整个视图都渲染出来再执行某些操作,建议在mounted钩子中使用vm.$nextTick
<template>
<div class="test-wrapper">
<div>number的值: {{number}}</div>
<button @click="addNumber">增加number</button>
</div>
</template>
data () {
return {
number: 1
};
},
beforeCreate() {
console.log('beforeCreate')
},
created() {
console.log('created');
},
beforeMount() {
console.log('beforeMount');
},
mounted() {
console.log('mounted');
console.log(document.querySelector('.test-wrapper'));
},
methods: {
addNumber() {
this.number++;
}
}
效果如下:
-
页面中呈现的是经过Vue编译的DOM
-
对DOM的操作均有效(尽可能避免)。至此初始化过程结束。一般在此进行:开启定时器,发送网络请求,订阅消息,绑定自定义事件等初始化操作
组件更新
组件更新主要是beforeUpdate -> updated,现在介绍一下这块的流程。
beforeUpdate
在数据发生改变后,DOM被更新之前被调用。这里适合在现有DOM将要被更新之前访问它,比如移除手动添加的事件监听器。需要注意的是该钩子在服务端渲染期间不被调用,因为只有初次渲染会在服务器端进行。
<template>
<div class="test-wrapper">
<div>number的值: {{number}}</div>
<button @click="addNumber">增加number</button>
</div>
</template>
data () {
return {
number: 1
};
},
beforeCreate() {
console.log('beforeCreate')
},
created() {
console.log('created');
},
beforeMount() {
console.log('beforeMount');
},
mounted() {
console.log('mounted');
},
beforeUpdate() {
console.log('beforeUpdate');
console.log(this.number);
},
methods: {
addNumber() {
this.number++;
}
}
效果如下:
数据是新的,页面是旧的。即:页面尚未和数据保持同步
updated
在数据更新导致的虚拟DOM重新渲染和更新完毕之后被调用。当这个钩子被调用时,组件DOM已经更新,所以你现在可以执行依赖于DOM的操作。然而在大多数情况下,最好不要在这个钩子里更改状态,最好是借助计算属性和watch来更改。需要注意的是,和mounted一样,updated不会保证所有的子组件也都被重新渲染完毕。如果你希望等到整个视图都渲染完毕,可以在updated里使用vm.$nextTick
<template>
<div class="test-wrapper">
<div>number的值: {{number}}</div>
<button @click="addNumber">增加number</button>
</div>
</template>
data () {
return {
number: 1
};
},
beforeCreate() {
console.log('beforeCreate')
},
created() {
console.log('created');
},
beforeMount() {
console.log('beforeMount');
},
mounted() {
console.log('mounted');
},
beforeUpdate() {
console.log('beforeUpdate');
},
updated() {
console.log('updated');
console.log(this.number);
},
methods: {
addNumber() {
this.number++;
}
}
效果如下:
数据是新的,页面也是新的。即:页面和数据保持同步
组件销毁
组件销毁主要是beforeDestroy -> destroyed,这块主要会经历下面的流程。
beforeDestroy
在实例销毁之前调用。在这一步,实例可用。需要注意的是该钩子在服务端渲染期间不被调用。
<template>
<div class="test-wrapper">
<div>number的值: {{number}}</div>
<button @click="addNumber">增加number</button>
<button @click="destroy">销毁</button>
</div>
</template>
data () {
return {
number: 1
};
},
beforeCreate() {
console.log('beforeCreate')
},
created() {
console.log('created');
},
beforeMount() {
console.log('beforeMount');
},
mounted() {
console.log('mounted');
},
beforeUpdate() {
console.log('beforeUpdate');
},
updated() {
console.log('updated');
},
beforeDestroy() {
console.log('beforeDestroy');
console.log(this);
},
methods: {
addNumber() {
this.number++;
},
destroy() {
this.$destroy();
}
}
效果如下:
vm中所有的data,methods, 指令等等,都处于可用状态,马上要执行销毁过程,一般在此过程:关闭定时器,取消订阅消息,解绑自定义事件等收尾操作
destroyed
在实例销毁后调用。该钩子被调用后,对应Vue实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。
<template>
<div class="test-wrapper">
<div>number的值: {{number}}</div>
<button @click="addNumber">增加number</button>
<button @click="destroy">销毁</button>
</div>
</template>
data () {
return {
number: 1
};
},
beforeCreate() {
console.log('beforeCreate')
console.log(this)
},
created() {
console.log('created');
},
beforeMount() {
console.log('beforeMount');
},
mounted() {
console.log('mounted');
},
beforeUpdate() {
console.log('beforeUpdate');
},
updated() {
console.log('updated');
},
beforeDestroy() {
console.log('beforeDestroy');
},
destroyed() {
console.log('destroyed');
console.log(this);
},
methods: {
addNumber() {
this.number++;
},
destroy() {
this.$destroy();
}
}
效果如下: 此时页面按钮已经不能点击了。还能在页面中看到内容是因为页面缓存。
转载自:https://juejin.cn/post/7177024582065324092