Vue3+TS 笔记:Props 与 Emits 的正确打开方式

最近在回顾 Vue3的核心知识点,今天重点梳理了Props(父传子)Emits(子传父) 的使用方式,结合实操代码做了总结,既方便自己后续复习,也希望能帮到同样在学 Vue3 的你们~

一、Props:父组件向子组件传递数据

1.1 核心知识点

Props 是 Vue3 中父组件向子组件传递数据的核心方式,遵循单向数据流原则(子组件只能读取 Props 数据,不能直接修改,修改需通过父组件更新)。结合 TypeScript 可以给 Props 做严格的类型约束,让代码更健壮。(基础概念部分可以参考一下我的上一篇文章)

1.2 实操代码解析

TypeScript 复制代码
<script setup lang="ts">
import { computed } from 'vue';

// 1. 用TS接口定义Props的类型约束
interface Props{
    name:string,          // 必传字符串类型
    age?:number,          // 可选 数字类型
    isMall?:boolean,      // 可选 布尔类型
    user?:object,         // 可选 对象类型
    status?:'success'|'error'|'warning' // 可选联合类型
}

// 2. 定义Props并设置默认值
const props =withDefaults(defineProps<Props>(),{age:18}) 
// 没有默认值可以直接const props =defineProps<Props>()
// 知识点:withDefaults用于给可选Props设置默认值,这里给age默认18
// 单向数据流:子组件只能读props.age,不能直接改,改的话要让父组件传新值
</script>

<template>
    <div>
        <br>
        子组件2
        {{ props }}  <!-- 直接渲染所有props数据 -->
        age:{{ props.age }} <!-- 渲染单个props值 -->
    </div>
</template>

关键总结

  • 用 TS 接口**interface**可以清晰定义 Props 的类型(必传 / 可选、基础类型 / 联合类型);
  • withDefaults() 专门用于给可选 Props 设置默认值(注意:只有可选属性才能设默认值);
  • 单向数据流:子组件修改 Props 不会同步到父组件,避免数据混乱,这是 Vue 组件通信的核心原则。

二、Emits:子组件向父组件传递事件

子组件想给父组件传数据,不能直接修改父组件数据,而是通过触发自定义事件 的方式(Emits),父组件监听该事件并处理数据。Vue3 中 Emits 有两种写法,结合 TS 推荐第二种~

2.1 基础写法--->字符串数组形式

适合简单场景,直接声明自定义事件名称:

TypeScript 复制代码
<script setup lang="ts">
// 1. 定义自定义事件(字符串数组形式)
const emits = defineEmits(['sub'])

// 2. 事件处理函数:监听输入框回车,获取值并触发自定义事件
const handler = (e:Event) =>{
    // 类型断言:把e.target转为HTMLInputElement,才能拿到value
    const val = (e.target as HTMLInputElement).value
    // 触发自定义事件,把输入值传给父组件
    emits('sub',val)
}
</script>

<template>
    <div>
        <!-- 监听输入框回车事件,触发handler -->
        <input type="text" placeholder="输入" @keyup.enter="handler">
    </div>
</template>

2.2 进阶写法--->TS类型字面量写法

TS 项目推荐这种写法,能严格约束事件名称和参数类型,减少错误:

TypeScript 复制代码
<script setup lang="ts">
// 1. 用TS类型字面量定义Emits:约束事件名、参数类型、返回值
const emits = defineEmits<{
    (e:"submit",val:string):void  // e=事件名,val=参数(字符串类型),void=无返回值
}>()

// 2. 回车事件处理:触发submit事件,传递输入值
function handler(e:Event){
    const val = (e.target as HTMLInputElement).value
    emits("submit",val)
}
</script>

<template>
    子组件1
    <input placeholder="go" @keyup.enter="handler">
</template>

2.3 父组件接受事件

不管子组件用哪种 Emits 写法,父组件都通过**@事件名**监听并处理数据:

TypeScript 复制代码
<script setup lang="ts">
// 导入子组件
import emit2 from "./study_tree/13.ts中emits.vue"

// 父组件的事件处理函数:接收子组件传递的值
function submit(val:string){
  console.log('父接受的事件',val);
}
</script>

<template>
  <div>
    父组件
    <!-- 监听子组件的submit事件,触发父组件的submit函数 -->
    <emit2 @submit="submit"></emit2>
  </div>
</template>

关键总结

  • defineEmits 是 Vue3 定义自定义事件的专用 API,替代了 Vue2 的**emits**选项;
  • 字符串数组写法简单,但无类型约束;TS 类型字面量写法能约束事件名和参数类型,适合大型项目;
  • 类型断言**(e.target as HTMLInputElement)**是 TS 中获取 DOM 元素属性的常用方式,避免类型报错;
  • 子组件**emits(事件名, 参数)** 触发事件,父组件**@事件名="处理函数"** 接收参数,完成子传父。

三、整体学习总结

  1. Props 和 Emits 是 Vue3 组件通信的基础,遵循 "父传子用 Props,子传父用 Emits" 的原则;
  2. 结合 TypeScript 能给 Props/Emits 做类型约束,提前规避运行时错误,这也是现代 Vue 项目的标配;
  3. 单向数据流是核心:Props 只读,子组件不能直接修改,必须通过父组件更新;Emits 是子组件通知父组件修改数据的 "正规途径";
  4. 两种 Emits 写法各有适用场景:小项目 / 快速开发用字符串数组,中大型 TS 项目用类型字面量。

Tip

加上ts后,从Props 的接口定义、Emits 的 TS 类型约束,虽然多写几行代码,但能避免运行时的类型错误,也能让组件的入参 / 出参更清晰。

相关推荐
We་ct15 分钟前
LeetCode 5. 最长回文子串:DP + 中心扩展
前端·javascript·算法·leetcode·typescript
William Dawson4 小时前
2026软考中级系统集成项目管理工程师备考笔记
笔记·系统集成项目管理工程师
@yanyu6665 小时前
登录注册功能-明文
vue.js·springboot
love530love7 小时前
精简版|Claude-HUD 插件介绍 + 一键安装教程
人工智能·windows·笔记
想成为优秀工程师的爸爸7 小时前
第三十篇技术笔记:郭大侠学UDS - 人有生老三千疾,望闻问切良方医
网络·笔记·网络协议·tcp/ip·信息与通信
cn_mengbei8 小时前
用React Native开发OpenHarmony应用:Reanimated共享元素过渡
javascript·react native·react.js
kyriewen8 小时前
前端测试:别为了100%覆盖率而写测试,那是自欺欺人
前端·javascript·单元测试
tq10869 小时前
数学:约束表征空间的最小闭包
笔记
Data_Journal9 小时前
如何使用cURL更改User Agent
大数据·服务器·前端·javascript·数据库
掌心向暖RPA自动化9 小时前
如何获取网页某个元素在屏幕可见部分的中心坐标影刀RPA懒加载坐标定位技巧
java·javascript·自动化·rpa·影刀rpa