Vue笔记(九)--defineEmits

这一节了解一下Vue3中的defineEmits,defineEmits 是Vue 3.2+引入的编译器宏,仅在<script setup>语法糖中使用,无需从vue导入。 它替代了Options API中的emits选项,返回一个emit函数用于触发事件,简单总结如下:

API:

TypeScript 复制代码
数组语法

<script setup>
const emit = defineEmits(['submit', 'close', 'update:modelValue'])
</script>
TypeScript 复制代码
TypeScript泛型语法

<script setup lang="ts">
const emit = defineEmits<{
  (e: 'submit', payload: { email: string }): void
  (e: 'close'): void
  (e: 'update:modelValue', value: string): void
}>()
// Vue 3.3+ 更简洁写法
const emit = defineEmits<{
  submit: [payload: { email: string }]
  close: []
  'update:modelValue': [value: string]
}>()
</script>

场景:

1 父子组件通信:子组件触发事件通知父组件,如表单提交、列表项删除。

2 自定义v-model双向绑定:子组件接收modelValue prop并触发update:modelValue事件。

3 弹窗/模态框状态通知:子组件触发open/close事件通知父组件控制显隐。

栗子:

TypeScript 复制代码
ChildEmit.vue

<template>
  <div class="child">
    <p>子组件内部数字:{{ innerNum }}</p>
    <button @click="handleAdd">+1,通知父组件</button>
    <button @click="handleClose">关闭弹窗</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const emit = defineEmits<{
  'update:num': [val: number]
  close: []
}>()

const innerNum = ref(0)
const handleAdd = () => {
  innerNum.value++
  emit('update:num', innerNum.value)
}

const handleClose = () => {
  emit('close') // 触发close事件,无参数
}
</script>
TypeScript 复制代码
父组件 ParentEmit.vue

<template>
  <div>
    <h2>父组件,接收子组件事件</h2>
    <p>父拿到的值:{{ parentNum }}</p>
    <ChildEmit @update:num="onUpdateNum" @close="onClose" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import ChildEmit from './ChildEmit.vue'

const parentNum = ref(0)

const onUpdateNum = (val: number) => {
  parentNum.value = val
  console.log('子传过来的新数字:', val)
}

const onClose = () => {
  alert('子组件触发关闭事件')
}
</script>

栗子2

TypeScript 复制代码
子组件 MyDialog.vue

<template>
  <div v-if="visible" class="dialog-wrap">
    <div class="dialog">
      <h3>{{ title }}</h3>
      <p>弹窗内容</p>
      <button @click="handleConfirm">确定</button>
      <button @click="handleCancel">取消</button>
    </div>
  </div>
</template>

<script setup lang="ts">
interface DialogProps {
  visible: boolean 
  title: string   
}
const props = defineProps<DialogProps>()

const emit = defineEmits<{
  confirm: []
  cancel: []
}>()

const handleConfirm = () => {
  emit('confirm')
}
const handleCancel = () => {
  emit('cancel')
}
</script>

<style scoped>
.dialog-wrap {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.4);
  display:flex;
  justify-content:center;
  align-items:center;
}
.dialog {
  background:#fff;
  padding:20px;
  border-radius:8px;
}
</style>
TypeScript 复制代码
父组件 ParentDialog.vue

<template>
  <div>
    <button @click="dialogVisible = true">打开弹窗</button>
    <MyDialog :visible="dialogVisible" title="用户编辑弹窗"
              @confirm="onConfirm"
              @cancel="onCancel"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import MyDialog from './MyDialog.vue'

const dialogVisible = ref(false)

const onConfirm = () => {
  alert('点击确定')
  dialogVisible.value = false
}
const onCancel = () => {
  alert('点击取消')
  dialogVisible.value = false
}
</script>

注意:

1 编译器宏不可导入:直接使用即可,import { defineEmits } from 'vue' 会触发警告。

2 必须顶层调用:只能在 <script setup> 顶层作用域调用,不可置于 if、函数或循环内。

3 每个组件仅调用一次。

相关推荐
叼烟扛炮12 小时前
[LangChain] 学习笔记(06):突破大模型限制——结构化输出(Structured Output)
windows·笔记·学习·langchain
且从容.14 小时前
VUE3学习笔记(根据黑马教程总结)
笔记·学习
蒸蒸yyyyzwd15 小时前
关于 AI 开发相关的一些面经。
笔记·学习
2603_9696948516 小时前
JDBC 基础学习笔记:API 核心原理解析与 CRUD 代码实操
数据库·笔记·mysql·学习方法·database·sql注入
子兮曰17 小时前
Chrome 权限元素实战:144 与 151 的渐进增强写法
前端·javascript·chrome
强尼银手17 小时前
我花一天做了个格斗游戏原型,判定全对,然后被「美术」劝退了
前端·javascript
迪康coolmu17 小时前
出差终端数据安全落地实战:基于迪康端点安全一体化管理系统的四道防线实践
运维·服务器·经验分享·笔记·其他·安全·php
总要学点什么18 小时前
第98篇:三维特效-材质线效果——给一条线换十种材质,虚线的图案只填了一半
开发语言·前端·javascript·ecmascript·gis·webgl·材质
10share18 小时前
基于大模型的 i18n 方案:把中文原文当 Key,轻松搞定多语言维护
前端·vue.js
OpsEye19 小时前
混合云 AI 架构,如何统一做敏感内容拦截?
javascript·ai编程