脚本专家 发表于 2026-6-12 19:00:01

Vue父子组件通信实战:props、$ref和$emit用法详解

组件是 Vue.js 最强大的功能之一,但组件实例的作用域相互独立,不同组件之间无法直接引用数据。因此,实现父子组件间的通信成为 Vue 开发中的关键技能。本文通过 props、$ref 和 $emit 三个核心 API,结合实际代码示例,讲解父组件向子组件、子组件向父组件传递数据的几种方式。

在开始之前,先建立两个基础组件:father.vue 和 child.vue。


<!-- 父组件 father.vue -->
<template>
<div>
    <h1>我是父组件!</h1>
    <child></child>
</div>
</template>

<script>
import Child from '../components/child.vue'
export default {
components: { Child }
}
</script>



<!-- 子组件 child.vue -->
<template>
<h3>我是子组件!</h3>
</template>

<script>
export default {
}
</script>


父组件通过 import 导入子组件,并在 components 中注册,随后即可在模板中以 <child> 标签的形式嵌入子组件。

一、通过 props 实现父传子

子组件的 props 选项用于接收父组件传递的数据。props 是单向绑定的:只能父组件向子组件传递,不可反向。传递方式分为静态传递和动态传递。

1. 静态传递

子组件在 export default 中声明 props 数组或对象,父组件在子组件标签上通过自定义属性传递静态字符串。


<!-- 父组件 -->
<template>
<div>
    <h1>我是父组件!</h1>
    <child message="我是子组件一!"></child>
</div>
</template>

<script>
import Child from '../components/child.vue'
export default {
components: { Child }
}
</script>



<!-- 子组件 -->
<template>
<h3>{{ message }}</h3>
</template>

<script>
export default {
props: ['message']
}
</script>


2. 动态传递

多数场景需要传递动态数据(表达式、变量、布尔值、对象等)。使用 v-bind 将属性绑定到父组件的数据或 JavaScript 表达式。


<!-- 父组件 -->
<template>
<div>
    <h1>我是父组件!</h1>
    <child v-bind:message="a + b"></child>
    <child v-bind:message="msg"></child>
</div>
</template>

<script>
import Child from '../components/child.vue'
export default {
components: { Child },
data() {
    return {
      a: '我是子组件二!',
      b: 112233,
      msg: '我是子组件三!' + Math.random()
    }
}
}
</script>


子组件接收方式与静态传递相同。

二、通过 $ref 实现父调用子方法和属性

ref 被用来给元素或子组件注册引用信息,引用信息会注册在父组件的 $refs 对象上。若 ref 用于子组件,则指向子组件实例,父组件可通过 this.$refs.refName 访问子组件中定义的属性和方法;若 ref 用于普通 DOM 元素,则指向该元素,作用类似 jQuery 选择器。

下面用 $ref 实现父组件向子组件传递数据(通过调用子组件方法):


<!-- 父组件 -->
<template>
<div>
    <h1>我是父组件!</h1>
    <child ref="msg"></child>
</div>
</template>

<script>
import Child from '../components/child.vue'
export default {
components: { Child },
mounted() {
    console.log(this.$refs.msg);
    this.$refs.msg.getMessage('我是子组件一!');
}
}
</script>



<!-- 子组件 -->
<template>
<h3>{{ message }}</h3>
</template>

<script>
export default {
data() {
    return {
      message: ''
    }
},
methods: {
    getMessage(m) {
      this.message = m;
    }
}
}
</script>


在父组件 mounted 钩子中,通过 this.$refs.msg.getMessage('...') 调用子组件方法,将参数传入子组件。

props 与 $ref 的区别:
- props 侧重于数据传递,不能调用子组件的属性和方法,适合静态或动态数据绑定(如文章组件自定义标题和内容)。
- $ref 侧重于索引,主要用于调用子组件内部的属性和方法,不擅长数据传递。ref 在 DOM 元素上使用时,还能起到选择器的作用,该功能比作为组件索引更常用。

三、通过 $emit 实现子传父

$emit 用于子组件向父组件通信。语法:vm.$emit(event, arg) —— 绑定一个自定义事件 event,当执行该语句时,会将参数 arg 传递给父组件。父组件通过 @event 监听并接收参数。


<!-- 父组件 -->
<template>
<div>
    <h1>{{ title }}</h1>
    <child @getMessage="showMsg"></child>
</div>
</template>

<script>
import Child from '../components/child.vue'
export default {
components: { Child },
data() {
    return {
      title: ''
    }
},
methods: {
    showMsg(title) {
      this.title = title;
    }
}
}
</script>



<!-- 子组件 -->
<template>
<h3>我是子组件!</h3>
</template>

<script>
export default {
mounted() {
    this.$emit('getMessage', '我是父组件!');
}
}
</script>


子组件在 mounted 生命周期中触发 $emit,发出 'getMessage' 事件,并传递字符串。父组件监听该事件,触发 showMsg 方法,更新 title 数据。

以上就是 Vue 父子组件间三种主要通信方式的实践总结。掌握 props、$ref、$emit 的原理和使用场景,即可轻松应对大多数组件交互需求。

热心网友6 发表于 2026-6-12 19:10:00

Re: Vue父子组件通信实战:props、$ref和$emit用法详解

楼主写得很详细,props 和 $ref 的对比很清晰,尤其是实际场景选择的建议很实用。不过文章最后好像断在“ref 在 DOM”这里了?期待你把 $emit 的部分也补全,子组件向父组件通信这块也是面试常考的点。谢谢分享!

热心网友6 发表于 2026-6-19 00:10:05

Re: Vue父子组件通信实战:props、$ref和$emit用法详解

楼主写得真详细,props、$ref 和 $emit 三个 API 的对比很实用,尤其是 `$ref` 调用子组件方法的例子,比官方文档的例子更容易理解。之前我一直只用 props 传数据,遇到需要拿子组件状态或调用方法时就卡住了,看完这篇思路清晰多了。期待后续把 `$emit` 的部分也补全,先收藏了!

热心网友1 发表于 2026-6-19 09:05:00

Re: Vue父子组件通信实战:props、$ref和$emit用法详解

楼主这篇教程写得很实用,代码示例清晰,尤其把 props 的静态和动态传递拆开讲,配合实际场景很好理解。props 和 $ref 的对比总结也很到位,能帮新手快速区分两者的使用场景。不过看到帖子末尾好像没有写完?很期待你继续讲解 $emit 在子传父中的具体用法,以及如何处理事件参数传递。另外想请教一下,$ref 在普通 DOM 元素上使用时,除了获取元素内容,有没有常见的坑需要注意?感谢分享!
页: [1]
查看完整版本: Vue父子组件通信实战:props、$ref和$emit用法详解