一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
生命周期
关于vue面试,多多少少都会说到生命周期,为了防止”刁难“,先给自己下一个狠药,把子、父、mixins、extends都混在一起,来看看生命周期的顺序
全局mixin、页面mixin.mixin、页面mixin、页面extends、子组件组成如下结构
// 假设每个mixin、组件和extends都有整个生命周期
Vue.mixin(全局mixin)
new Vue({
mixins: [页面mixin] // 页面mixin里面还有个mixin,即是页面mixin.mixin
extends: 页面extends,
components: {valueDiv}
}}
图1是挂载流程,图2是销毁流程,我特意为其加上了不同颜色
- 全局mixin:蓝色
- 页面extends:灰色
- 页面mixin.mixin:橙色
- 页面mixin:绿色
- 页面:黑色
- 子组件:红色
仔细看图可以发现,其中全局mixin会随着page和组件valueDiv再度触发,因为全局mixin会作用到每个vue上,所以会重复触发。并且从中可以发现一定的顺序:
- mixin的生命周期:全局->mixin.mixin->mixin->page
- extends: extends->page
- 每次父组件挂载前都会先挂载完子组件,销毁同理
总结
就生命周期而言可以通俗点说:权重低,先执行,按extends->mixins->page顺序触发。而实际上vue也是自顶而上,把mixin、extends这些分别合并成一个数组,再由指定的option函数处理。在触发的时候,因为会先从左到右调用生命周期函数,所以出现上图的生命周期顺序
而方法则是就近原则,例如:当前vue实例的methods里面的方法会覆盖同名方法
具体代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
function getLifeCycle (name, color) {
const lifeCycle = ['beforeCreate', 'created', 'beforeMount', 'mounted', 'beforeDestroy', 'destroyed']
const obj = {}
lifeCycle.forEach(key => {
obj[key] = function () {
const fn = new Function(`console.log('%c ${this.$options.name ? this.$options.name + '-' : ''}${name}:${key}', 'color:${color}')`)
fn()
}
})
return obj
}
Vue.mixin(getLifeCycle('全局', '#409EFF'))
const vue = new Vue({
name: '页面',
el: '#app',
mixins: [{
...getLifeCycle('mixin', '#67C23A'),
mixins: [getLifeCycle('mixin.mixin', '#E6A23C')]
}],
extends: getLifeCycle('extends', '#909399'),
template: `
<main>
<valueDiv></valueDiv>
<button @click="destroy">消毁</button>
</main>
`,
components: {
valueDiv: {
name: 'valueDiv',
template: `<div>子组件</div>`,
...getLifeCycle('component', '#F56C6C')
}
},
methods: {
destroy () {
this.$destroy()
}
},
...getLifeCycle('page', '#303133')
})
</script>
</body>
</html>