[Vue3] 指令 v-model
默认 v-model
默认的 v-model 就是不写其他任何的东西,也就是在使用时是这样的格式 v-model="value"
。
子组件
要定义一个默认的 v-model(不带参数的 v-model),就必须要按照以下格式来定义。
<script setup lang="ts">
defineProps(["modelValue"]);
defineEmits(["update:modelValue"]);
</script>
<template>
<input type="text" @input="$event => $emit('update:modelValue', ($event.target as HTMLInputElement).value)" />
</template>
定义 props 的时候,默认的 v-model 是 modelValue
,v-model 本质上是一个自定义函数通知父组件更新数据,所以也需要一个 emit,而 v-model 的 emit 必须是 update:Xxxx
的格式。
父组件
<script setup lang="ts">
const state = ref("");
</script>
<template>
{{ state }}
<Test v-model="state" />
</template>
v-model
是利用 emit 向父组件传递数据,通知父组件的 state 更新。而默认的 v-model
所对应的子组件 prop 就是 modelValue,与之对应的也要有一个 update:modelValue 的 emit 自定义事件。
具名 v-model
默认的 v-model 相反的就是具名 v-model,顾名思义,就是给 v-model 取一个名字方便区分,也就是说可以定义很多个 v-model。
子组件
和默认 v-model 不同,具名 v-model 可以取任何一个合法的 JS 名称。
<script setup lang="ts">
defineProps(["disabled"]);
defineEmits(["update:disabled"]);
</script>
<template>
<input type="text" @input="$event => $emit('update:disabled', ($event.target as HTMLInputElement).value)" />
</template>
其余的定义方式和上面默认 v-model 都一样。
父组件
<script setup lang="ts">
const state = ref("");
</script>
<template>
{{ state }}
<Test v-model:disabled="state" />
</template>
修饰符
v-model
修饰符可以很方便地处理输入时的前置工作,如输入时,给一串英文的首字母进行大写转换。这个修饰符的作用就好像是一个开关,带上修饰符就是要开启某一项功能,不带上就不开启。
子组件
子组件定义了一个 capitalize 修饰符,意思就是带了这个修饰符就要进行大小写转换,否则就不进行这一项任务。
<script setup lang="ts">
const props = defineProps({
value: String,
valueModifiers: {
default: () => ({
capitalize: false
})
}
});
const emits = defineEmits(["update:value"]);
function onInputChange(e: any) {
let targetValue = e.target.value;
// 判断修饰符有没有开启
if (props.valueModifiers.capitalize) {
targetValue = targetValue.charAt(0).toUpperCase() + targetValue.slice(1);
}
emits("update:value", targetValue);
}
</script>
<template>
<input type="text" :value="value" @input="onInputChange" />
</template>
父组件
v-model
冒号后面的是 value,它是一个具名 v-model,绑定的子组件 props。所有的 .
都是前面 props 的修饰符,这个修饰符是一个布尔值,也就是两种状态,即开不开启某项功能。
<template>
<Text v-model:value.capitalize="state" />
</template>
修饰符不写就是 false,写了就是 true。实例中我写了修饰符,所以我输入小写的单词,首字母会被转换。
链式修饰符
修饰符在父组件中不止可以 .
一个,可以有多个:
<template>
<Text v-model:value.capitalize.a.b="state" />
</template>
也就是 valueModifiers 默认返回的对象中属性有很多个:
const props = defineProps({
value: String,
valueModifiers: {
default: () => ({
capitalize: false,
a: false,
b: false
})
}
});