Vue 组件的生命周期可以被分为 8 个阶段:
-
beforeCreate
:在实例被创建之前调用,此时实例的数据、方法及生命周期都未初始化。
在 Vue 组件的生命周期中,beforeCreate 是第一个被调用的钩子函数。它表示实例刚创建,但数据观测和事件系统都未初始化完成,因此在该阶段无法获取到 data、computed、methods 等属性。在 beforeCreate 钩子函数中,我们可以进行一些组件级别的初始化工作,如创建一个全局的事件总线对象、初始化一些组件级别的变量等。但是,因为在该阶段无法获取到 data、computed、methods 等属性,所以需要注意在该阶段进行的任何操作都不能依赖这些属性。
下面是一个示例,在 beforeCreate 钩子函数中创建了一个全局的事件总线对象:
Vue.component('my-component', { beforeCreate: function () { this.$bus = new Vue(); // 创建全局事件总线对象 }, mounted: function () { this.$bus.$emit('event-name', eventData); // 触发事件 } })
在该示例中,我们在 beforeCreate 钩子函数中创建了一个全局事件总线对象 this.$bus,并在 mounted 钩子函数中触发了一个名为 event-name 的事件。由于在 beforeCreate 钩子函数中创建了该对象,因此在组件的其它钩子函数中都可以使用该对象来进行事件的传递和监听。
-
created
:实例刚刚被创建,数据初始化完成,但是 DOM 模板还未生成并挂载。
created 阶段是在 Vue 实例被创建之后,组件的数据观测和事件监听都已经初始化完成,但是组件的模板还没有渲染成 HTML 结构。在这个阶段,组件实例已经完成了初始化,可以访问到组件的数据和方法,但是此时模板还没有被渲染到页面上。在 created 阶段可以进行如下操作:
访问组件的数据和方法:此时 Vue 实例已经创建好了,可以通过 this 访问到组件实例的数据和方法。
对组件的数据进行初始化:可以通过修改组件实例的数据来初始化组件的状态。
调用异步请求或者操作 DOM 的方法:由于模板还没有被渲染到页面上,因此此时操作 DOM 是没有效果的,但是可以进行异步请求以及其他需要在组件创建之后立刻执行的操作。
需要注意的是,在 created 阶段中,组件的 $el 属性还不存在,因为模板还没有被渲染成 HTML。但是可以使用 $nextTick 方法来访问 $el 属性,该方法会在组件渲染更新之后执行回调函数。
总之,created 阶段是组件生命周期中比较重要的一个阶段,可以在此阶段进行组件数据的初始化和一些操作。
-
beforeMount
:DOM 模板已经准备好,但尚未挂载到页面上。beforeMount 阶段会在以下情况下被触发:
- 组件实例化之后,在调用 render 方法生成虚拟 DOM 之前。
- 组件需要被挂载到页面上时,即执行 $mount 方法之前。
在 beforeMount 阶段,我们可以进行一些 DOM 操作和数据的初始化,例如:
- 通过 this.$el 可以获取到组件的根 DOM 元素,从而进行一些 DOM 操作。
- 可以通过 this.$nextTick 方法来确保 DOM 加载完毕之后再进行一些操作。
- 可以对一些需要在组件挂载前初始化的数据进行赋值。
- 由于组件还没有完全渲染到页面上,因此此时修改组件的相关参数和数据对页面是不会产生影响的。
总之,beforeMount 阶段是组件生命周期中非常重要的一个阶段,它提供了一个机会来进行一些初始化工作,确保组件在挂载到页面之前处于一个良好的状态。
-
mounted
:DOM 模板已经完成挂载到页面上,此时页面上的元素可以被访问到。mounted是Vue组件生命周期中的一个阶段,表示组件已经被挂载到DOM中。在mounted方法执行之前,Vue会先将template编译成render函数,然后将组件的数据和render函数生成的虚拟DOM渲染到真实的DOM节点上。
在mounted方法中,组件已经挂载到了DOM上,可以执行一些需要访问DOM元素的操作,比如获取元素的属性、添加事件监听等等。此外,mounted方法还是组件初始化数据的好地方,可以在这里进行一些异步请求,获取数据后更新组件的状态。
下面是一个例子,展示了mounted的执行过程:
<template> <div> {{ message }} </div> </template> <script> export default { data() { return { message: 'Hello World!' } }, mounted() { console.log('mounted') // 获取元素属性 console.log(this.$el.getAttribute('class')) // 添加事件监听 this.$el.addEventListener('click', () => { console.log('click!') }) // 发送异步请求 fetch('https://jsonplaceholder.typicode.com/users/1') .then(response => response.json()) .then(json => { this.message = `Hello ${json.name}!` }) } } </script>
在上述例子中,组件的数据初始化为
Hello World!
。在mounted方法中,我们首先打印了一个字符串mounted
,证明mounted方法成功执行。接着,我们获取了组件的class属性,并且添加了一个点击事件监听器。最后,我们使用fetch API发送了一个异步请求,获取了JSON数据中的name属性,并更新了组件的message属性,使得视图中显示的内容变为Hello
+姓名!
。需要注意的是,mounted方法只会执行一次,即当组件首次被渲染到页面后mounted方法会执行一次。如果组件数据发生了变化,视图会随之更新,但mounted方法不会再次执行。如果需要在数据变化后执行一些操作,可以考虑使用
watch
监听数据变化的方法。 -
beforeUpdate
:组件数据更新,但尚未更新到页面上。beforeUpdate 函数会在组件数据更新之前被调用,常用于在组件更新之前获取更新前的状态,或进行一些更新前的操作。
具体来说,beforeUpdate 函数在以下情况下会被调用:
-
组件触发更新时,包括由父组件传递的属性更新、组件自身状态的更新、以及父组件强制重新渲染等情况。
-
当组件的数据发生变化时,Vue 会重新渲染组件,触发一次新的生命周期,包括 beforeUpdate、updated 等函数。
因此,如果需要在组件更新之前获取更新前的状态,可以在 beforeUpdate 中通过 this 获取组件旧的数据值,进行比较或记录。例如:
<template> <div> <p>旧的计数值为:{{oldCount}}</p> <p>新的计数值为:{{count}}</p> </div> </template> <script> export default { data() { return { count: 0, oldCount: null } }, beforeUpdate() { this.oldCount = this.count }, updated() { console.log('组件已更新') } } </script>
在上面的例子中,我们定义了一个计数器组件,通过 beforeUpdate 声明了一个 oldCount 的变量,用于记录组件更新前的计数值。在组件更新之后,会触发 updated 函数,控制台会输出更新后的计数值,方便我们进行比较。
-
-
updated
:组件数据更新完毕,已成功渲染到页面上。Vue组件的updated生命周期函数是在组件的DOM更新完毕后被调用。它跟前面提到的created、mounted等生命周期函数类似,都是Vue组件的内置函数,用于在不同阶段执行一些特定的操作。
updated生命周期函数有两个参数(第一个参数是更新前的虚拟DOM节点,第二个参数是更新后的虚拟DOM节点),可以用来比较更新前后的状态,从而做一些相应的处理。例如,我们可以在updated函数中监听数据的变化,当数据变化时,更新组件的状态或重新渲染组件。
下面是一个updated生命周期函数的示例:
Vue.component('my-component', { template: '<div>{{ message }}</div>', data: function() { return { message: 'Hello, world!' }; }, updated: function(prevNode, nextNode) { console.log('Component updated'); console.log('Prev node:', prevNode); console.log('Next node:', nextNode); } });
在上面的例子中,我们在组件更新时打印一些信息,以便了解组件的状态。当我们修改组件的数据时,updated生命周期函数会被调用,并输出前后虚拟DOM节点的信息。
总结一下,updated生命周期函数是Vue组件在更新DOM后被调用的。在updated函数中,我们可以监听数据的变化,根据数据的变化来更新组件的状态或重新渲染组件。
-
beforeDestroy
:实例销毁之前调用,此时实例上的数据、方法及生命周期都可用。beforeDestroy生命周期钩子函数是在Vue组件销毁之前调用的函数,该函数可以用来清除一些在组件内部产生的副作用(比如在mounted中注册的定时器、事件监听等),以及解除该组件和其他组件之间的一些绑定关系,以便在组件销毁时不会对其他组件产生影响。
在beforeDestroy生命周期钩子函数中,我们可以做一些清理工作,例如:
- 取消定时器或请求,以避免内存泄漏。
- 取消一些监听事件,以避免对其他组件产生影响。
- 销毁一些插件,以避免对系统产生负面影响。
示例代码:
export default { data() { return { timer: null, }; }, mounted() { this.timer = setInterval(() => { console.log("定时器在运行"); }, 1000); }, beforeDestroy() { clearInterval(this.timer); }, };
在上述代码中,我们在mounted函数中设置了一个定时器,在组件销毁前,通过beforeDestroy函数清除了这个定时器。这是beforeDestroy生命周期钩子函数的一个常见用法。
-
destroyed
:实例已经销毁,此时实例上的数据、方法及生命周期都已被销毁。Vue 组件的 destroyed 钩子函数是在组件被销毁之后被调用的。当一个组件被销毁,它的所有指令和事件监听器都会被移除,所有子组件的实例也都会被销毁。这个钩子函数可以让我们在组件销毁后执行一些清理工作,比如取消订阅、卸载插件等。
destroyed 钩子函数的调用时机是在组件完全销毁后调用,此时组件的 DOM 元素已经被移除,但是组件实例仍然存在于内存中,可以访问组件的实例属性和方法,但是不能再对其进行修改。
destroyed 钩子函数可以用来清理组件的定时器、异步请求、WebSocket 连接等,以避免出现内存泄漏的问题。
下面是一个简单的例子,展示了 destroyed 钩子函数的用法:
Vue.component('my-component', { data() { return { message: 'Hello, Vue!' } }, created() { this.timer = setInterval(() => { console.log(this.message) }, 1000) }, destroyed() { clearInterval(this.timer) } })
在这个例子中,我们在 created 钩子函数中设置了一个定时器,每秒钟输出组件的 message 数据。在 destroyed 钩子函数中清除了这个定时器,避免了组件销毁后定时器仍然继续运行的问题。
在这些生命周期函数中,常用的是 created
和 mounted
。在 created
钩子中,组件实例已经创建完成,可以访问组件中的数据和方法。在 mounted
钩子中,组件模板已经挂载到页面上,可以访问页面中的 DOM 元素并进行操作。在 beforeDestroy
钩子中,可以进行一些清理工作,例如取消定时器、移除事件监听器等。