如何实现父组件监听子组件的生命周期
方法一:$emit
// 父组件
<template>
<div>
<Child
@mounted="onMounted"
@updated="onUpdated"
@beforeDestroy="onBeforeDestroy"
></Child>
</div>
</template>
// 子组件
...
mounted () {
this.$emit('mounted')
}
updated () {
this.$emit('updated')
}
beforeDestroy () {
this.$emit('beforeDestroy')
}
...
优点:简单易上手
缺点:此种方法子组件必须是自己编写的组件,若引用第三方库这种方式则不可行
方法二:@hook
// 父组件
<template>
<div>
<Child
@hook:mounted="onMounted"
@hook:updated="onUpdated"
@hook:beforeDestroy="onBeforeDestroy"
></Child>
</div>
</template>
// 子组件
<!--无-->
官方文档并没有太多相关解释,只在处理边界情况 #程序化的事件侦听器— Vue.js (vuejs.org)里有出现。
子组件无需相关处理就能实现侦听,这块的实现原理可以从源码里探究部分
在组件生命周期的每个函数内都调用了callHook它支持两个参入,分别是实例vm
和对应的生命周期钩子名称。而callHook
里面就执行了vm.$emit('hook:' + hook)
,此为方法一!
当在子组件上传入了对应的@hook:mounted
钩子,也就是执行了vm.$on('hook:mounted')
,而vue实例在生命周期里本身就会执行vm.$emit('hook:mounted')
,其实就连带着触发了我们绑定给子组件的回调函数了。
ps:使用callHook的好处
callHook(vm, 'beforeCreate')
调用后, const handlers = vm.$options[hook]
即读取到了当前 vm
实例上的任务队列,然后通过 for
循环依次传递给 invokeWithErrorHandling(handlers[i], vm, null, vm, info)
进行处理, 调用 invokeWithErrorHandling
如果发生异常, 则会统一报错处理。
拓展
1.hook:提升代码简洁性
在编写组件时,我们往往需要在各个生命周期里都针对某个业务逻辑做一些处理,业务散落在各个生命周期钩子里:
<script type="text/ecmascript-6">
export default {
mounted () {
// 挂载时执行一些业务A相关逻辑
// 挂载时执行一些业务B相关逻辑
}
updated () {
// 更新时执行一些业务A逻辑
// 更新时执行一些业务B逻辑
// 更新时执行一些业务C逻辑
}
beforeDestroy () {
// 销毁时执行一些业务A逻辑
// 销毁时执行一些业务C逻辑
}
}
</script>
业务逻辑散落在各个生命周期里,有时候是不利于我们阅读代码的,尤其是当该业务是一个复杂的长段代码时,这个时候我们就可以考虑利用hook:
来梳理某一块的业务代码,提升可阅读性:
<script type="text/ecmascript-6">
export default {
created() {
this.$on('hook:mounted', () => {
挂载时执行一些业务A相关逻辑
})
this.$on('hook:updated', () => {
挂载时执行一些业务A相关逻辑
})
this.$once('hook:beforeDestroy', () => {
挂载时执行一些业务A相关逻辑
})
}
}
</script>
这样就可以将散落的业务逻辑,都在一个created钩子函数里书写完毕,而且仍保持原来的生命周期逻辑。
2.避免data里的无用变量的定义
例如我们在编写组件时会执行一些事件监听或者定时器函数,我们希望在组件销毁的时候都能去销毁这些监听或者定时器,但是由于夸生命周期的问题,常常会将定时器赋值给一个全局变量或者绑定到this上,然后在另一个生命周期里获取并执行销毁操作。
// 优化前
<script type="text/ecmascript-6">
export default {
data() {
return {
timer:null
}
}
mounted () {
this.timer = setInterval(() => {
// todo
}, 1000);
}
beforeDestroy () {
clearInterval(this.timer)
}
}
</script>
// 优化后
<script type="text/ecmascript-6">
export default {
mounted () {
const timer = setInterval(() => {
// todo
}, 1000);
this.$once('hook:beforeDestroy', function () {
clearInterval(timer)
})
}
}
</script>
Vue3.X
参考 https://v3-migration.vuejs.org/zh/breaking-changes/vnode-lifecycle-events.html
1.本站内容仅供参考,不作为任何法律依据。用户在使用本站内容时,应自行判断其真实性、准确性和完整性,并承担相应风险。
2.本站部分内容来源于互联网,仅用于交流学习研究知识,若侵犯了您的合法权益,请及时邮件或站内私信与本站联系,我们将尽快予以处理。
3.本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
4.根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
5.本站是非经营性个人站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途
暂无评论内容