生命周期
生命周期是指组件从创建,运行到销毁的阶段。而生命周期函数(也叫生命周期钩子)是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++;}}
效果如下:
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++;}}
效果如下:
1.页面中呈现的是经过Vue编译的DOM2.对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();}}
效果如下: 此时页面按钮已经不能点击了。还能在页面中看到内容是因为页面缓存。
最后
整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。
有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享
部分文档展示:
文章篇幅有限,后面的内容就不一一展示了
有需要的小伙伴,可以点下方卡片免费领取