vue中分别在原生input输入框和组件输入框上运用v-model的注意点
问题的发现
在写15届蓝桥杯模拟赛一的最后一题时,竟然被第一问难住了,我用input的双向绑定进行事件触发有问题吗?
题目是这样的,如下:
-
父组件中的html代码
<form-input id="nickname" v-model="formData.nickname" :show-message="errorMessage.nickname" :holder="`nickname`"></form-input> <form-input id="email" v-model="formData.email" :show-message="errorMessage.email" :holder="`email (8-20 characters)`"></form-input>
-
form-input组件里面的代码
const FormInput = { template: ` <div> <input class="form-input" :placeholder="holder" v-model="inputValue" /> <div v-if="showMessage" class="error-message">{{ showMessage }}</div> </div> `, props: { value: String, // v-model 绑定的值,这里取名为 inputValue showMessage: String, // 是否显示消息 holder: String, // 输入框的占位符 }, setup(props, { emit }) { const inputValue = ref(props.value); const holder = ref(props.holder) // TODO:目标 1 当输入框的值变化时,触发 input 事件更新父组件的 v-model 值 watch(inputValue,(newValue,oldValue)=>{ // console.log(newValue,oldValue); //这里如果有问题的话可以去看官网怎么解释v-model在组件上的 //emit('input',newValue)//我当时想,为什么不行???????? emit('update:modelValue',newValue) }) // TODO:end return { inputValue, holder }; }, };
问题的解决
后面实在觉得这个问题太离谱了,很纳闷,就去看了一下官网文档。之前vue2的文档是没有说明输入组件上使用v-model的,我当时觉得反正v-model在vue2这里就是一个value值的绑定,一个input事件==>v-model。没想到看vue3的文档,变化居然这么大!!!学到了~
对比vue2和vue3,在原生的input输入框上进行数据的双向绑定,他们的原理还是一样的,只是vue3新添加了在输入组件上v-model这个规范约束。下面让我来慢慢陈列~
原生input上使用v-model
首先,原生是这样用的:
<input v-model="data" />
其实在vue2/3的背后,上面的这个代码等价于下面这行代码:
<input
:value="data"
@input="data = $event.target.value"
/>
其实看到这里,应该有考虑过我还能用emit事件触发吗?不会啦,它只是对于它自己本身进行操作的,只是我们今天遇到的主要问题是输入组件上绑定的v-model,我们怎么通过组件里面的代码进行事件的触发。
在一个输入组件上使用v-model
先看组件上:
<CustomInput v-model="searchText" />
在背后实际上被展开成:
<CustomInput
:model-value="searchText"
@update:model-value="newValue => searchText = newValue"
/>
看官网文档介绍的重点!!!
要让这个例子实际工作起来,<CustomInput>
组件内部需要做两件事:
- 将内部原生
<input>
元素的value
attribute 绑定到modelValue
prop - 当原生的
input
事件触发时,触发一个携带了新值的update:modelValue
自定义事
再看看官网给的例子,就知道父子组件关于数据传输的真实情况了。实际上在做这题也是这样的,我们在组件中触发父组件中的输入组件的
update:modelValue
事件,顺便将原生输入框的变化值带过去。
<!-- CustomInput.vue -->
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
总结
还是得多去看文档吧!我写的只是我个人遇到的问题,关于v-model,vue3官方文档上还写了很多,自己想对这个有更多的了解,就请跳转官网吧!vue3文档中关于v-model的解释