**staging-cn.vuejs.org/guide/compo…
触发与监听事件
在组件的模板表达式中,可以直接使用 $emit 方法触发自定义事件,父组件可以通过 v-on (缩写为 @) 来监听事件.
//子组件,传参
<button @click="$emit('someEvent',1)">click me</button>
//父组件,接收参数
<MyComponent @some-event="callback" />
function callback(n){
console.log(n)
}
声明触发的事件
组件要触发的事件可以显式地通过defineEmits() 宏来声明:
在<template>中使用 <template>中使用的 $emit 方法不能在组件的 <script setup> 部分中使用,但 defineEmits() 会返回一个相同作用的函数供我们使用.
<script setup>:
<script setup>
const emit = defineEmits(['inFocus', 'submit'])
function buttonClick() {
emit('submit')
}
</script>
该 defineEmits() 宏不能在子函数中使用,他必须直接放置在 <script setup> 中。
setup函数:
显式地使用了 setup 函数而不是 <script setup>,则事件需要通过 emits 选项来定义,emit 函数也被暴露在 setup() 的上下文对象上:
export default {
emits: ['inFocus', 'submit'],
setup(props, ctx) {//或者可以直接在参数中将emit解构出来
function buttonClick() {
ctx.emit('submit')
}
}
}
事件校验
和对 prop 添加类型校验的方式类似,所有触发的事件也可以使用对象形式来描述。
要为事件添加校验,那么事件可以被赋值为一个函数,接受的参数就是抛出事件时传入 emit 的内容,返回一个布尔值来表明事件是否合法。
<script setup>
const emit = defineEmits({
// 没有校验
click: null,
// 校验 submit 事件
submit: ({ email, password }) => {
if (email && password) {
return true
} else {
console.warn('Invalid submit event payload!')
return false
}
}
})
function submitForm(email, password) {
emit('submit', { email, password })
}
</script>
配合 v-model 使用
自定义事件可以用来创建对应 v-model 的自定义输入。
<input v-model="searchText" />
//等同于
<input
:value="searchText"
@input="searchText = $event.target.value"
/>
当使用在一个组件上时。
<CustomInput
:modelValue="searchText"
@update:modelValue="newValue => searchText = newValue"
/>
为了使组件能像这样工作,内部的 <input> 组件必须:
- 绑定
valueattribute 到modelValueprop - 输入新的值时在
input元素上触发update:modelValue事件
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
另一种在组件内实现 v-model 的方式是使用一个可写的 computed property,给出 getter 和 setter。get 方法需返回 modelValue property 而 set 方法需触发相应的事件:
<script setup>
import { computed } from 'vue'
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
const value = computed({
get() {
return props.modelValue
},
set(value) {
emit('update:modelValue', value)
}
})
</script>
<template>
<input v-model="value" />
</template>
v-model 的参数
默认情况下,v-model 在组件上都是使用 modelValue 作为 prop,以 update:modelValue 作为对应的事件。我们可以通过给 v-model 指定一个参数来更改这些名字:
<MyComponent v-model:title="bookTitle" />
<script setup>
defineProps(['title'])
defineEmits(['update:title'])
</script>
<template>
<input
type="text"
:value="title"
@input="$emit('update:title', $event.target.value)"
/>
</template>