"有时候,我们需要在实例创建过程中进行一些初始化的工作,以帮助我们完成项目中更复杂更丰富的需求开发,针对这样的需求,Vu e提供给我们一系列的钩子函数。
本文将详细介绍Vue实例在创建和销毁的过程中我们可以使用的钩子函数。
这是官方文档提供的Vue实例生命周期图,我们结合这张图来进行钩子函数的解析。
@
- 实例创建之前执行——beforeCreate
- 实例创建之后执行——created
- 挂载之前执行——beforeMount
- 挂载之后执行——mounted
- 数据更新之前执行——beforeUpdate
- 数据更新之后执行——updated
- 实例销毁之前执行——beforeDestroy
- 实例销毁之后执行——destroyed
- keep-alive组件激活时执行——activated
- keep-alive组件停用时执行——deactivated
实例创建之前执行——beforeCreate
除标签外,所有的vue需要的数据(data)、事件(methods)、标签(el)都不存在.
<body> <div id="app"> {{ name }} <button @click="myClick">点击修改数据</button> </div> <script> new Vue({ el: '#app', data: { name: 'zyk', }, methods: { init: function () { console.log(this.name); }, myClick: function () { this.name = 'ZYK'; } }, // 实例创建之前执行 beforeCreate() { console.group('beforeCreate'); console.log('el:', this.$el); console.log('data:', this.$data); console.log('name:', this.name); console.log('init:', this.init); console.log('innerHTML:', document.getElementById('app').innerHTML); }, }); </script> </body>
打印结果如下图:
实例创建之后执行——created
数据和事件被解析到,标签(el)还未被解析.
<body> <div id="app"> {{ name }} <button @click="myClick">点击修改数据</button> </div> <script> new Vue({ el: '#app', data: { name: 'zyk', }, methods: { init: function () { console.log(this.name); }, myClick: function () { this.name = 'ZYK'; } }, // 实例创建之后执行 created() { console.group('created'); console.log('el:', this.$el); console.log('data:', this.$data); console.log('name:', this.name); console.log('init:', this.init); console.log('innerHTML:', document.getElementById('app').innerHTML); }, }); </script> </body>
挂载之前执行——beforeMount
数据、事件、标签都已被解析,但数据还未被渲染.
<body> <div id="app"> {{ name }} <button @click="myClick">点击修改数据</button> </div> <script> new Vue({ el: '#app', data: { name: 'zyk', }, methods: { init: function () { console.log(this.name); }, myClick: function () { this.name = 'ZYK'; } }, // 挂载之前执行 beforeMount() { console.group('beforeMount',); console.log('el:', this.$el); console.log('data:', this.$data); console.log('name:', this.name); console.log('init:', this.init); console.log('myClick:', this.myClick); console.log('innerHTML:', document.getElementById('app').innerHTML); }, }); </script>
挂载之后执行——mounted
开始渲染数据,开始监听事件.
<body> <div id="app"> {{ name }} <button @click="myClick">点击修改数据</button> </div> <script> new Vue({ el: '#app', data: { name: 'zyk', }, methods: { init: function () { console.log(this.name); }, myClick: function () { this.name = 'ZYK'; } }, // 挂载之后执行 mounted() { console.group('mounted',); console.log('el:', this.$el); console.log('data:', this.$data); console.log('name:', this.name); console.log('init:', this.init); console.log('myClick:', this.myClick); console.log('innerHTML:', document.getElementById('app').innerHTML); }, }); </script> </body>
数据更新之前执行——beforeUpdate
数据己被修改在虚拟DOM,但还未被渲染到页面上
数据更新时(之前)被调用,发生在虚拟DOM打补丁之前.
适合在更新之前访问现有的DOM,比如手动移除已添加的事件监听器.
该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行.
<body> <div id="app"> {{ name }} <button @click="myClick">点击修改数据</button> </div> <script> new Vue({ el: '#app', data: { name: 'zyk', }, methods: { init: function () { console.log(this.name); }, myClick: function () { this.name = 'ZYK'; } }, // 数据更新之前执行 beforeUpdate() { console.group('beforeUpdate',); console.log('el:', this.$el); console.log('data:', this.$data); console.log('name:', this.name); console.log('init:', this.init); console.log('myClick:', this.myClick); console.log('innerHTML:', document.getElementById('app').innerHTML); }, }); </script> </body>
数据更新之后执行——updated
将虚拟DOM中的数据应用到页面上,此时真实的DOM数据被修改了.
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子.
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之.
<body> <div id="app"> {{ name }} <button @click="myClick">点击修改数据</button> </div> <script> new Vue({ el: '#app', data: { name: 'zyk', }, methods: { init: function () { console.log(this.name); }, myClick: function () { this.name = 'ZYK'; } }, // 数据更新之后执行 updated() { console.group('updated',); console.log('el:', this.$el); console.log('data:', this.$data); console.log('name:', this.name); console.log('init:', this.init); console.log('myClick:', this.myClick); console.log('innerHTML:', document.getElementById('app').innerHTML); }, }); </script> </body>
实例销毁之前执行——beforeDestroy
所有的数据都存在.
实例销毁之前调用,在这一步,实例仍然完全可用.
频繁地创建和销毁组件对性能的影响很大,因此可使用activated和deactivated(将在下面介绍这两个钩子).
该钩子在服务端渲染期间不被调用.
<body> <div id="app"></div> <script> let Laside = { template: ` <div> <h1>{{ mes }}</h1> </div> `, data() { return { mes: 'Hello Vue!', }; }, methods: { changeData: function () { this.mes = 'Pizza is here!'; }, }, // 实例销毁之前执行 beforeDestroy() { console.log("beforeDestroy"); console.log("el: ", this.$el); console.log("data: ", this.$data); console.log("mes: ", this.mes); console.log("changeData: ", this.changeData); }, }; let App = { template: ` <div> <Laside v-if="isShow"></Laside> <button @click="showHide">创建消除组件</button> </div> `, // 判断是否有嵌套的子组件 components: { 'Laside': Laside, }, methods: { showHide: function () { this.isShow = !this.isShow; } }, data() { return { isShow: true, }; }, }; new Vue({ el: '#app', template: `<App/>`, components: { App, }, }); </script> </body>
实例销毁之后执行——destroyed
所有的数据都存在(虚拟DOM找的).
Vue实例销毁后调用,调用后,Vue实例指示的所有东西都将会解除绑定,所有的事件监听器会被移除,所有的子实例也会被销毁.
<body> <div id="app"></div> <script> let Laside = { template: ` <div> <h1>{{ mes }}</h1> </div> `, data() { return { mes: 'Hello Vue!', }; }, methods: { changeData: function () { this.mes = 'Pizza is here!'; }, }, // 实例销毁之后执行 destroyed() { console.log("destroyed"); console.log("el: ", this.$el); console.log("data: ", this.$data); console.log("mes: ", this.mes); console.log("changeData: ", this.changeData); }, }; let App = { template: ` <div> <Laside v-if="isShow"></Laside> <button @click="showHide">创建消除组件</button> </div> `, // 判断是否有嵌套的子组件 components: { 'Laside': Laside, }, methods: { showHide: function () { this.isShow = !this.isShow; } }, data() { return { isShow: true, }; }, }; new Vue({ el: '#app', template: `<App/>`, components: { App, }, }); </script> </body>
打印结果如下图:
keep-alive组件激活时执行——activated
Vue提供的用来缓存被消除的标签,keep-alive组件激活时调用.
使用activated和deactivated可分别取代取代beforeDestroy和destroyed的执行.
< keep-alive >包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们.
<body> <div id="app"></div> <script> let Laside = { template: ` <div> <h1>{{ mes }}</h1> </div> `, data() { return { mes: 'Hello Vue!', }; }, methods: { changeData: function () { this.mes = 'Pizza is here!'; }, }, // keep-alive组件激活后不会被调用 beforeDestroy() { console.log("destroyed"); console.log("el: ", this.$el); console.log("data: ", this.$data); console.log("mes: ", this.mes); console.log("changeData: ", this.changeData); }, // keep-alive组件激活时执行 activated() { console.log("destroyed"); console.log("el: ", this.$el); console.log("data: ", this.$data); console.log("mes: ", this.mes); console.log("changeData: ", this.changeData); }, }; let App = { // 激活keep-alive组件 template: ` <div> <keep-alive> <Laside v-if="isShow"></Laside> </keep-alive> <button @click="showHide">创建消除组件</button> </div> `, // 判断有没有嵌套的子组件 components: { 'Laside': Laside, }, methods: { showHide: function () { this.isShow = !this.isShow; }, }, data() { return { isShow: true, }; }, }; new Vue({ el: '#app', template: `<App/>`, components: { App, }, }); </script> </body>
打印结果如下图:
keep-alive组件停用时执行——deactivated
<body> <div id="app"></div> <script> let Laside = { template: ` <div> <h1>{{ mes }}</h1> </div> `, data() { return { mes: 'Hello Vue!', }; }, methods: { changeData: function () { this.mes = 'Pizza is here!'; }, }, // keep-alive组件停用时执行 deactivated() { console.log("destroyed"); console.log("el: ", this.$el); console.log("data: ", this.$data); console.log("mes: ", this.mes); console.log("changeData: ", this.changeData); }, }; let App = { // 激活keep-alive组件 template: ` <div> <keep-alive> <Laside v-if="isShow"></Laside> </keep-alive> <button @click="showHide">创建消除组件</button> </div> `, // 判断有没有嵌套的子组件 components: { 'Laside': Laside, }, methods: { showHide: function () { this.isShow = !this.isShow; }, }, data() { return { isShow: true, }; }, }; new Vue({ el: '#app', template: `<App/>`, components: { App, }, }); </script> </body>