Vue 3 的父子组件传值主要遵循单向数据流的原则:父传子 和 子传父。

Vue 3 的父子组件传值主要遵循单向数据流 的原则:父传子 和 子传父 。

以下是详细的实现方式、代码示例以及注意事项。

1. 父传子

父组件通过自定义属性 传递数据,子组件通过 defineProps 接收数据。

核心步骤:
  1. 父组件 :在子组件标签上绑定属性(如 :title="msg")。
  2. 子组件 :使用 defineProps 声明并接收属性。
代码示例:

父组件

html 复制代码
<template>
  <div>
    <h2>父组件</h2>
    <!-- 1. 传递静态值 -->
    <ChildComponent title="静态标题" />
    
    <!-- 2. 传递动态变量 -->
    <ChildComponent :title="parentMsg" :age="18" />
  </div>
</template>
<script setup>
import ChildComponent from './ChildComponent.vue'
import { ref } from 'vue'
const parentMsg = ref('来自父组件的动态消息')
</script>

子组件

html 复制代码
<template>
  <div class="child-box">
    <p>子组件接收到的标题:{{ title }}</p>
    <p>年龄:{{ age }}</p>
  </div>
</template>
<script setup>
// 2. 使用 defineProps 接收
// 写法一:数组写法(简单,但不直观)
// defineProps(['title', 'age'])
// 写法二:对象写法(推荐,可以限制类型和默认值)
const props = defineProps({
  title: {
    type: String,
    required: true, // 必填
    default: '默认标题' // 默认值
  },
  age: {
    type: Number,
    default: 0
  }
})
// 注意:在 JS 中使用 props 变量需要通过 props.title
console.log(props.title) 
</script>

⚠️ 注意:

  • 在 <template> 模板中直接使用变量名(如 title)。
  • 在 <script> 代码中,需要通过 props.title 访问。
  • 不要在子组件中直接修改 props 传来的值 (如 props.title = 'new'),这会违反单向数据流,导致报错。

2. 子传父

父组件通过自定义事件 接收数据,子组件通过 defineEmits 触发事件并传参。

核心步骤:
  1. 父组件 :在子组件标签上监听事件(如 @change-msg="handleMsg")。
  2. 子组件 :使用 defineEmits 声明事件,并在合适时机调用 emit('事件名', 数据)。
代码示例:

父组件

html 复制代码
<template>
  <div>
    <h2>父组件收到的消息:{{ msgFromChild }}</h2>
    
    <!-- 1. 绑定自定义事件 change-msg -->
    <ChildComponent @change-msg="handleChange" />
  </div>
</template>
<script setup>
import ChildComponent from './ChildComponent.vue'
import { ref } from 'vue'
const msgFromChild = ref('等待子组件发送...')
// 3. 定义处理函数,接收子组件传来的参数
const handleChange = (newMsg) => {
  msgFromChild.value = newMsg
}
</script>

子组件

html 复制代码
<template>
  <button @click="sendToParent">点击向父组件传值</button>
</template>
<script setup>
// 1. 声明要触发的事件
const emit = defineEmits(['change-msg'])
const sendToParent = () => {
  const message = '你好父组件,我是子组件'
  // 2. 触发事件并传递数据
  emit('change-msg', message)
}
</script>

💡 技巧 :

Vue 官方推荐事件命名使用 kebab-case (短横线命名) ,如 @update-value,因为在 HTML 模板中不区分大小写,@updateValue 可能会被解析成 @updatevalue。


3. 双向绑定

如果你想要实现"父传子,子修改后自动传回父"的效果(类似 v-model),Vue 3 提供了更简便的方式。

方式一:使用 v-model (推荐)

Vue 3 的 v-model 默认绑定了 modelValue 属性和 update:modelValue 事件。
父组件

html 复制代码
<template>
  <!-- 等同于 :modelValue="text" @update:modelValue="text = $event" -->
  <ChildInput v-model="text" />
</template>

子组件

html 复制代码
<template>
  <!-- 必须绑定 value 并触发 input 事件 -->
  <input 
    type="text" 
    :value="modelValue" 
    @input="$emit('update:modelValue', $event.target.value)"
  />
</template>
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>
方式二:defineModel 宏 (Vue 3.4+ 最新语法)

这是一个编译器宏,大大简化了双向绑定的代码。
子组件

html 复制代码
<script setup>
// 自动定义 props 和 emit,返回一个可写的 ref
const modelValue = defineModel()
// 修改 modelValue.value 会自动同步到父组件
</script>
<template>
  <input v-model="modelValue" />
</template>

4. 父组件直接操作子组件

如果父组件想要直接调用子组件的方法或访问其数据,可以通过 ref 获取子组件实例。
父组件

html 复制代码
<template>
  <ChildComponent ref="childRef" />
  <button @click="callChildMethod">调用子组件方法</button>
</template>
<script setup>
import { ref } from 'vue'
import ChildComponent from './ChildComponent.vue'
// 1. 定义与 ref 同名的变量
const childRef = ref(null)
const callChildMethod = () => {
  // 3. 通过 value 访问子组件暴露的方法
  childRef.value.someMethod()
}
</script>

子组件

html 复制代码
<script setup>
const someMethod = () => {
  console.log('子组件方法被调用了!')
}
// 2. 必须使用 defineExpose 暴露方法或属性,父组件才能通过 ref 调用
defineExpose({
  someMethod
})
</script>

总结图表

传输方向 核心语法 父组件操作 子组件操作
父传子 Props <Child :msg="data" /> const props = defineProps(['msg'])
子传父 Emits <Child @update="fn" /> const emit = defineEmits(['update'])
双向绑定 v-model <Child v-model="data" /> defineProps + defineEmits 或 defineModel
直接调用 Ref <Child ref="cRef" /> defineExpose({ method })
相关推荐
Dream-Y.ocean2 小时前
鸿蒙PC平台宅匠 3D 室内设计适配实战:基于 Electron 壳方案的 Three.js 双渲染引擎与参数化户型编辑器开发
javascript·3d·harmonyos
Csvn3 小时前
性能监控
前端
Highcharts.js3 小时前
Highcharts Gantt使用符号的自定义数据标签开发甘特图示例
javascript·甘特图·highcharts·图表开发·实战代码·响应式图表
Csvn3 小时前
构建工具
前端
FRing033 小时前
vue2干货总结3(computed计算属性、watch监听器)
开发语言·前端·vue.js·vue2
Java小卷4 小时前
JuanForm vs FormCreate!Vue3 表单引擎联动配置 PK!
vue.js·低代码
kyriewen6 小时前
Skills 榜前 10 我全装了:只有 3 个能直接用
前端·javascript·程序员
IT_陈寒6 小时前
当Java的hashCode遇上Lombok,我的缓存被全清了
前端·人工智能·后端
工控丫丫6 小时前
帆软看板中经常使用的公式函数及经常搭的组合
前端·javascript·数据库
jerrywus7 小时前
我用 GPT-6.1-sol 做了台会讲解的 3D 售货机:60 罐饮料,一口没喝上
前端·agent·claude