实战篇 vue3 中的 emit 详细解答

在 Vue 3 中,emit 是一个用于触发自定义事件的方法,允许子组件向父组件发送消息或数据。通过 defineEmits 定义的事件列表,子组件可以明确地声明它会发出哪些事件。这不仅有助于代码的清晰性,也为工具支持(如类型推断)提供了基础。

emit 的使用

你提供的代码片段中,emit 被用来通知父组件 modelValue 的值发生了变化。具体来说:

javascript 复制代码
javascript
深色版本
const emit = defineEmits(['update:modelValue', 'confirm', 'cancel']);

// 控制弹框显示状态
const visible = computed({
  get() {
    return props.modelValue;
  },
  set(value) {
    emit('update:modelValue', value);
  },
});

这里有两个主要部分:定义事件和使用 emit 发送事件。

1. 定义事件

ini 复制代码
javascript
深色版本
const emit = defineEmits(['update:modelValue', 'confirm', 'cancel']);
  • defineEmits 是一个编译时宏,它接受一个包含事件名称的数组作为参数。在这里,你声明了三个事件:update:modelValueconfirmcancel
  • 这意味着你的子组件将会触发这三个事件之一来与父组件进行通信。

2. 使用 emit 发送事件

javascript 复制代码
javascript
深色版本
const visible = computed({
  get() {
    return props.modelValue;
  },
  set(value) {
    emit('update:modelValue', value);
  },
});
  • visible 是一个计算属性,它有一个 get 方法和一个 set 方法。
  • get 方法返回 props.modelValue 的当前值。这意味着每当父组件中的 v-model 值发生变化时,visible 也会随之更新。
  • set 方法则在 visible 的值发生变化时被调用,并且通过 emit('update:modelValue', value) 向父组件发送一个名为 update:modelValue 的事件,同时传递新的值 value

内在原理

当父组件使用 v-model="isPopupVisible" 绑定到 <MyPopup> 子组件时,实际上是在做两件事情:

  1. 绑定 Prop :将父组件中的 isPopupVisible 值作为 modelValue prop 传递给子组件。
  2. 监听事件 :监听子组件发出的 update:modelValue 事件,并在接收到该事件时更新父组件中的 isPopupVisible 值。

因此,当你在子组件中调用 emit('update:modelValue', value) 时,实际上是通知父组件更新其 isPopupVisible 的值为 value

具体流程

  1. 初始状态 :父组件中的 isPopupVisible 初始值为某个布尔值(例如 false),这个值会被传递给子组件作为 modelValue
  2. 用户交互 :假设用户执行了一个操作(比如点击关闭按钮),导致子组件内部的 visible 值需要更新。
  3. 更新状态 :在 visibleset 方法中,调用 emit('update:modelValue', value),向父组件发送一个 update:modelValue 事件并附带新的值。
  4. 父组件响应 :父组件监听到了这个事件,并更新其 isPopupVisible 的值为新值。由于 v-model 的双向绑定机制,这一变化会自动反映在父组件的状态中。

示例

假设父组件如下:

ini 复制代码
vue
深色版本
<template>
  <div>
    <button @click="togglePopup">打开弹窗</button>
    <MyPopup 
      v-model="isPopupVisible" 
      title="远程设置"
      :options="optionsList"
      :maxHeight="400"
      @confirm="handleConfirm"
      @cancel="handleCancel"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue';
import MyPopup from './path/to/MyPopup.vue'; // 替换为实际路径

const isPopupVisible = ref(false);
const optionsList = [
  { label: '选项一', selected: false },
  { label: '选项二', selected: true },
];

const togglePopup = () => {
  isPopupVisible.value = !isPopupVisible.value;
};

const handleConfirm = (selectedOption) => {
  console.log('确认选择:', selectedOption);
  isPopupVisible.value = false; // 关闭弹窗
};

const handleCancel = () => {
  console.log('取消选择');
  isPopupVisible.value = false; // 关闭弹窗
};
</script>

在这个例子中:

  • 当用户点击"打开弹窗"按钮时,isPopupVisible 被设置为 true,这会通过 v-model 传递给子组件,使得 visible 也变为 true,从而显示弹出层。
  • 当用户在子组件中关闭弹出层时,子组件会调用 emit('update:modelValue', false),这会导致父组件中的 isPopupVisible 被更新为 false,从而隐藏弹出层。

总结

emit 在这里起到了关键作用,它使得子组件能够与父组件进行有效的通信。通过 emit('update:modelValue', value),子组件能够在自身状态发生改变时通知父组件,保持两者之间状态的一致性。这种方式不仅简化了组件间的通信,还提高了代码的可维护性和灵活性。

相关推荐
Sheldon一蓑烟雨任平生7 小时前
Vue3 依赖注入(provide 和 inject)
vue.js·inject·provide·vue3 依赖注入·跨级别组件通信
paopaokaka_luck9 小时前
基于SpringBoot+Vue的助农扶贫平台(AI问答、WebSocket实时聊天、快递物流API、协同过滤算法、Echarts图形化分析、分享链接到微博)
java·vue.js·spring boot·后端·websocket·spring
Sheldon一蓑烟雨任平生10 小时前
Vue3 重构待办事项(主要练习组件化)
vue.js·重构·vue3·组件化练习
zuo-yiran14 小时前
vue div标签可输入状态下实现数据双向绑定
前端·javascript·vue.js
qq_3168377514 小时前
使用leader-line-vue 时垂直元素间距过小连线打转的解决
前端·javascript·vue.js
abiao198114 小时前
VUE的“单向数据绑定” 和 “双向数据绑定”
前端·javascript·vue.js
麦麦大数据15 小时前
F042 A星算法课程推荐(A*算法) | 课程知识图谱|课程推荐vue+flask+neo4j B/S架构前后端分离|课程知识图谱构造
vue.js·算法·知识图谱·neo4j·a星算法·路径推荐·课程推荐
拉不动的猪15 小时前
多窗口数据实时同步常规方案举例
前端·javascript·vue.js
南清的coding日记15 小时前
Java 程序员的 Vue 指南 - Vue 万字速览(01)
java·开发语言·前端·javascript·vue.js·css3·html5
Xiaouuuuua15 小时前
2026年计算机毕业设计项目合集
前端·vue.js·课程设计