关关难过, 关关过 :)
1.beforeCreat
beforeCreate在实例初始化之后、数据观测(data observer)和事件配置之前被调用。在 beforeCreate 钩子函数中,Vue 实例已经完成了数据观测的设置,但尚未初始化,也没有 DOM 相关操作,因此在这个钩子函数中还不能访问数据或组件模板,也不能操作 DOM 元素。
数据观测(data observation)指的是 Vue 响应式系统对组件数据的监测,当组件数据发生变化时,Vue 会自动触发视图更新。这是 Vue 实现响应式的核心机制。
通常在 beforeCreate 中可以做一些初始化的工作,例如初始化数据、获取远程数据、设置事件监听器等,但需要注意的是,在 beforeCreate 中对数据进行的修改是不会触发视图更新的,因为此时 Vue 实例还未初始化完成。
如果在beforeCreate阶段中获取的数据需要在Vue实例的生命周期中使用,需要在数据返回后手动调用this.$forceUpdate()来触发Vue实例的重新渲染。
注意
在 beforeCreate 钩子函数中对实例的数据进行修改是无效的,因为实例的数据和方法尚未初始化。在这个钩子函数中有this对象, 这个this并不能访问data和props。你可以通过函数的参数来访问到这些数据,但在这个时候组件实例还没有完成数据的响应式化, 也就是说, 此时仅能读取它们的值,而不能修改
beforeCreate() {
console.log(this.$options.data()) // 访问 data
console.log(this.$options.propsData) // 访问 props
}
2.created
created钩子函数是Vue实例创建完成后执行的第一个函数。在这个钩子函数中,Vue实例已经完成了数据的观测,可以访问到实例中的data数据以及props属性。此时模板已经编译成了虚拟DOM,但是还没有被渲染成真实的DOM。
在created钩子函数中,我们可以进行一些实例的初始化操作,例如发送异步请求获取数据、调用methods中的方法等。在这个阶段,我们可以访问到data和props中的数据,并可以对它们进行修改,但是不能保证这些修改能够立即更新到视图中,因为此时模板还没有被渲染成真实的DOM。
需要注意的是,created钩子函数执行完毕后,才会进入到模板的编译和挂载阶段,因此,在created钩子函数中进行的异步操作,不会阻塞模板的编译和挂载。如果需要在模板被渲染之后执行一些操作,可以使用mounted钩子函数。
3.beforeMount
beforeMount 钩子函数是 Vue 生命周期中的一个阶段,在模板编译完成并准备渲染到页面上之前调用。在这个阶段,Vue 实例已经完成了数据的观测和与数据的绑定,但还没有开始创建真正的 DOM 节点。
在 beforeMount 钩子函数中,可以访问到 Vue 实例的所有属性和方法。
但要注意,如果需要修改数据,应该在 beforeMount 钩子函数之前进行,因为此时 Vue 实例的数据已经与 DOM 节点绑定,如果在beforeMount 中修改数据,实际上是在生成 VNode 的过程中修改了组件实例的数据,此时这些数据还没有被同步到真实的 DOM 节点上。可能会导致视图与数据不同步。
4.mounted
mounted 钩子是在组件挂载到DOM上后调用的钩子函数,可以理解为组件生命周期的最后一个阶段。该钩子函数一般用于获取DOM节点、初始化第三方库、发送异步请求等等操作。
具体来说,在 mounted 钩子执行期间,组件实例已经被编译成真实的DOM,并且该DOM节点已经被添加到页面上,所以在这个钩子中可以访问this.$el,即当前组件的根节点标签,并可以进行一些需要访问DOM节点的操作,例如使用jQuery或原生DOM API等。
在执行 mounted 钩子期间,Vue会将组件的DOM节点和组件实例关联起来,形成一个双向绑定关系,从而实现数据的自动响应式更新。
需要注意的是,如果在 mounted 钩子中进行的操作需要在组件销毁时进行清理,那么必须在 beforeDestroy 钩子中进行相应的清理工作,例如定时器、绑定的事件监听器等,如果没有进行清理操作,在组件销毁后,相关的数据和事件监听器就会一直存在于内存中,导致内存泄漏问题,影响应用的性能和稳定性。
因此,在编写 Vue 组件时,需要注意这个问题,及时清理组件中创建的数据和事件监听器,避免内存泄漏。
5.beforeUpdate
在数据更新时,在 updated 钩子函数之前被调用。它可以用来检测数据的变化、执行一些特定的操作以及阻止不必要的重渲染。
在 beforeUpdate 钩子函数中,可以访问到组件实例的 this 对象以及更新前的数据和状态。通过对比更新前后的数据和状态,可以判断是否需要进行重渲染,并作出相应的处理。
在 beforeUpdate 钩子中直接修改数据是不会导致死循环的,不管新旧值是否相同,只要数据被修改,Vue 会进入下一次的渲染周期。
这个钩子是在组件更新之前被调用,此时组件的 DOM 尚未更新,Vue 会对新旧虚拟 DOM 树进行比对,以确定需要对哪些节点进行更新。如果在 beforeUpdate 钩子中修改了组件的数据,那么这些数据会在下一次更新时生效,从而触发新的 beforeUpdate 钩子调用。因此,在 beforeUpdate 中修改数据通常没有意义,因为这些修改不会立即生效,也可能导致一些意料之外的行为。
同时在这个钩子函数中,也可以使用 watch 来监听数据的变化,并在变化时执行相应的操作。例如,可以监听组件中的某个数据对象,并在其变化时执行一些特定的操作。
注意
在 beforeUpdate 钩子函数中,还不能访问到更新后的 DOM 节点,因为此时更新过程还没有完成,新的节点还没有渲染出来。如果需要在 DOM 更新完成后进行一些操作,可以在 updated 钩子函数中执行。
6.updated
这个钩子函数常常用于执行一些需要在组件更新后进行的操作,比如 DOM 操作或者与服务器的交互。下面从源码角度来详细解释 updated 钩子的实现过程:
- Vue.js 会在更新前执行
beforeUpdate钩子函数,该函数在组件的数据更新之前被调用。beforeUpdate函数会将当前的渲染 watcher 添加到观察者列表中,以便在更新后能够被执行。 - Vue.js 然后会调用 updateComponent 函数,该函数会重新渲染组件,并更新组件的 VNode 树。
- 在组件的 VNode 树更新完成后,Vue.js 会执行
updated钩子函数。在执行 updated 钩子函数之前,Vue.js 会先执行 activated 钩子函数(如果组件是被 keep-alive 缓存的话)。 updated钩子函数会接收两个参数:prevVNode 和 prevData,分别表示组件更新前的 VNode 和数据。通过这些参数,可以在 updated 钩子函数中比较组件更新前后的状态,从而执行一些需要在组件更新后进行的操作,比如 DOM 操作或者与服务器的交互。- 最后,Vue.js 会从观察者列表中移除渲染 watcher,从而结束更新过程。
总的来说,updated 钩子函数是在组件的 VNode 树更新后被调用的,它允许开发者在组件更新后执行一些操作。Vue.js 的实现过程中,updated 钩子函数的执行是在 beforeUpdate 钩子函数、updateComponent 函数和 activated 钩子函数之后,通过移除渲染 watcher 来结束更新过程的。
注意
不要在这个钩子函数里做任何改变组件状态的操作,会无限循环导致堆栈溢出.
7.beforeDestory
beforeDestroy 生命周期钩子函数会在一个组件实例被销毁之前被调用。具体来说,它会在组件实例从 DOM 树中被移除之前被调用。
在 beforeDestroy 钩子函数中,Vue.js 会执行以下操作:
- 调用
vm.$off()方法来移除组件实例上的所有事件监听器。这个方法会将组件实例上的所有事件监听器从事件总线中移除,以防止它们在组件实例被销毁后继续存在,从而导致内存泄漏。 - 调用
vm.$destroy()方法来递归销毁组件实例上的所有子组件。这个方法会先递归销毁所有子组件上的子组件,然后再依次调用子组件实例的beforeDestroy、destroyed钩子函数,完成子组件的销毁工作。 - 最后,调用
vm._isBeingDestroyed = true将组件实例标记为正在被销毁的状态,然后触发组件实例的beforeDestroy钩子函数,执行用户定义的销毁逻辑。
由于 beforeDestroy 钩子函数是在组件实例销毁之前被调用的,因此它可以用于执行一些与销毁相关的清理工作,例如取消异步任务、释放资源等。同时,它也可以用于在组件实例销毁之前执行一些操作,例如提交最后一次数据到服务器等。
8.destoryed
destroyed 钩子函数是在组件实例被销毁之后执行的,它可以用于执行一些与销毁无关的操作,例如记录日志、清除定时器等。在这个钩子函数中,组件实例已经被销毁,可以在 destroyed 钩子中访问 data 和 methods,因为这些属性是在组件实例化时创建的,并且在组件销毁时仍然存在。但是它的状态和属性不会改变,因此这里做的任何操作都应该是与销毁无关的。
总的来说,beforeDestroy 钩子函数和 destroyed 钩子函数的主要区别在于执行时机和作用范围。beforeDestroy 钩子函数用于执行与销毁相关的操作,而 destroyed 钩子函数用于执行与销毁无关的操作。在实际开发中,应该根据具体的需求选择合适的钩子函数来完成相应的操作。
注意
如果有操作需要在卸载组件时进行,请使用beforeDestroy
补充:
- vue中生命周期的钩子里的操作会被vue移入微任务队列执行, 所以在这些钩子函数内进行的异步操作, 不能立刻体现出来。举个例子:
//this.name = 'aaaa'
created() {
new Promise((resolve) => {
resolve('111')
}).then(r => {
this.name = r
})
},
mounted() {
console.log(this.name) //'aaaa'
},
所有的异步操作会进入下一个微任务队列, 所以在这个例子中想要访问this.name改变后的结果,需要使用nextTick
mounted() {
console.log(this.name) //'aaaa'
this.$nextTick(() => {
console.log(this.name)// '111'
})
},
- 当组件已经渲染,而且mounted钩子中有setTimeout函数,在wait之前组件被销毁,这个setTimeout依然会执行。因为生命周期钩子被调用,组件卸载并不会中断其中函数的执行。