Vue3 自定义事件
事件名
与组件和 prop 一样,事件名提供了自动的大小写转换。如果在子组件中触发一个以 camelCase (驼峰式命名) 命名的事件,你将可以在父组件中添加一个 kebab-case (短横线分隔命名) 的监听器。
1
| <my-component @my-event="doSomething"></my-component>
|
定义自定义事件
通过 emits
选项在组件上定义发出的事件
1 2 3
| app.component('custom-form', { emits: ['inFocus', 'submit'] })
|
当在 emits
选项中定义了原生事件 (如 click
) 时,将使用组件中的事件替代原生事件侦听器。
验证抛出的事件
与 prop 类型验证类似,如果使用对象语法而不是数组语法定义发出的事件,则可以对它进行验证。
要添加验证,请为事件分配一个函数,该函数接收传递给 $emit
调用的参数,并返回一个布尔值以指示事件是否有效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| app.component('custom-form', { emits: { click: null,
submit: ({ email, password }) => { if (email && password) { return true } else { console.warn('Invalid submit event payload!') return false } } }, methods: { submitForm(email, password) { this.$emit('submit', { email, password }) } } })
|
v-model
参数
默认情况下,组件上的 v-model
使用 modelValue
作为 prop 和 update:modelValue
作为事件。我们可以通过向 v-model
传递参数来修改这些名称:
1
| <my-component v-model:title="bookTitle"></my-component>
|
子组件将需要一个 title
prop 并发出 update:title
事件来进行同步:
1 2 3 4 5 6 7 8 9 10 11 12
| app.component('my-component', { props: { title: String }, emits: ['update:title'], template: ` <input type="text" :value="title" @input="$emit('update:title', $event.target.value)"> ` })
|
多个 v-model
绑定
每个 v-model 将同步到不同的 prop,而不需要在组件中添加额外的选项
1 2 3 4
| <user-name v-model:first-name="firstName" v-model:last-name="lastName" ></user-name>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| app.component('user-name', { props: { firstName: String, lastName: String }, emits: ['update:firstName', 'update:lastName'], template: ` <input type="text" :value="firstName" @input="$emit('update:firstName', $event.target.value)">
<input type="text" :value="lastName" @input="$emit('update:lastName', $event.target.value)"> ` })
|
处理 v-model
修饰符
创建一个示例自定义修饰符 capitalize
,它将 v-model
绑定提供的字符串的第一个字母大写。
添加到组件 v-model
的修饰符将通过 modelModifiers
prop 提供给组件。在下面的示例中,我们创建了一个组件,其中包含默认为空对象的 modelModifiers
prop。
TIP
当组件的 created
生命周期钩子触发时,modelModifiers
prop 会包含 capitalize
,且其值为 true
——因为 capitalize
被设置在了写为 v-model.capitalize="myText"
的 v-model
绑定上。
1
| <my-component v-model.capitalize="myText"></my-component>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| app.component('my-component', { props: { modelValue: String, modelModifiers: { default: () => ({}) } }, emits: ['update:modelValue'], template: ` <input type="text" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)"> `, created() { console.log(this.modelModifiers) } })
|
已经设置了 prop,我们可以检查 modelModifiers
对象键并编写一个处理器来更改发出的值。在下面的代码中,每当 <input/>
元素触发 input
事件时,我们都将字符串大写。
1 2 3 4
| <div id="app"> <my-component v-model.capitalize="myText"></my-component> {{ myText }} </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| const app = Vue.createApp({ data() { return { myText: '' } } })
app.component('my-component', { props: { modelValue: String, modelModifiers: { default: () => ({}) } }, emits: ['update:modelValue'], methods: { emitValue(e) { let value = e.target.value if (this.modelModifiers.capitalize) { value = value.charAt(0).toUpperCase() + value.slice(1) } this.$emit('update:modelValue', value) } }, template: `<input type="text" :value="modelValue" @input="emitValue">` })
app.mount('#app')
|
对于带参数的 v-model
绑定,生成的 prop 名称将为 arg + "Modifiers"
1
| <my-component v-model:description.capitalize="myText"></my-component>
|
1 2 3 4 5 6 7 8 9 10 11 12
| app.component('my-component', { props: ['description', 'descriptionModifiers'], emits: ['update:description'], template: ` <input type="text" :value="description" @input="$emit('update:description', $event.target.value)"> `, created() { console.log(this.descriptionModifiers) } })
|