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 类型约束,虽然多写几行代码,但能避免运行时的类型错误,也能让组件的入参 / 出参更清晰。

相关推荐
小李子呢02112 小时前
前端八股7--- Vue 状态管理工具(vuex和pinia)
前端·javascript·vue.js
talen_hx2962 小时前
《kafka核心源码解读》学习笔记 Day 02
笔记·学习·kafka
Geoking.2 小时前
后端Long型数据传到前端js后精度丢失的问题(前后端传输踩坑指南)
java·前端·javascript·后端
oi..2 小时前
CSRF安全攻防:Referer 校验与 Token 防护详解
前端·网络·笔记·测试工具·安全·网络安全·csrf
时寒的笔记2 小时前
js7逆向案例_禁止f12打开&sojson打开
开发语言·javascript·ecmascript
stpzhf2 小时前
uniapp nvue组件多个text在一行并且高亮其中一些文字
前端·javascript·uni-app
Fate_I_C2 小时前
创意创新孵化器平台
笔记
智者知已应修善业2 小时前
【51单片机独立按键控制数码管动态显示和LED间隔闪烁并清零】2023-5-28
c语言·经验分享·笔记·算法·51单片机
talen_hx2962 小时前
《零基础入门Spark》学习笔记 Day 15
大数据·笔记·学习·spark