Vue中如何编程统计触发component-loaded事件的子组件数量
解决方案
方案1:集中维护待加载组件清单(兼容性最好,不易出错)
把所有需要监听component-loaded事件的组件统一存为常量数组,新增组件时仅需修改该数组即可,无需调整Watcher里的判断逻辑,还能避免硬编码数值的问题。
代码实现
script部分:
// 统一维护需要监听加载事件的组件列表,新增组件仅需修改此处 const COMPONENTS_TO_LOAD = ['warehouses-01', 'warehouses-03', 'warehouses-04', 'warehouses-07'] export default { watch: { componentsLoaded() { // 直接取数组长度,无需硬编码数值 if (this.componentsLoaded.size === COMPONENTS_TO_LOAD.length) { this.isLoaded = true } } }, data() { return { // 用Set存储避免同一组件重复触发事件导致计数错误 componentsLoaded: new Set(), isLoaded: false } }, methods: { handleComponentLoaded(componentName) { this.componentsLoaded.add(componentName) } } }
模板部分可以优化为动态渲染,无需重复写组件绑定逻辑:
<template> <component v-for="compName in COMPONENTS_TO_LOAD" :key="compName" :is="compName" @component-loaded="() => handleComponentLoaded(compName)" /> </template>
如果不想用动态组件,继续手写组件标签也可以,只要确保新增的组件名加入COMPONENTS_TO_LOAD数组即可,Watcher逻辑完全不需要修改。
方案2:自动统计子组件数量(无需手动维护清单)
如果不想手动维护组件列表,可以通过子组件标记自动统计总数:
- Vue2项目可以直接使用
$children遍历统计 - Vue3项目可以给所有目标子组件套一个父容器,通过ref获取容器后统计子组件数量
代码示例(Vue2)
export default { data() { return { componentsLoaded: [], isLoaded: false, totalLoadComponents: 0 } }, mounted() { // 统计所有带hasLoadEvent自定义属性的子组件 this.totalLoadComponents = this.$children.filter(child => child.$attrs.hasLoadEvent).length }, watch: { componentsLoaded() { if (this.componentsLoaded.length === this.totalLoadComponents) { this.isLoaded = true } } } }
模板中给需要统计的子组件加标记即可:
<warehouses-01 hasLoadEvent @component-loaded="() => this.componentsLoaded.push('warehouses-01')" />
方案3:provide/inject主动上报(适合组件嵌套深的场景)
如果子组件嵌套层级较多,可以通过依赖注入的方式实现自动统计,完全不需要手动维护任何列表:
父组件代码
export default { provide() { return { registerLoadComponent: this.registerLoadComponent, reportComponentLoaded: this.reportComponentLoaded } }, data() { return { totalLoadComponents: 0, loadedComponents: new Set(), isLoaded: false } }, methods: { // 子组件注册上报,统计总数 registerLoadComponent() { this.totalLoadComponents++ }, // 子组件加载完成后上报 reportComponentLoaded(compId) { this.loadedComponents.add(compId) if (this.loadedComponents.size === this.totalLoadComponents) { this.isLoaded = true } } } }
子组件代码
export default { inject: ['registerLoadComponent', 'reportComponentLoaded'], mounted() { // 注册当前组件为需要统计加载状态的组件 this.registerLoadComponent() // 自身加载逻辑执行完成后上报 this.reportComponentLoaded(this._uid) } }
该方案新增组件时不需要修改父组件任何代码,只要子组件按规则调用注入的两个方法即可。
内容的提问来源于stack exchange,提问作者knot22
相关产品推荐
相关产品推荐

