Vue:Props 和 Emits 对比总结

Props与Emits对比摘要

核心区别:Props实现父→子单向数据流(用于配置),Emits实现子→父事件通知(用于交互)。

特性对比

  • 数据流:Props向下传递只读数据,Emits向上触发事件
  • 验证:Props支持类型/默认值验证,Emits无内置验证
  • Vue3优化:均支持TS类型推断,Composition API提供defineProps/defineEmits

使用场景

  • Props:初始化配置/展示数据
  • Emits:用户交互反馈/状态变更通知

最佳实践

  • 遵循单向数据流原则
  • 为复杂数据添加验证
  • 使用kebab-case命名事件
  • 避免直接修改Props

特殊用法:v-model本质是Props+Emits的组合语法糖。


Props 和 Emits 对比总结

对比维度 Props(属性) Emits(事件)
数据流向 父 → 子(单向向下) 子 → 父(单向向上)
作用 父组件向子组件传递数据 子组件向父组件通知事件
使用场景 配置子组件、传递初始数据 用户交互反馈、状态变化通知
是否可变 只读(子组件不应直接修改) 可触发多次,传递不同数据
响应式 在子组件中是响应式的 事件本身不是响应式的,但可传递响应式数据

Vue 2 Options API 中的用法

特性 Props Emits
声明方式 props: ['title', 'content'] 或对象形式 emits: ['submit', 'change'](Vue 2.3+)
类型验证 支持完整类型验证 无内置验证(Vue 2 中)
默认值 通过 default 属性设置 不适用
必需性 通过 required: true 设置 不适用
代码示例 props: {<br> title: {<br> type: String,<br> required: true<br> }<br>} emits: ['update:modelValue']

Vue 3 Composition API / <script setup> 中的用法

特性 Props Emits
声明方式 defineProps() defineEmits()
类型验证 支持对象和泛型两种方式 支持数组和对象两种方式
TypeScript 完美支持类型推断 完美支持类型推断
访问方式 通过 props.xxx 访问 通过 emit('event', data) 触发
代码示例 const props = defineProps<{<br> title: string,<br> count?: number<br>}>() const emit = defineEmits<{<br> (e: 'submit', data: any): void<br>}>()

实际使用示例对比

Props 示例

javascript 复制代码
<!-- 父组件 Parent.vue -->
<template>
  <!-- 传递 props -->
  <ChildComponent :title="pageTitle" :count="counter" />
</template>

<!-- 子组件 Child.vue -->
<template>
  <h1>{{ title }}</h1>
  <p>计数: {{ count }}</p>
</template>

<script setup>
// Vue 3 Composition API
const props = defineProps({
  title: String,
  count: {
    type: Number,
    default: 0
  }
})
</script>

Emits 示例

vue

javascript 复制代码
<!-- 子组件 Child.vue -->
<template>
  <button @click="handleClick">提交</button>
</template>

<script setup>
// Vue 3 Composition API
const emit = defineEmits(['submit', 'update:value'])

const handleClick = () => {
  // 触发事件并传递数据
  emit('submit', { id: 1, data: 'test' })
  emit('update:value', 'new value')
}
</script>

<!-- 父组件 Parent.vue -->
<template>
  <!-- 监听事件 -->
  <ChildComponent 
    @submit="handleSubmit" 
    @update:value="value = $event" 
  />
</template>

特殊用法:双向绑定

模式 实现方式 说明
v-model props: modelValue + emits: update:modelValue Vue 3 默认方式
v-model:propName props: propName + emits: update:propName Vue 3 参数化 v-model
.sync 修饰符 props: xxx + emits: update:xxx Vue 2 方式(Vue 3 已废弃)

双向绑定示例

vue

javascript 复制代码
<!-- 子组件 CustomInput.vue -->
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])

const updateValue = (event) => {
  emit('update:modelValue', event.target.value)
}
</script>

<template>
  <input :value="modelValue" @input="updateValue" />
</template>

<!-- 父组件使用 -->
<template>
  <!-- Vue 3 默认 v-model -->
  <CustomInput v-model="username" />
  
  <!-- Vue 3 参数化 v-model -->
  <CustomInput v-model:firstName="first" v-model:lastName="last" />
</template>

最佳实践对比

最佳实践 Props Emits
命名规范 使用 camelCase 声明,kebab-case 传递 使用 kebab-case 命名事件
数据验证 始终添加类型验证和默认值 为复杂数据添加验证函数
单向数据流 不要直接修改 props,使用 emits 通知父组件修改 传递最小必要数据,避免传递整个对象
TypeScript 使用泛型语法获得更好的类型安全 为事件定义完整类型签名
文档注释 为每个 prop 添加 JSDoc 注释说明用途 为每个事件添加注释说明触发时机

常见错误对比

错误类型 Props 相关错误 Emits 相关错误
语法错误 使用 v-bind 传递动态值::prop="value" 监听事件使用 @ 或 v-on:@event="handler"
逻辑错误 在子组件中修改 props(违反单向数据流) 在父组件中直接修改子组件数据(应通过事件)
性能问题 传递大型对象导致不必要的重新渲染 频繁触发高开销的事件处理函数
类型错误 传递错误类型的数据(类型验证可捕获) 事件参数类型与处理函数期望类型不匹配

选择指南

场景 应该使用 Props 应该使用 Emits
配置子组件 ✅ 传递初始配置、样式参数
用户交互反馈 ✅ 按钮点击、表单提交
数据展示 ✅ 传递要显示的数据
状态变化通知 ✅ 数据更新、组件状态变化
表单输入 ✅ 接收初始值 ✅ 输入变化时通知父组件

核心原则:Props 向下,Events 向上。


父组件通过 Props 控制子组件的显示,子组件通过 Emits 通知父组件用户交互。

相关推荐
saadiya~2 小时前
实战笔记:在 Ubuntu 离线部署 Vue + Nginx 踩坑与避雷指南
vue.js·笔记·nginx
随祥3 小时前
Tauri+vue开发桌面程序环境搭建
前端·javascript·vue.js
老华带你飞12 小时前
农产品销售管理|基于java + vue农产品销售管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
C_心欲无痕13 小时前
vue3 - 类与样式的绑定
javascript·vue.js·vue3
JIngJaneIL13 小时前
基于springboot + vue房屋租赁管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
期待のcode15 小时前
@RequestBody的伪表单提交场景
java·前端·vue.js·后端
一颗烂土豆15 小时前
vfit.js v2.0.0 发布:精简、语义化与核心重构 🎉
前端·vue.js·响应式设计
总之就是非常可爱16 小时前
vue3 KeepAlive 核心原理和渲染更新流程
前端·vue.js·面试
red润16 小时前
手把手封装Iframe父子单向双向通讯功能
前端·javascript·vue.js