HTML表单元素v-model双向绑定
<custom-input v-model="searchText"/>
当在一个自定义组件上使用v-model时,v-model 会被展开为如下的形式
将父组件实例上的searchText绑定给自定义组件的modelValue属性
在父组件中,监听自定义组件的update:modelValue事件,当自定义组件使用$emit触发update:modelValue事件时(并携带了事件参数),对应的监听函数将执行,并且将事件参数的值更新给父组件实例上的searchText,由于修改了响应式数据,从而引发重新渲染。
<CustomInput
:modelValue="searchText"
@update:modelValue="newValue => searchText = newValue"
/>
子组件
<template>
<input type="text" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)">
{{ modelValue }}
</template>
<script>
export default {
name: 'CustomInput',
data() {
return {
}
},
props: ['modelValue']
}
</script>
<style lang="scss"></style>
使用computed属性实现v-model双向绑定
另一种在组件内实现 v-model 的方式是使用一个可写的,同时具有 getter 和 setter 的 computed 属性。
get 方法需返回 modelValue prop,而 set 方法需触发相应的事件
过程分析:
1. 父组件通过v-model指令, 将值通过props的方式传递给了子组件定义的modelValue
2. 子组件中使用计算属性value, 读此属性返回modelValue, 修改此属性将触发 update:modelValue事件
3. 当子组件初始化时, 模板被渲染, 拿到父组件传过来的modelValue,
模板中用到计算属性value的地方,计算属性value的get将被触发,于是返回modeValue的值
4. 当修改子组件input框中的内容时, 将会把修改后的内容赋值给计算属性value,
计算属性value的set将会触发,将会把修改后的内容交给父组件的update:modelValue事件处理函数,
从而子组件又开始更新渲染模板,于是跟第三步是一样的
父组件
<custom-input2 v-model="value1"/>
子组件
<!-- <input v-model="value" /> -->
<!-- 以上等价于下方 -->
<input :value="value" @input="value = $event.target.value"/>
const props = defineProps({
modelValue: {
type: String,
},
});
const emit = defineEmits(['update:modelValue']);
const value = computed({
get() {
return props.modelValue
},
set(value) {
emit('update:modelValue', value)
}
})
多个v-model
可以在单个组件实例上,创建多个v-model双向绑定,组件上的每一个 v-model 都会同步不同的 prop,(v-model的prop 名称将默认为modelValue)
<UserName
v-model:first-name="first"
v-model:last-name="last"
/>
<!-- UserName组件 -->
<script>
export default {
props: {
firstName: String,
lastName: String
},
emits: ['update:firstName', 'update:lastName']
}
</script>
<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)"
/>
</template>
vue3.4更新了defineModel
目前没用过。
似乎会自动创建一个双向绑定的props。