Vue 3 组件通信入门:props、emit 与 Pinia 一瞥

举报
神的孩子都在跳舞 发表于 2026/11/08 11:07:40 2026/11/08
【摘要】 刚开始写 Vue 3 的时候,很多人会把所有逻辑塞进一个组件里,页面一复杂就变得难以维护。把页面拆成小组件之后,新的问题就来了:组件之间怎么说话?这篇文章把最常用的三种通信方式串起来讲清楚。 为什么组件要通信组件化的本质是分工:列表组件负责展示,表单组件负责输入,按钮组件负责触发操作。数据不可能只待在一个组件里,父组件拿到的数据要交给子组件显示,子组件里的操作结果又要回传给父组件处理。如果没...

刚开始写 Vue 3 的时候,很多人会把所有逻辑塞进一个组件里,页面一复杂就变得难以维护。把页面拆成小组件之后,新的问题就来了:组件之间怎么说话?这篇文章把最常用的三种通信方式串起来讲清楚。

为什么组件要通信

组件化的本质是分工:列表组件负责展示,表单组件负责输入,按钮组件负责触发操作。数据不可能只待在一个组件里,父组件拿到的数据要交给子组件显示,子组件里的操作结果又要回传给父组件处理。如果没有清晰的通信规则,数据会在组件之间乱窜,出了问题很难定位。

父传子:props

父组件向子组件传数据用 props,这是最常用、也最推荐的方式。子组件先声明自己需要什么,父组件再把数据传进来,数据的来源一目了然。

<!-- 父组件 -->
<UserCard :name="userName" :age="18" />

<!-- 子组件 UserCard.vue -->
<script setup>
const props = defineProps({
  name: String,
  age: Number
})
</script>
<template>
  <p>{{ props.name }},{{ props.age }} 岁</p>
</template>

用 props 有一个好处:子组件只管展示,不管数据从哪来,复用起来很方便。

子传父:emit

子组件想把消息传回父组件,就用 emit 触发自定义事件。父组件监听这个事件,拿到数据后再决定怎么处理。

<!-- 子组件 -->
<script setup>
const emit = defineEmits(['update-name'])
function onInput(event) {
  emit('update-name', event.target.value)
}
</script>
<template>
  <input @input="onInput" placeholder="输入新名字" />
</template>

父组件里写 @update-name="userName = $event" 就能收到新值。事件名建议用短横线分隔的小写形式,和原生事件的写法保持一致,读起来不容易混淆。

兄弟组件怎么办

两个没有父子关系的组件要通信,最直接的办法是把共享的状态提升到它们共同的父组件:父组件持有数据,通过 props 分发给两个子组件,子组件再用 emit 把变化传回父组件。这样数据只有一条来路,流程很清晰。如果兄弟组件层级很深、中间要经过很多层 props,代码会变得啰嗦,这时可以考虑用全局状态。

Pinia 全局状态一瞥

Pinia 是 Vue 官方推荐的状态管理库,适合放那些很多组件都要用到的数据,比如登录用户信息、主题设置。用法很直观:先定义一个 store,再在需要的组件里读取或修改它。

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({ name: '小明' }),
  actions: {
    rename(newName) {
      this.name = newName
    }
  }
})

组件里调用 useUserStore() 就能拿到同一份状态,不用一层层传 props。不过全局状态也不是越多越好,只有真正共享的数据才值得放进来。

常见坑

第一,props 是单向数据流,子组件不要直接修改 props 的值。需要改的时候,先把新值通过 emit 交给父组件,由父组件更新后再传下来,这样数据的变化才有迹可循。

第二,emit 的事件名要和监听的名字完全一致,大小写或短横线写错了,事件就悄悄失效了,页面上看不到任何报错,最容易浪费时间。

第三,不要一上来就把所有数据都放进 Pinia。只在当前组件内部用的数据,留在组件自己的 ref 里就够了,全局状态用得越多,组件之间的耦合就越强,后面改起来越费劲。

总结一下:父传子用 props,子传父用 emit,跨组件的共享数据再请 Pinia 出马。先把这三条路走顺,Vue 3 的组件通信就入门了。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。