Vue 组件通信之 “父与子的对话”—— 从 0 到 1 理解 props 与 $emit
作为一名刚接触 Vue 不久的大二前端学习者,最近在做课程小作业时被组件通信搞得头都大了。明明看着教程敲代码,却总是出现 “父组件拿不到子组件数据” 或者 “子组件接收不到父组件参数” 的问题。经过几天的踩坑总结,终于理清了最基础的父子组件通信逻辑,今天就来和大家分享一下我的学习心得。
一、为什么需要组件通信?
刚开始学 Vue 时我一直不懂,为什么不能直接在子组件里调用父组件的数据?后来才明白,Vue 的组件就像一个个独立的 “小模块”,每个组件都有自己的作用域。就像现实中,孩子不能随便翻父母的抽屉,父母也不能直接闯进孩子的房间 —— 组件之间需要有规范的 “沟通方式”,这样代码才不会乱成一锅粥。
最常见的组件关系就是父子关系:比如一个页面(父组件)里包含了一个按钮组件(子组件),页面需要告诉按钮 “你应该显示什么文字”,按钮被点击后需要告诉页面 “我被点击了”。这就是最典型的父子组件通信场景。
二、父传子:用 props 传递数据
父组件给子组件传数据,就像父母给孩子递东西,需要孩子先 “伸出手”—— 也就是在子组件中定义 props 来接收。
1. 父组件如何发数据?
假设父组件是Parent.vue,我们想给子组件传一个 “用户名称”:
vue
<template>
<div class="parent">
<h3>我是父组件</h3>
<!-- 用属性的方式给子组件传值 -->
<Child :username="parentName" />
</div>
</template>
<script>
import Child from './Child.vue' // 引入子组件
export default {
components: { Child },
data() {
return {
parentName: '小明' // 要传递给子组件的数据
}
}
}
</script>
2. 子组件如何接数据?
子组件Child.vue需要通过 props 声明接收:
vue
<template>
<div class="child">
<h4>我是子组件</h4>
<p>父组件传来的名字:{{ username }}</p>
</div>
</template>
<script>
export default {
// 声明接收的属性(必须和父组件传递的属性名一致)
props: ['username']
}
</script>
踩坑提醒:
- props 是 “单向数据流”:子组件不能直接修改 props 的值(就像孩子不能直接改父母给的东西),如果要改,得先复制到 data 里
- 命名规范:父组件用 kebab-case(如
user-name),子组件 props 用 camelCase(如userName),Vue 会自动转换
三、子传父:用 $emit 触发事件
子组件给父组件传数据,更像是 “喊一声”—— 子组件通过$emit触发一个事件,父组件监听这个事件并接收数据。
1. 子组件如何发数据?
子组件里有个按钮,点击后要把自己的数据传给父组件:
vue
<template>
<div class="child">
<button @click="sendMsg">告诉父组件</button>
</div>
</template>
<script>
export default {
data() {
return {
childMsg: '爸爸我想吃西瓜' // 子组件要传递的数据
}
},
methods: {
sendMsg() {
// 第一个参数:事件名(自定义),第二个参数:要传递的数据
this.$emit('tellParent', this.childMsg)
}
}
}
</script>
2. 父组件如何接数据?
父组件监听子组件触发的事件:
vue
<template>
<div class="parent">
<!-- 监听子组件的tellParent事件,用getMsg方法接收数据 -->
<Child @tellParent="getMsg" />
<p>子组件说:{{ childMessage }}</p>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: { Child },
data() {
return {
childMessage: '' // 存储子组件传来的数据
}
},
methods: {
getMsg(msg) {
// msg就是子组件传递过来的数据
this.childMessage = msg
}
}
}
</script>
踩坑提醒:
- 事件名要一致:子组件
$emit('xxx'),父组件就要@xxx监听 - 别忘记传参数:刚开始我经常只写
this.$emit('tellParent'),结果父组件接收不到数据,原来漏了第二个参数!
四、实战小案例:父子组件双向互动
结合上面两种方式,做一个简单的互动:父组件给子组件传一个初始值,子组件修改后再传给父组件显示。
完整代码可以参考我之前练习的例子:
- 父组件通过 props 给子组件传初始消息
- 子组件通过按钮点击,用 $emit 把修改后的数据传回父组件
- 父组件更新数据后,子组件会自动同步(因为 props 是响应式的)
这个过程就像父子对话:
- 父:“今天天气不错”(props 传值)
- 子:“是啊,适合出去玩”($emit 传值)
- 父:“那我们下午去公园”(props 更新,子组件同步显示)
五、总结
学了这么久才发现,Vue 的组件通信其实很像现实中的人际交流 —— 有来有回,有规有矩。刚开始总觉得难,其实是因为没搞懂 “props 是父给子,$emit 是子喊父” 这个核心逻辑。
作为前端新手,我觉得没必要一开始就纠结复杂的通信方式(比如 Vuex、Pinia),先把最基础的父子组件通信练熟,再逐步学习更高级的用法。如果大家有和我一样的困惑,建议多写几个小案例,亲手调试一下数据流向,比光看教程有用多了~
最后,欢迎大家在评论区分享自己学习组件通信时踩过的坑,让我们一起避坑成长!
更多推荐


所有评论(0)