组件上使用v-model
一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
由于
props
是单向数据流,子组件修改props
的值是不会同步到父组件去的。如果我们想要实现子组件和父组件数据双向绑定,可以在组件上使用v-model
。
v-model
本质上是一个语法糖:
<input v-model="searchText" />
和下面这段代码是等价的:
<input
:value="searchText"
@input="searchText = $event.target.value"
/>
将v-mode
的属性绑定给input
元素的value
属性,然后去监听输入事件,当事件触发去获取传入的值,然后将值赋值给v-mode
的属性。这样就完成了双向绑定。
当作用在一个组件上时,v-model
是这样做的:
(原理一样,绑定属性然后去监听事件,当事件触发去获取事件传入的值,去赋值给绑定的属性)
<CustomInput
:modelValue="searchText"
@update:modelValue="newValue => searchText = newValue"
/>
默认情况下,v-model
在组件上都是使用 modelValue
作为 prop的属性名称,以 update:modelValue
作为对应的事件名次。
实现在组件上使用v-model
的步骤:
- 定义一个名为
modelValue
的props属性。 - 定义一个名为
update:modelValue
的自定义事件。 - 创建一个input标签,将
modelValue
绑定给input的value属性。 - 监听input标签的输入事件,当事件触发,则抛出自定义事件。
代码实现:
//hello-world组件中
//定义props
defineProps<{
modelValue: string
}>()
//定义自定义事件
const emits = defineEmits<{
(e: "update:modelValue", str: string): void
}>();
//监听input的输入事件
function input(event: Event) {
//抛出自定义事件。
emits("update:modelValue", (event.target as HTMLInputElement).value)
}
<!--绑定props和监听输入事件-->
<input :value="modelValue" @input="input($event)">
父组件:
<hello-world v-model="reactive1.name"></hello-world>
组件上绑定多个v-model
一个组件上是可以绑定多个
v-mode
l的,在前面有提到过,v-model
作用在组件上,默认绑定的属性是modelValue
,监听的事件是update:modelValue
。但其实v-model
绑定的值是可以指定的。
指定v-model
绑定的属性:
HelloWorld
组件内:
defineProps<{
personName: string
}>()
const emits = defineEmits<{
(e: "update:personName", str: string): void
}>();
function inputEvent(event: Event) {
emits("update:personName", (event.target as HTMLInputElement).value)
}
<input :value="personName" @input="inputEvent($event)">
在父组件中使用:
<hello-world v-model:person-name="person.name"></hello-world>
通过v-model:属性名称
的方式来指定绑定的属性,如果指定了属性,则监听的事件也会自动变化,监听的事件会变成update:属性名称
的形式。
能够指定v-model
绑定的属性,那么就可以实现在一个组件上绑定多个v-model
。
子组件内:
<script setup lang="ts">
defineProps<{
personName: string,
sex: string
}>()
const emits = defineEmits<{
(e: "update:personName", str: string): void
(e: "update:sex", str: string): void
}>();
function inputEvent(event: Event) {
emits("update:personName", (event.target as HTMLInputElement).value)
}
function inputEvent2(event: Event) {
emits("update:sex", (event.target as HTMLInputElement).value)
}
</script>
<template>
<input :value="personName" @input="inputEvent($event)">
<input :value="sex" @input="inputEvent2($event)">
</template>
父组件使用:
<hello-world v-model:person-name="person.name" v-model:sex="person.sex"></hello-world>