详细分析Vue3中的defineEmits基本知识(子传父)

前言

对于Vue3中的基本知识推荐阅读:

  1. 详细分析Vue3中组合式API(附Demo)
  2. 详细分析Vue3中的props用法(父传子)
  3. 详细分析Vue3中的emit用法(子传父)

1. 基本知识

defineEmits 是 Vue 3 的组合式 API(Composition API)的一部分,用于在组件中定义和使用自定义事件

它替代了 Vue 2 中的 this.$emitthis.$on,让事件的定义和使用变得更加清晰和类型安全,尤其在 TypeScript 中

defineEmits 的基本用法

  1. 定义事件:在组件内部通过 defineEmits 定义事件
    可以传递一个数组或对象来定义事件名和事件参数

  2. 触发事件:使用 emit 方法触发定义的事件

  3. 接收事件:在父组件中使用自定义事件监听器来接收事件

2. Demo

2.1 传值

基本的用法如下:

在子组件中,定义两个事件:increment 和 decrement。当按钮被点击时,相应的事件会被触发

<template>
  <div>
    <button @click="handleIncrement">Increment</button>
    <button @click="handleDecrement">Decrement</button>
  </div>
</template>

<script setup lang="ts">
const emit = defineEmits(['increment', 'decrement']);

const handleIncrement = () => {
  emit('increment');
};

const handleDecrement = () => {
  emit('decrement');
};
</script>

在父组件中,监听子组件触发的 increment 和 decrement 事件,并通过相应的处理函数来更新计数器

<template>
  <div>
    <p>Counter: {{ counter }}</p>
    <ChildComponent @increment="increment" @decrement="decrement" />
  </div>
</template>

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

const counter = ref(0);

const increment = () => {
  counter.value++;
};

const decrement = () => {
  counter.value--;
};
</script>

2.2 传参

子组件中,定义一个事件 updateValue,它会传递一个数值参数

<template>
  <div>
    <button @click="update(1)">Increment</button>
    <button @click="update(-1)">Decrement</button>
  </div>
</template>

<script setup lang="ts">
const emit = defineEmits<{ (e: 'updateValue', value: number): void }>();

const update = (value: number) => {
  emit('updateValue', value);
};
</script>

在父组件中,接收 updateValue 事件,并使用传递的参数更新计数器

<template>
  <div>
    <p>Counter: {{ counter }}</p>
    <ChildComponent @updateValue="updateCounter" />
  </div>
</template>

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

const counter = ref(0);

const updateCounter = (value: number) => {
  counter.value += value;
};
</script>

2.3 传对象

在对象中,键是事件名,值是一个函数,该函数的参数就是事件的参数

子组件 使用对象语法定义事件和参数类型

<template>
  <div>
    <button @click="update(1)">Increment</button>
    <button @click="update(-1)">Decrement</button>
  </div>
</template>

<script setup lang="ts">
const emit = defineEmits({
  updateValue: (value: number) => true,
});

const update = (value: number) => {
  emit('updateValue', value);
};
</script>

在父组件中,接收 updateValue 事件,并使用传递的参数更新计数器

<template>
  <div>
    <p>Counter: {{ counter }}</p>
    <ChildComponent @updateValue="updateCounter" />
  </div>
</template>

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

const counter = ref(0);

const updateCounter = (value: number) => {
  counter.value += value;
};
</script>

3. 实战

先给一个实战的例子:

整体逻辑如下:

  1. 定义和触发事件
    使用 defineEmits([‘success’]) 定义了一个 success 事件
    在表单提交成功后,通过 emit(‘success’) 触发 success 事件

  2. 表单提交逻辑
    submitForm 函数负责表单提交逻辑
    首先校验表单数据
    根据表单类型 (create 或 update) 发起相应的 API 请求
    请求成功后,弹出成功消息并关闭表单对话框
    最后触发 success 事件,通知父组件刷新列表

  3. 父组件监听事件
    父组件 EnterpriseRegistry 监听子组件 EnterpriseRegistryForm 的 success 事件
    在监听到 success 事件后,调用 getList 方法重新获取列表数据

子组件(表单组件)

// 定义和触发 success 事件
const emit = defineEmits(['success']);

const submitForm = async () => {
  await formRef.value.validate();
  formLoading.value = true;
  try {
    const data = formData.value as unknown as EnterpriseRegistryVO;
    if (formType.value === 'create') {
      await EnterpriseRegistryApi.createEnterpriseRegistry(data);
      message.success(t('common.createSuccess'));
    } else {
      await EnterpriseRegistryApi.updateEnterpriseRegistry(data);
      message.success(t('common.updateSuccess'));
    }
    dialogVisible.value = false;
    emit('success'); // 触发 success 事件
  } finally {
    formLoading.value = false;
  }
};

父组件:

<EnterpriseRegistryForm ref="formRef" @success="getList" />

对应的方法:

const getList = async () => {
  loading.value = true;
  try {
    const data = await EnterpriseRegistryApi.getEnterpriseRegistryPage(queryParams);
    list.value = data.list;
    total.value = data.total;
  } finally {
    loading.value = false;
  }
};

对应的逻辑如下:

  1. defineEmits 定义事件:在子组件中使用 defineEmits 定义事件,事件名可以是字符串数组或对象形式,用于明确事件类型和参数
  2. emit 触发事件:通过调用 emit 方法触发已定义的事件,并可携带相关参数
  3. 父组件监听事件:父组件通过 @事件名 监听子组件触发的事件,从而在事件触发时执行相应的处理逻辑
  • 28
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农研究僧

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值