Skip to content

组件自定义事件 (component-custom-events)

事件名

事件名 可以 与 组件名 和 属性名(prop) 一样,自动进行大小写转换

js
this.$emit('yourEvent');
html
<your-component @your-event="doSth" />

DOM 模板中 建议使用 kebab-case 形式,字符串模板则没有这个限制

定义自定义事件

js
app.component('your-custom-component', {
    emits: ['sth-happen', 'click']
});

正如看到的那样,如果 emits 中定义了原生事件,则会使用组件中相应的事件侦听器

验证抛出的事件

触发事件后通过自定义代码进行校验以决定该事件是否有效,类似组件的属性(prop)校验。

js
app.component('your-custom-component', {
    emits: {
        // 无验证
        click: null,
        // 验证事件
        'sth-happen': ({ when, where, who, how }) => {
            if ([when, where, who].filter(Boolean).length < 3) {
                console.warn(`sth-happen: invalidate event`);
                return false;
            }
            return true;
        }
    },
    methods: {
        report() {
            this.$emit('sth-happen', { when: Date.now(), where: null })
        }
    }
});

v-model 参数

之前 v-model 只是 对 value|checked 等 单个特定属性 封装的语法糖,
"默认情况下,组件上的 v-model 使用 modelValue 作为 prop 和 update:modelValue 作为事件。我们可以通过向 v-model 传递参数来修改这些名称:"

html
<your-form v-model:label="xxx" />

对应的组件代码可以是:

js
app.component('your-form', {
  props: {
    label: String
  },
  emits: ['update:label'],
  template: `
    <input
      type="text"
      :value="label"
      @input="$emit('update:label', $event.target.value)">
  `
})

多个 v-model 绑定

<YourForm4Models v-model:label="x" v-model:value="y" />
title:
value:

在当前组件定义好相应组件属性数据 在子组件中只要触发相应 update:xxx 事件即可修改上级组件的属性数据

@/pages/40-lrn/20-vue3/40-component-custom-events/components/YourForm4Models.vue

vue
<template>
    <div>
        <div>
        title:
        <input :value="label" @input="emit('update:label', $event.target['value'])">
        {{label}}
        </div>
        <div>
            value:
            <input :value="value" @input="emit('update:value', $event.target['value'])">
            {{value}}
        </div>
    </div>
</template>

<script lang="ts" setup>
import { defineProps, toRefs, defineEmits } from "vue"
const props = defineProps<{
   label: string;
   value: string;
}>();
const { label, value } = toRefs(props);
let emit = defineEmits(['update:label', 'update:value']);
</script>

处理 v-model 修饰符

2.x 中的 表单输入绑定 v-model 的 .trim、.number、.lazy 等修饰符都是框架内部实现的。

3.x 中,可以自定义修饰符

下面创建一个自定义修饰符 reverse 作用是返回字符顺序相反的字符串

@/pages/40-lrn/20-vue3/40-component-custom-events/components/ReverseModifierExample.vue

vue
<template>
    <input :value="modelValue" @input="onInput" />
</template>

<script lang="ts" setup>
import { defineProps, defineEmits } from "vue"
const props = withDefaults(defineProps<{
    modelValue: string;
    modelModifiers: Record<string, boolean>;
}>(), {
    modelModifiers: () => ({}),
});
const emit = defineEmits(['update:modelValue']);
const onInput = ($event) => {
    let val = $event.target['value'];
    let result = props.modelModifiers.reverse
        ? Array.from(val).reverse().join('')
        : val;
    emit('update:modelValue', result);
};
</script>