文章目录
- 前言
- 简单封装Input组件
- v-mode参数
- 多个v-model绑定
前言
比如我们有自定义的Form组件、Input组件。
如果Form组件想拿到Input组件中input框输入的内容,我们可以让Form这个父组件给Input子组件传值props:value
(不能直接修改子组件的props),子组件定义变量记录prop的值,子组件监听数据变化,再用$emit('input')
传给父组件,父组件接收调用方法去修改value。
vue3可以使用组件v-model去解决上述问题,从而实现组件的双向数据绑定。v-model是$emit('input')
和props:value
的语法糖。
使用组件 v-model 的主要好处是无需记特定的 prop 字段名,即可绑定到组件中的值,降低组件的使用成本。
简单封装Input组件
Input.vue
<template><div><input type="text":value="inputRef.val"@input="updateValue"></div>
</template>
// ......
props:{modelValue: String // 默认使用 modelValue 作为prop
},
setup(props, context) {const inputRef = reactive({val: props.modelValue || '', // 不建议直接修改props中的数据error: false,message: ''})const updateValue = (e: KeyboardEvent) => {const targetValue = (e.target as HTMLInputElement).valueinputRef.val = targetValue // 拿到更新后的值context.emit('update:modelValue', targetValue) // emit传递的方法名必须是update:modelValue}
}
在组件中使用Input组件
Form.vue
<template><form><Input v-model="emailVal"/></form>
</template>
//
<script lang="ts">
import { defineComponent, reactive, ref } from 'vue'
// ....
export default defineComponent({name: 'Form.vue',components: {Input },setup () {const emailVal = ref('')return {emailVal}}
})
</script>
<Input v-model="emailVal"/>
在代码背后,模板编译器会对 v-model 进行更冗长的等价展开。因此上面的代码其实等价于下面这段:
<Input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)"/
v-mode参数
使用Input组件<Input v-model="emailVal"/>
时,input组件默认使用 modelValue 作为prop。
当然也可以自定义,<Input v-model:emailVal="emailVal"/>
,input组件中就可以使用emailVal作为prop:
props:{emailVal: String // 默认使用 modelValue 作为prop
},
多个v-model绑定
此外,也可以有多个v-model绑定,如:
<UserNamev-model:first-name="first"v-model:last-name="last"
/>
子组件编写方式:
<script setup>
defineProps({firstName: String,lastName: String
})defineEmits(['update:firstName', 'update:lastName'])
</script><template><inputtype="text":value="firstName"@input="$emit('update:firstName', $event.target.value)"/><inputtype="text":value="lastName"@input="$emit('update:lastName', $event.target.value)"/>
</template>
更多内容详见官方文档Vue官网-组件 v-model