在 Vue
中,每一个实例都有本身的一个完整的生命周期,包括开始建立 —— 初始化数据 —— 编译模板 —— 将实例挂载到 DOM
—— 渲染 —— 更新 —— 渲染 —— 卸载等一系列过程。同时在这个过程当中也会运行一些叫作生命周期钩子的函数,这样咱们就能够在实例生命周期的不一样阶段作一些须要作的事情。javascript
这里可能会有个小疑惑,怎么忽然又说是 Vue
实例呢?实例和组件有什么区别吗?css
在 SPA(Single Page Application)
应用中,咱们只会建立一个 Vue
根实例,整个应用都是经过这个根实例启动的。在经过 vue-cli
脚手架生成的项目中, main.js
里建立了 Vue
根实例:
<!-- more -->html
new Vue({ el: '#app', router, components: { App }, template: '<App/>', });
经过 new Vue()
建立一个 Vue
实例。在实例化 Vue
时,须要传入一个选项对象,它能够包含挂载元素 el
、路由router
、模板 template
、数据 data
、方法 methods
、生命周期钩子等选项。vue
Vue
组件是被扩展的 Vue
实例。同 Vue
实例相似,它也须要传入一个选项对象,包含数据、模板、生命周期钩子函数等等。在前面咱们只介绍了单文件组件的方式来建立组件,也能够这样来建立一个组件:java
// 定义一个名为 button-counter 的新组件 Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>' })
能够发现,和建立 Vue
实例很是的相似,全部的 Vue
组件同时都是 Vue
的实例。因此咱们说:实例的生命周期也叫作组件的生命周期。vue-cli
Vue
实例从建立到销毁的过程,就是生命周期。文章的开头咱们提到了生命周期钩子函数,它是框架提供的函数,可以让开发人员的代码参与到组件的生命周期中。也就是说,经过钩子函数,能够控制组件的行为。这里有两个点须要记住:缓存
Vue
实例的的生命周期中,会自动调用这些生命周期函数,咱们只须要提供这些钩子函数便可;生命周期图示:app
图中,红色矩形框表明着在生命周期对应阶段的钩子函数。框架
咱们经过三种案例来学习生命周期函数:函数
案例中,经过打开控制台查看钩子函数打印的内容来学习。
<template> <div class='container'> <h3>单组件的生命周期(打开控制台查看)</h3> <button @click='dataVar += 1'>更新 {{dataVar}}</button> <button @click='handleDestroy'>销毁</button> </div> </template> <script> const compName = 'single'; export default { name: 'SingleComLifecycle', data() { return { dataVar: 1, }; }, beforeCreate() { console.log(`--${compName}--beforeCreate`); // eslint-disable-line }, created() { console.log(`--${compName}--created`); // eslint-disable-line }, beforeMount() { console.log(`--${compName}--beforeMount`); // eslint-disable-line }, mounted() { console.log(`--${compName}--mounted`); // eslint-disable-line }, beforeUpdate() { console.log(`--${compName}--beforeUpdate`); // eslint-disable-line }, updated() { console.log(`--${compName}--updated`); // eslint-disable-line }, beforeDestroy() { console.log(`--${compName}--beforeDestroy`); // eslint-disable-line }, destroyed() { console.log(`--${compName}--destroyed`); // eslint-disable-line }, methods: { handleDestroy() { this.$destroy(); }, }, }; </script> <style lang="postcss" scoped> .container { width: 70%; margin: 0 auto; background-color: aliceblue; padding: 50px; text-align: center; } button { padding: 6px; background-color: #35b880; border: none; color: white; font-size: 16px; margin: 5px; } </style>
初始化组件时打印:
--single--beforeCreate --single--created --single--beforeMount --single--mounted
data
中的数据变化时打印:
--single--beforeUpdate --single--updated
组件销毁时打印:
--single--beforeDestroy --single--destroyed
因此咱们能够得出如下结论:
beforeCreate/Created/beforeMount/mounted
四个钩子函数data
中定义的变量(响应式变量)时,会执行 beforeUpdate/updated
钩子函数beforeDestory/destroyed
钩子函数beforeUpdate/updated
可屡次执行建立一个父组件:
<template> <div class='container'> <h3>父子组件的生命周期(打开控制台查看)</h3> <child-com :compName='dataVar.toString()'></child-com> <button @click='dataVar += 1'>父组件更新 {{dataVar}}</button> <button @click='handleDestroy'>父组件销毁</button> </div> </template> <script> import ChildCom from './ChildCom'; const COMPONENT_NAME = 'parent'; export default { data() { return { dataVar: 1, }; }, components: { 'child-com': ChildCom, }, beforeCreate() { console.log(`--${COMPONENT_NAME}--beforeCreate`); // eslint-disable-line }, created() { console.log(`--${COMPONENT_NAME}--created`); // eslint-disable-line }, beforeMount() { console.log(`--${COMPONENT_NAME}--beforeMount`); // eslint-disable-line }, mounted() { console.log(`--${COMPONENT_NAME}--mounted`); // eslint-disable-line }, beforeUpdate() { console.log(`--${COMPONENT_NAME}--beforeUpdate`); // eslint-disable-line }, updated() { console.log(`--${COMPONENT_NAME}--updated`); // eslint-disable-line }, beforeDestroy() { console.log(`--${COMPONENT_NAME}--beforeDestroy`); // eslint-disable-line }, destroyed() { console.log(`--${COMPONENT_NAME}--destroyed`); // eslint-disable-line }, methods: { handleDestroy() { this.$destroy(); }, }, }; </script> <style lang="postcss" scoped> .container { width: 70%; margin: 20px auto; background-color: aliceblue; padding: 50px; text-align: center; } button { padding: 6px; background-color: #2196f3; border: none; color: white; font-size: 16px; margin: 5px; } </style>
建立一个子组件:
<template> <div> <div>父组件传递的props:{{compName}}</div> <button @click='dataVar += 1'>子组件更新 {{dataVar}}</button> <button @click='handleDestroy'>子组件销毁</button> </div> </template> <script> export default { data() { return { dataVar: 1, }; }, props: { compName: { type: String, default: 'single', }, }, beforeCreate() { console.log(` --此时data未初始化--child--beforeCreate`); // eslint-disable-line }, created() { console.log(`--${this.compName}--child--created`); // eslint-disable-line }, beforeMount() { console.log(`--${this.compName}--child--beforeMount`); // eslint-disable-line }, mounted() { console.log(`--${this.compName}--child--mounted`); // eslint-disable-line }, beforeUpdate() { console.log(`--${this.compName}--child--beforeUpdate`); // eslint-disable-line }, updated() { console.log(`--${this.compName}--child--updated`); // eslint-disable-line }, beforeDestroy() { console.log(`--${this.compName}--child--beforeDestroy`); // eslint-disable-line }, destroyed() { console.log(`--${this.compName}--child--destroyed`); // eslint-disable-line }, methods: { handleDestroy() { this.$destroy(); }, }, }; </script> <style lang="postcss" scoped> button { padding: 6px; background-color: #35b880; border: none; color: white; font-size: 16px; margin: 5px; } </style>
初始化组件时打印:
--parent--beforeCreate --parent--created --parent--beforeMount --此时data未初始化--child--beforeCreate --1--child--created --1--child--beforeMount --1--child--mounted --parent--mounted
当子组件 data
中的值变化时打印:
--1--child--beforeUpdate --1--child--updated
当父组件 data
中的值变化时打印(子组件接受了父组件传递的 props
):
--parent--beforeUpdate --2--child--beforeUpdate --2--child--updated --parent--updated
当子组件销毁时打印:
--1--child--beforeDestroy --1--child--destroyed
当父组件销毁时打印:
--parent--beforeDestroy --1--child--beforeDestroy --1--child--destroyed --parent--destroyed
结论:
data
变化中是分别监控的,可是在更新 props
中的数据是关联的建立一个单组件:
<template> <div class='container'> <button @click='dataVar += 1'>更新 {{dataVar}}</button> <button @click='handleDestroy'>销毁</button> </div> </template> <script> export default { data() { return { dataVar: 1, }; }, props: { compName: { type: String, default: 'single', }, }, beforeCreate() { console.log(`--此时data未初始化--beforeCreate`); // eslint-disable-line }, created() { console.log(`--${this.compName}--created`); // eslint-disable-line }, beforeMount() { console.log(`--${this.compName}--beforeMount`); // eslint-disable-line }, mounted() { console.log(`--${this.compName}--mounted`); // eslint-disable-line }, beforeUpdate() { console.log(`--${this.compName}--beforeUpdate`); // eslint-disable-line }, updated() { console.log(`--${this.compName}--updated`); // eslint-disable-line }, beforeDestroy() { console.log(`--${this.compName}--beforeDestroy`); // eslint-disable-line }, destroyed() { console.log(`--${this.compName}--destroyed`); // eslint-disable-line }, methods: { handleDestroy() { this.$destroy(); }, }, }; </script> <style lang="postcss" scoped> .container { width: 70%; margin: 0 auto; background-color: aliceblue; padding: 10px; text-align: center; } button { padding: 6px; background-color: #35b880; border: none; color: white; font-size: 16px; margin: 5px; } </style>
引入两个单组件,构建兄弟组件:
<template> <div class='container'> <h3>兄弟组件的生命周期(打开控制台查看)</h3> <div>兄弟1 <single compName='cihld1'></single> </div> <div>兄弟2 <single compName='child2'></single> </div> <div> <p>兄弟两个的父亲</p> <button @click='dataVar += 1'>更新 {{dataVar}}</button> <button @click='handleDestroy'>销毁</button> </div> </div> </template> <script> import Single from './Single'; const COMPONENT_NAME = 'parent'; export default { data() { return { dataVar: 1, }; }, components: { single: Single, }, beforeCreate() { console.log(`--${COMPONENT_NAME}--beforeCreate`); // eslint-disable-line }, created() { console.log(`--${COMPONENT_NAME}--created`); // eslint-disable-line }, beforeMount() { console.log(`--${COMPONENT_NAME}--beforeMount`); // eslint-disable-line }, mounted() { console.log(`--${COMPONENT_NAME}--mounted`); // eslint-disable-line }, beforeUpdate() { console.log(`--${COMPONENT_NAME}--beforeUpdate`); // eslint-disable-line }, updated() { console.log(`--${COMPONENT_NAME}--updated`); // eslint-disable-line }, beforeDestroy() { console.log(`--${COMPONENT_NAME}--beforeDestroy`); // eslint-disable-line }, destroyed() { console.log(`--${COMPONENT_NAME}--destroyed`); // eslint-disable-line }, methods: { handleDestroy() { this.$destroy(); }, }, }; </script> <style lang="postcss" scoped> .container { width: 70%; margin: 5px auto; background-color: aliceblue; padding: 50px; text-align: center; } button { padding: 6px; background-color: #2196f3; border: none; color: white; font-size: 16px; margin: 5px; } </style>
初始化组件时打印:
--parent--beforeCreate --parent--created --parent--beforeMount --此时data未初始化--beforeCreate --cihld1--created --cihld1--beforeMount --此时data未初始化--beforeCreate --child2--created --child2--beforeMount --cihld1--mounted --child2--mounted --parent--mounted
当 child1
更新和销毁时,打印:
--cihld1--beforeUpdate --cihld1--updated --cihld1--beforeDestroy --cihld1--destroyed
当 child2
更新和销毁时,打印:
--cihld2--beforeUpdate --cihld2--updated --cihld2--beforeDestroy --cihld2--destroyed
当父组件销毁时,打印:
--parent--beforeDestroy --cihld1--beforeDestroy --cihld1--destroyed --child2--beforeDestroy --child2--destroyed --parent--destroyed
结论:
欢迎关注个人博客: https://togoblog.cn/