关于父组监听子组件的生命周期有两种方式:
方法1:$emit
其实就是在父组件上封装了一个v-on的事件用来监听子组件的事件,只不过事件名和钩子函数同名,当子组件发布时,即执行this.$emit('钩子函数created/mounted',参数)时,在父组件则可以监听到,然后执行回调,使用参考下面的例子
父组件:
<template>
<div>
<child-component @mounted="handleDoSomething"></child-component>
</div>
</template>
<script>
export default Vue.component("HelloWorld", {
...
methods:{
handleDoSomething(data){
console.log('监听到子组件生命周期钩子函数mounted时,触发该回调',data)
}
},
components:{
"child-component":ChildComponent
}
});
</script>
子组件:
<script>
export default {
...
mounted(){
this.$emit('mounted','mounted 触发了')
},
}
</script>
总结:其实就是父子组件通信,事件名和钩子函数相同
缺点:以上方法虽然可行,但每次都需要手动写一次 $emit 触发父组件的事件。
推荐使用:更简单的方式可以在父组件引用子组件时通过 @hook 来监听生命周期。
方法2:@hook
@hook 方法可以监听子组件的任何的生命周期。子组件不需要发布。直接在父组件中,插入子组件的地方,使用@hook.声明周期函数名="函数名"即可
原理:就是父子组件通信的基础上(方法1),添加@hook,形成了对应生命周期函数的自动发布,方法1每次都是手动执行发布。
实现方式如下:
<template>
<div>
<child-component @hook:mounted="handleDoSomething"></child-component>
</div>
</template>
<script>
export default Vue.component("HelloWorld", {
...
methods:{
handleDoSomething(data){
console.log('监听到子组件生命周期钩子函数mounted时,触发该回调',data)
}
},
components:{
"child-component":ChildComponent
}
});
</script>
为什么要用@hook
下面浅谈一下,为什么要用@hook,以及hook实现的原理?首先我们先看一个例子
<script>
export default {
mounted() {
this.timer = setInterval(() => { ... }, 1000);
},
beforeDestroy() {
clearInterval(this.timer);
}
};
</script>
但是其实更好的做法是:
<script>
export default {
mounted() {
const timer = setInterval(() => { ... }, 1000);
this.$once('hook:beforeDestroy', () => clearInterval(timer);)
}
};
</script>
上面确实可以达到优化或简化代码的效果。比如到多个生命周期的逻辑都非常简单,简单到只有一句时,这个时候就可以考虑将这些代码放在 created 或者 mounted 里,通过这种方式来监听并执行那些简单逻辑。上面的是在组件内的使用。在组件外的使用同样简单。如果在组件外使用,就用父组件上加上@hook就可以达到上面的效果
使用场景
通过监听子组件的生命周期函数来处理业务,例如监听子组件loading,数据渲染到页面的之前让页面 loading。mounted 之后停止 loading。beforeUpdata 时开始 loading。updatad 之后停止 loading,
官网上对hook 也有描述处理边界情况 — Vue.js
参考:
@hook 的实现原理可参考https://zhuanlan.zhihu.com/p/142395540
上面是个人理解,写的不好,请指教!