在 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:modelValue
、confirm
和cancel
。- 这意味着你的子组件将会触发这三个事件之一来与父组件进行通信。
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>
子组件时,实际上是在做两件事情:
- 绑定 Prop :将父组件中的
isPopupVisible
值作为modelValue
prop 传递给子组件。 - 监听事件 :监听子组件发出的
update:modelValue
事件,并在接收到该事件时更新父组件中的isPopupVisible
值。
因此,当你在子组件中调用 emit('update:modelValue', value)
时,实际上是通知父组件更新其 isPopupVisible
的值为 value
。
具体流程
- 初始状态 :父组件中的
isPopupVisible
初始值为某个布尔值(例如false
),这个值会被传递给子组件作为modelValue
。 - 用户交互 :假设用户执行了一个操作(比如点击关闭按钮),导致子组件内部的
visible
值需要更新。 - 更新状态 :在
visible
的set
方法中,调用emit('update:modelValue', value)
,向父组件发送一个update:modelValue
事件并附带新的值。 - 父组件响应 :父组件监听到了这个事件,并更新其
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)
,子组件能够在自身状态发生改变时通知父组件,保持两者之间状态的一致性。这种方式不仅简化了组件间的通信,还提高了代码的可维护性和灵活性。