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 每个组件仅调用一次。

相关推荐
AomanHao1 小时前
【阅读笔记】Weighted Guided Image Filtering(WGIF)权重引导滤波
图像处理·人工智能·笔记·计算机视觉·滤波·引导滤波
weixin_440730502 小时前
字符编码笔记-utf-8 、unicode、gbk,ascii编码格式
开发语言·笔记
andyweike9 小时前
php笔记
开发语言·笔记·php
xian_wwq11 小时前
【学习笔记】等保合规安全基线核查实战
笔记·学习
M78佐菲12 小时前
ARM学习笔记(11)
linux·arm开发·笔记·嵌入式硬件·学习
M78佐菲12 小时前
ARM学习笔记(10)
linux·arm开发·笔记·嵌入式硬件·学习
李游Leo13 小时前
HarmonyOS 7 + ArkUI + RelationalStore 学习笔记:本地数据分层存储与状态持久化架构实践【鸿蒙心迹】
笔记·学习·架构·harmonyos
我命由我1234513 小时前
经纪人的职业定义
经验分享·笔记·学习·职场和发展·求职招聘·职场发展·学习方法
摇滚侠14 小时前
《On Java 中文版 基础卷》阅读笔记 对象无处不在 03
java·笔记·python