Vue组件v-model修饰符capitalize返回空的原因及解决方法
问题:Vue自定义v-model修饰符无法获取,modelModifiers返回空对象
我在Vue组件中使用带修饰符的自定义v-model:
<hello-world v-model="refInputModel" v-model:firstName.capitalize="refInputModel2"/>
运行时,HelloWorld组件的onUpdated钩子中执行console.log("modelModifiers:",props.modelModifiers);返回空对象,但期望得到{ capitalize: true }。
App组件代码
<template> <img alt="Vue logo" src="./assets/logo.png"> <div> <button @click="counterFunc">methodHandler</button> <hello-world v-model="refInputModel" v-model:firstName.capitalize="refInputModel2"/> </div> </template> <script> export default { name: 'App', components: { HelloWorld } } </script> <script setup> import HelloWorld from './components/HelloWorld.vue' import {ref,defineProps} from 'vue' const props = defineProps(['inputModel_','inputModel_2']) let refInputModel = ref(props.inputModel_) let refInputModel2 = ref(props.inputModel_2) const counterFunc = ()=> { refInputModel.value = "changed" refInputModel2.value = "changed2" } </script>
HelloWorld组件代码(原代码)
<template> <div class="hello"> <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)"/> <input :value="firstName" @input="$emit('update:firstName', $event.target.value)"/> </div> </template> <script> export default { name: 'HelloWorld', } </script> <script setup> import { onUpdated,defineProps,defineEmits} from 'vue' const props = defineProps({ modelValue:String, firstName:String, modelModifiers: { default: () => ({}) } }) defineEmits(['update:modelValue', 'update:firstName']) onUpdated(()=>{ console.log("HelloWorld.onUpdated"); console.log("modelValue:",props.modelValue); console.log("modefirstNamelValue:",props.firstName); console.log("modelModifiers:",props.modelModifiers); }) </script>
原因分析
你把修饰符加在了**带参数的v-model(v-model:firstName)**上,但组件中声明的是默认v-model对应的modelModifiers。Vue的规则是:
- 不带参数的默认v-model,修饰符对应prop为
modelModifiers - 带参数的v-model(如
v-model:xxx),修饰符对应prop为xxxModifiers
你的修饰符是给firstName这个v-model参数加的,所以对应的prop应该是firstNameModifiers,而非modelModifiers,这就是原代码中modelModifiers为空的原因。
修正方法
修改HelloWorld组件的defineProps,添加firstNameModifiers,并在钩子中打印该prop:
<script setup> import { onUpdated,defineProps,defineEmits} from 'vue' const props = defineProps({ modelValue: String, firstName: String, modelModifiers: { default: () => ({}) }, // 添加对应参数的修饰符prop firstNameModifiers: { default: () => ({}) } }) defineEmits(['update:modelValue', 'update:firstName']) onUpdated(()=>{ console.log("HelloWorld.onUpdated"); console.log("modelValue:",props.modelValue); console.log("firstName:",props.firstName); console.log("modelModifiers:",props.modelModifiers); // 打印对应参数的修饰符 console.log("firstNameModifiers:",props.firstNameModifiers); // 此时会输出 { capitalize: true } }) </script>
如果需要在组件内应用这个修饰符的逻辑,比如在触发update事件时将输入值首字母大写,可以修改input的事件处理:
<template> <div class="hello"> <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)"/> <input :value="firstName" @input="handleFirstNameInput"/> </div> </template> <script setup> import { onUpdated,defineProps,defineEmits} from 'vue' const props = defineProps({ modelValue: String, firstName: String, modelModifiers: { default: () => ({}) }, firstNameModifiers: { default: () => ({}) } }) const emit = defineEmits(['update:modelValue', 'update:firstName']) const handleFirstNameInput = (e) => { let value = e.target.value // 如果有capitalize修饰符,执行首字母大写逻辑 if (props.firstNameModifiers.capitalize) { value = value.charAt(0).toUpperCase() + value.slice(1) } emit('update:firstName', value) } onUpdated(()=>{ console.log("firstNameModifiers:",props.firstNameModifiers); }) </script>
内容的提问来源于stack exchange,提问作者Amrmsmb
相关产品推荐
相关产品推荐

