查看: 150|回复: 0

Vue父子组件传值六种方式:Props、emit与v-model实践

[复制链接]
发表于 1 小时前 | 显示全部楼层 |阅读模式
在 Vue 的组件化开发中,父子组件通信是绕不开的基础能力。原文围绕父组件向子组件传值、子组件向父组件反馈两条链路,归纳了六种方式:Props、自定义事件 $emit、v-model、Provide/Inject、ref 调用,以及 $attrs 与 $listeners 透传。六种方式并不是互相替代关系,选择时先看数据流向和组件耦合程度:单向数据流优先 Props,子组件反馈用 $emit,需要双向同步用 v-model,需要直接控制子组件实例用 ref,跨层级共享用 Provide/Inject,封装透传组件则考虑 $attrs 与 $listeners。原文还提示,$attrs 与 $listeners 在 Vue 3 Composition API 中主要对应 attrs 和 expose 的使用。

1. Props:最基础的单向传值
Props 是父子通信的主干。父组件可以把字符串常量静态传给子组件,也可以用 v-bind 缩写 : 绑定 data 或计算属性。静态写法如下:
  1. <!-- 父组件 Parent.vue -->
  2. <template>
  3.   <ChildComponent title='静态标题' />
  4. </template>
复制代码

动态绑定写法:
  1. <!-- 父组件 Parent.vue -->
  2. <template>
  3.   <ChildComponent :title='parentTitle' />
  4. </template>
  5. <script>
  6. export default {
  7.   data() {
  8.     return {
  9.       parentTitle: '动态数据'
  10.     }
  11.   }
  12. }
  13. </script>
复制代码

这里的重点是父组件持有数据源,子组件通过 props 接收。原文将 Props 定位为单向数据流的主要方式,适合父级把配置、展示数据或初始值下发给子组件。

2. 自定义事件 $emit:子组件向父组件反馈
当子组件需要把点击结果或内部数据交给父组件时,用 $emit 触发自定义事件,父组件通过 v-on 或 @ 监听。子组件代码:
  1. <!-- 子组件 Child.vue -->
  2. <template>
  3.   <button @click='handleClick'>点击触发事件</button>
  4. </template>
  5. <script>
  6. export default {
  7.   methods: {
  8.     handleClick() {
  9.       this.$emit('custom-event', '从子组件传递的数据');
  10.     }
  11.   }
  12. }
  13. </script>
复制代码

父组件监听并接收数据:
  1. <!-- 父组件 Parent.vue -->
  2. <template>
  3.   <ChildComponent @custom-event='handleData' />
  4. </template>
  5. <script>
  6. export default {
  7.   methods: {
  8.     handleData(data) {
  9.       console.log('接收到的数据:', data);
  10.     }
  11.   }
  12. }
  13. </script>
复制代码

这段代码的关键是事件名要一致:子组件触发 custom-event,父组件就监听 custom-event。父组件的方法参数 data 就是 $emit 第二个参数传出的数据。

3. v-model:双向绑定的语法糖
v-model 常用于父子组件之间的双向数据绑定。原文指出,它的本质是子组件内部通过 props 接收 value,并通过 $emit('input') 更新父组件数据。默认用法下,父组件只写 v-model:
  1. <!-- 父组件 -->
  2. <template>
  3.   <ChildComponent v-model='inputValue' />
  4. </template>
  5. <script>
  6. export default {
  7.   data() {
  8.     return { inputValue: '' };
  9.   }
  10. }
  11. </script>
复制代码

如果需要自定义 v-model,子组件可以定义自己的 prop 和事件名称。原文示例中 prop 为 currentValue,事件为 update:currentValue:
  1. <!-- 子组件 Child.vue -->
  2. <script>
  3. export default {
  4.   props: ['currentValue'],
  5.   emits: ['update:currentValue'],
  6.   methods: {
  7.     change(val) {
  8.       this.$emit('update:currentValue', val);
  9.     }
  10.   }
  11. }
  12. </script>
复制代码

自定义 v-model 时,要重点核对 prop 名与 update: 事件名是否对应。原文给出的模式是 currentValue 配 update:currentValue,调用 change 时把新值交给父组件,从而完成同步更新。

4. Provide/Inject:父子与跨层级共享
Provide/Inject 主要面向跨层级组件通信,但父子组件之间同样可用。父组件通过 provide 提供数据或函数,子组件通过 inject 获取。原文示例:
  1. <!-- 父组件 Parent.vue -->
  2. <script>
  3. export default {
  4.   provide() {
  5.     return {
  6.       themeColor: 'blue',
  7.       getUser: () => ({ name: 'Admin' })
  8.     }
  9.   }
  10. }
  11. </script>
复制代码

子组件注入:
  1. <!-- 子组件 Child.vue -->
  2. <script>
  3. export default {
  4.   inject: ['themeColor', 'getUser']
  5. }
  6. </script>
复制代码

原文说明数据会响应式跟随变化。实际使用时,provide 返回的内容既可以是普通值,也可以是函数,示例中的 getUser 就是一个注入后可调用的函数。对于深层嵌套组件共享主题色或工具方法,这种方式比逐层传 props 更直接。

5. ref:父组件直接访问子组件实例
父组件可以通过 ref 标记子组件,然后在模板中访问子组件的属性和方法。原文示例:
  1. <!-- 父组件 Parent.vue -->
  2. <template>
  3.   <ChildComponent ref='childRef' />
  4.   <button @click='callChildMethod'>调用子组件方法</button>
  5. </template>
  6. <script>
  7. export default {
  8.   methods: {
  9.     callChildMethod() {
  10.       this.$refs.childRef.childMethod();
  11.       console.log(this.$refs.childRef.childData);
  12.     }
  13.   }
  14. }
  15. </script>
复制代码

这段代码中,this.$refs.childRef 指向子组件实例,因此可以调用 childMethod 并读取 childData。使用 ref 的前提是子组件已经渲染并建立了引用;排查时先确认 ref 名称与模板中的 ref 标记一致,再看调用发生在哪个生命周期或事件回调中。

6. $attrs 与 $listeners:属性和事件透传
原文将 $attrs 与 $listeners 列为第六种方式,主要用于组件属性透传和事件透传。它们适合封装中间层组件:父组件传下来的属性或监听事件,中间组件不逐项声明,而是继续传给内部组件。原文同时提示,在 Vue 3 Composition API 中主要是 attrs 和 expose 的使用。由于原文没有展开代码,这里不补写虚构示例,实际落地时应结合项目使用的 Vue 版本确认 API 形态。

选择与排查建议
从数据流看,Props 适合父到子的单向传递;$emit 适合子到父的事件反馈;v-model 适合需要双向同步的表单或值绑定;ref 适合父组件需要直接调用子组件方法、读取子组件数据的场景;Provide/Inject 适合跨层级共享;$attrs 与 $listeners 适合做透传封装。排查传值问题时,可以按顺序检查:数据方向是否选错;props 名称和绑定值是否正确;自定义事件名是否与监听名一致;自定义 v-model 的 prop 与 update: 事件是否配对;ref 是否指向已渲染的子组件实例;Provide/Inject 的注入键名是否与提供方一致。把这些通信方式按场景拆开使用,比在单个组件里堆叠多种传值手段更容易维护。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-10-22 16:35 , Processed in 0.025824 second(s), 29 queries , Gzip On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部