Vue中父组件监听子组件挂载完成的操作过程

 更新时间:2025年11月24日 14:25:07   作者:藤原とラふ店丶  
文章介绍了父组件监听子组件挂载完成的可靠方法,通过子组件主动发送事件通知父组件,实现父子组件之间的通信,文章结合实例代码介绍了Vue中父组件监听子组件挂载完成的实例代码,感兴趣的朋友跟随小编一起看看吧

父组件监听子组件挂载完成,核心逻辑是 子组件在自身挂载完毕后主动向父组件发送事件,父组件监听该事件并执行后续操作(比如调用子组件方法)。这种方式最可靠,能确保子组件完全渲染+初始化完成,适配 Vue2、Vue3 所有版本,下面分场景详细说明实现步骤和注意事项:

一、核心原理

  1. 子组件生命周期:mounted 钩子触发时,子组件已完成 DOM 渲染、自身初始化(无异步逻辑时),是“挂载完成”的关键节点;
  2. 父子通信:子组件通过 $emit(Vue2/Vue3 选项式)或 defineEmits(Vue3 组合式)发送自定义事件(比如 mounted-complete);
  3. 父组件响应:在模板中通过 @事件名 监听子组件事件,回调函数中即可安全操作子组件(调用方法、访问属性)。

二、分版本实现(含完整代码)

场景 1:Vue2(选项式 API)

1. 子组件:挂载完成后发送事件

<!-- 子组件 Child.vue(Vue2) -->
<template>
  <div>子组件内容</div>
</template>
<script>
export default {
  name: 'ChildComponent',
  mounted() {
    // 关键:子组件挂载完毕,向父组件发送事件(事件名建议 kebab-case)
    this.$emit('mounted-complete'); 
  },
  methods: {
    // 父组件要调用的子组件方法
    childMethod() {
      console.log('子组件方法执行(已挂载完成)');
    }
  }
}
</script>

2. 父组件:监听事件并调用方法

<!-- 父组件 Parent.vue(Vue2) -->
<template>
  <!-- 1. v-if 控制子组件显示;2. ref 绑定子组件;3. @监听子组件事件 -->
  <ChildComponent
    v-if="isChildShow"
    ref="childRef"
    @mounted-complete="handleChildMounted" <!-- 监听挂载完成事件 -->
  />
  <button @click="showChild">显示子组件</button>
</template>
<script>
import ChildComponent from './Child.vue';
export default {
  components: { ChildComponent },
  data() {
    return { isChildShow: false };
  },
  methods: {
    // 触发子组件显示
    showChild() {
      this.isChildShow = true;
    },
    // 子组件挂载完成后的回调(核心)
    handleChildMounted() {
      // 此时子组件已完全挂载,$refs 一定存在,可安全调用方法
      this.$refs.childRef.childMethod();
      // (可选)访问子组件属性
      console.log('子组件属性:', this.$refs.childRef.childProp);
    }
  }
}
</script>

场景 2:Vue3(选项式 API,与 Vue2 兼容)

逻辑和 Vue2 一致,仅语法细微差异(无需 name 也可正常通信):

<!-- 子组件 Child.vue(Vue3 选项式) -->
<script>
export default {
  mounted() {
    this.$emit('mounted-complete'); // 同样用 $emit 发事件
  },
  methods: {
    childMethod() { /* ... */ }
  }
}
</script>
<!-- 父组件 Parent.vue(Vue3 选项式) -->
<template>
  <ChildComponent v-if="isChildShow" ref="childRef" @mounted-complete="handleChildMounted" />
</template>
<script>
import ChildComponent from './Child.vue';
export default {
  components: { ChildComponent },
  data() { return { isChildShow: false }; },
  methods: {
    showChild() { this.isChildShow = true; },
    handleChildMounted() { this.$refs.childRef.childMethod(); }
  }
}
</script>

场景 3:Vue3(组合式 API / setup 语法,推荐)

Vue3 组合式 API 需用 defineEmits 声明事件,ref 绑定方式略有不同:

1. 子组件:用 defineEmits 声明事件并发送

<!-- 子组件 Child.vue(Vue3 setup) -->
<template>
  <div>子组件内容</div>
</template>
<script setup>
// 1. 声明要发送的事件(TypeScript 可选,增强类型提示)
const emit = defineEmits(['mounted-complete']);
// 2. 模拟子组件挂载完成(mounted 钩子等价于 setup 中直接执行异步逻辑后触发)
// 注:setup 执行时机是 beforeCreate -> created 之间,需用 onMounted 监听挂载
import { onMounted } from 'vue';
onMounted(() => {
  // 挂载完成后发送事件
  emit('mounted-complete'); 
});
// 子组件方法(需用 defineExpose 暴露给父组件)
const childMethod = () => {
  console.log('Vue3 子组件方法执行(已挂载)');
};
// 关键:setup 中定义的方法/属性,需显式暴露才能被父组件 $refs 访问
defineExpose({ childMethod });
</script>

2. 父组件:监听事件并调用暴露的方法

<!-- 父组件 Parent.vue(Vue3 setup) -->
<template>
  <ChildComponent
    v-if="isChildShow"
    ref="childRef" <!-- 用 ref 绑定子组件实例 -->
    @mounted-complete="handleChildMounted" <!-- 监听事件 -->
  />
  <button @click="isChildShow = true">显示子组件</button>
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './Child.vue';
// 1. 控制子组件显示的开关
const isChildShow = ref(false);
// 2. 绑定子组件的 ref(初始为 null)
const childRef = ref(null);
// 3. 子组件挂载完成后的回调
const handleChildMounted = () => {
  // 此时 childRef.value 是子组件实例,且已暴露 childMethod
  childRef.value.childMethod(); // 安全调用
};
</script>

三、进阶场景:子组件有异步初始化逻辑

如果子组件 mounted 中存在异步操作(比如请求接口、加载资源),仅靠 mounted 只能保证 DOM 渲染,不能保证异步逻辑完成。此时需修改子组件:在异步逻辑结束后再发送事件

示例(子组件有接口请求):

<!-- 子组件 Child.vue(Vue3 setup) -->
<script setup>
const emit = defineEmits(['mounted-complete']);
import { onMounted } from 'vue';
// 子组件方法(依赖接口返回数据)
const childMethod = (data) => {
  console.log('子组件方法执行,数据:', data);
};
onMounted(async () => {
  // 模拟异步接口请求(实际开发中是 axios/fetch)
  const res = await fetch('/api/child-data');
  const data = await res.json();
  // 异步逻辑完成后,再发送“挂载+初始化完成”事件(可携带数据)
  emit('mounted-complete', data); 
});
defineExpose({ childMethod });
</script>
<!-- 父组件 Parent.vue(Vue3 setup) -->
<script setup>
// ... 其他代码不变
const handleChildMounted = (data) => {
  // 接收子组件传递的异步数据,再调用方法
  childRef.value.childMethod(data);
};
</script>

四、关键注意事项(避免踩坑)

  1. 事件命名规范:推荐用 kebab-case(短横线分隔),比如 mounted-complete,避免驼峰(Vue 模板中不区分大小写,可能导致事件监听失效);
  2. Vue3 setup 必须暴露方法:setup 中定义的方法/属性默认是“私有”的,需用 defineExpose 显式暴露,父组件才能通过 ref 访问;
  3. 避免重复触发:如果子组件可能多次挂载(比如 v-if 反复切换 true/false),父组件回调会多次执行,可通过标志位控制:
// 父组件中添加标志位
const isChildMounted = ref(false);
const handleChildMounted = () => {
  if (!isChildMounted.value) {
    childRef.value.childMethod();
    isChildMounted.value = true; // 执行一次后标记
  }
};
  1. 兜底判断:极端情况下(比如子组件内部有条件渲染导致未真正挂载),可加可选链判断:
// Vue2:this.$refs.childRef?.childMethod();(需开启 ES6+ 可选链语法)
// Vue3:childRef.value?.childMethod();(天然支持)

五、总结

父组件监听子组件挂载完成的核心流程:

  1. 子组件:在「挂载完成 + 初始化完成」时,通过 $emit/defineEmits 发送事件;
  2. 父组件:监听该事件,在回调中通过 $refs 安全操作子组件;
  3. 适配场景:
    • 简单场景(无异步):子组件 mounted 中发事件;
    • 复杂场景(有异步):子组件异步逻辑结束后发事件;
    • Vue2 用 $emit,Vue3 setup 用 defineEmits + defineExpose

这种方式比 $nextTick 更可靠,因为它是子组件“主动通知”,能确保子组件完全就绪,不会出现 undefined 报错。

到此这篇关于Vue中父组件监听子组件挂载完成的操作过程的文章就介绍到这了,更多相关vue父组件监听子组件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Vue Element前端应用开发之获取后端数据

    Vue Element前端应用开发之获取后端数据

    这篇文章主要介绍了Vue Element前端应用开发之获取后端数据,对vue感兴趣的同学,可以参考下
    2021-05-05
  • 一文详解Pinia和Vuex与两个Vue状态管理模式

    一文详解Pinia和Vuex与两个Vue状态管理模式

    这篇文章主要介绍了一文详解Pinia和Vuex与两个Vue状态管理模式,Pinia和Vuex一样都是是vue的全局状态管理器。其实Pinia就是Vuex5,只不过为了尊重原作者的贡献就沿用了这个看起来很甜的名字Pinia
    2022-08-08
  • ElementUI 组件之Layout布局(el-row、el-col)

    ElementUI 组件之Layout布局(el-row、el-col)

    这篇文章主要介绍了ElementUI 组件之Layout布局(el-row、el-col),本文通过实例代码图文相结合给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2024-07-07
  • vue3项目中eslint+prettier统一代码风格方式

    vue3项目中eslint+prettier统一代码风格方式

    这篇文章主要介绍了vue3项目中eslint+prettier统一代码风格方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-05-05
  • vue使用原生swiper代码实例

    vue使用原生swiper代码实例

    这篇文章主要介绍了vue使用原生swiper代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • 8个非常实用的Vue自定义指令

    8个非常实用的Vue自定义指令

    这篇文章主要介绍了8个非常实用的Vue自定义指令,帮助大家更好的理解和使用vue,感兴趣的朋友可以了解下
    2020-12-12
  • vue如何读取外部配置文件

    vue如何读取外部配置文件

    这篇文章主要介绍了vue如何读取外部配置文件问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • 深入理解vue输入框字符限制的优化设计方案

    深入理解vue输入框字符限制的优化设计方案

    限制输入框字符是一项需要结合技术实现与用户体验的综合设计,通过实时限制、提交校验与性能优化,开发者可以高效解决输入限制问题,同时提升用户满意度和数据安全性,本文给大家介绍vue输入框字符限制的优化设计,感兴趣的朋友跟随小编一起看看吧
    2024-12-12
  • vue之组件内监控$store中定义变量的变化详解

    vue之组件内监控$store中定义变量的变化详解

    今天小编就为大家分享一篇vue之组件内监控$store中定义变量的变化详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • vue实现分页加载效果

    vue实现分页加载效果

    这篇文章主要为大家详细介绍了vue实现分页加载效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12

最新评论