通过自定义事件可以实现组件之间的通信,(如父子组件和兄弟组件之间的通信)
可以触发父组件的某些动作或方法(如表单提交,数据加载等)
自定义事件有带参数的自定义事件和不带参数的自定义事件
1.不带参数的自定义事件触发就是可以起事件通知的作用,如果父组件监听了这个事件,就可以执行相对应的处理逻辑
2.带参数的自定义事件触发后,参数会传递给监听该事件的父组件中的事件处理函数
3.如果父组件未监听该事件,就算你调用带参数的自定义事件,也不会发生什么,事件和其参数将被“忽略”,不会有任何反应或副作用
注意:
-
v-model
绑定:v-model
在自定义组件上创建了一个双向数据绑定。- 它通常绑定子组件的
modelValueziding
prop 和update:modelValue
事件。 - 当子组件触发
update:modelValue
事件时,事件的参数会自动更新父组件中与v-model
绑定的属性。
如下,子组件可以通过自定义事件向父组件传递数据,
并且这个自定义事件不带参数,但是触发该事件的时候给他传递了一个参数,参数就是传递给了监听该事件的父组件的处理函数
父组件调用自定义事件 @send-toy,自定义事件触发后就会调用父组件的save-toy中的方法
<template>
<div class="father">
<h3>父组件</h3>
<h4 v-show="toy">子给的玩具:{{ toy }}</h4>
<!-- 给子组件Child绑定事件 -->
<Child @send-toy="saveToy"/>
</div>
</template>
<script setup lang="ts" name="Father">
import Child from './Child.vue'
import { ref } from "vue";
// 数据
let toy = ref('')
// 用于保存传递过来的玩具
function saveToy(value:string){
console.log('saveToy',value)
toy.value = value
}
</script>
子组件中定义自定义事件和选择如何触发自定义事件
子组件中通过 defineEmits 定义了一个名为 send-toy的没有参数的自定义事件
点击测试按钮就会 触发 send-toy事件,并且将子组件中的toy 数据传送给了父组件事件触发时的方法做参数,在这样父组件就可以获取子组件中的参数数据
<template>
<div class="child">
<h3>子组件</h3>
<h4>玩具:{{ toy }}</h4>
<button @click="emit('send-toy',toy)">测试</button>
</div>
</template>
<script setup lang="ts" name="Child">
import { ref } from "vue";
// 数据
let toy = ref('奥特曼')
// 声明事件
const emit = defineEmits(['send-toy'])
</script>
特例:组件上 v--model双向绑定的自定义事件,v-model 通常自己绑定了input表单的modelValueziding
prop 和 update:modelValue
事件
子组件:
<!-- 子组件 -->
<template>
<input :value="modelValue" @input="updateModel" />
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps({
modelValue: String
});
const emits = defineEmits(['update:modelValue']);
const updateModel = (event) => {
emits('update:modelValue', event.target.value);
};
</script>
父组件:searchTerm
是父组件中的响应式数据属性,它通过 v-model
与子组件 CustomInput
中的 input
元素绑定,当输入文本内容时,input
元素的值会更新,并且通过 v-model
的机制,父组件中的 searchTerm
也会相应地更新。
<!-- 父组件 -->
<template>
<CustomInput v-model="searchTerm" />
</template>
<script setup>
import { ref } from 'vue';
import CustomInput from './CustomInput.vue';
const searchTerm = ref('');
</script>
最后再讲述一下遇到的自定义事件 的两种不同格式、
简单,通俗版
<script setup>
import { defineEmits } from 'vue';
const emit = defineEmits([
'update:modelValue',
{ name: 'change', props: ['value'] }
]);
const onChange = (value) => {
emit('change', value);
};
</script>
接口版定义自定义事件
如果不加 void
返回类型,接口的定义依然有效,但失去了类型安全的保证。以下是不指定返回类型的情况:
注意:如果自定义事件的函数型不为 void 的话在,
Vue中,自定义事件总是通过 emit
来触发,并且事件处理函数的返回值不会被 emit
捕获或以任何方式使用。即使事件处理函数有返回值,这个返回值也不会传递给触发事件的组件或其他监听同一事件的组件。
通过返回值可以执行一些比如异步操作的功能,回调函数等等
<script setup lang="ts">
import { defineEmits } from 'vue';
interface IEmits {
(e: 'search', v?: string | number): void
(e: 'cancel'): void
(e: 'clear'): void
(e: 'update: modelValue', v?: string | number): void
(e:'inputClick'): void
}
const emits = defineEmits<IEmits>();
const onSearch = (query?: string | number) => {
emits('search', query);
};
const onCancel = () => {
emits('cancel');
};
</script>