您现在的位置是:首页 >其他 >vue 3 第二十八章:组件十二(组件的v-model、多v-model)网站首页其他
vue 3 第二十八章:组件十二(组件的v-model、多v-model)
在 Vue 3 中,
v-model
指令的使用更加灵活,可以绑定任意属性和事件。例如,我们可以使用
v-model:checked
指令来绑定单选框或复选框的
checked
属性,使用
v-model:my-prop
来绑定自定义组件的
my-prop
属性。
1. 基本使用
同时,Vue3 中的组合式 API 也为自定义组件的 v-model
提供了更好的支持。我们可以使用 modelValue
和 update:modelValue
两个参数来定义组件的 v-model
,例如:
// MyComponent.vue
<template>
<div>
<input :value="props.modelValue" @input="updateValue" />
<span>子组件:{{ props.modelValue }}</span>
</div>
</template>
<script setup lang="ts">
const props = defineProps({
modelValue: String,
});
let emit = defineEmits(["update:modelValue"]);
const updateValue = (event: any) => {
emit("update:modelValue", event.target.value);
};
</script>
在上面的例子中,我们使用 modelValue
属性来接收父组件传递的值,并在输入框的 input
事件中使用 update:modelValue
事件来更新父组件的值。在父组件中,我们可以使用 v-model
指令来绑定这个自定义组件:
// parent.vue
<template>
<div>
<my-component v-model="data"></my-component>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import MyComponent from "./components/MyComponent.vue";
const data = ref("hello word");
</script>
需要注意的是,使用 v-model
指令绑定自定义组件时,组件需要定义 modelValue
和 update:modelValue
两个属性。另外,v-model
指令在绑定自定义组件时,会自动将组件的 modelValue
属性作为 value
属性绑定,因此,在自定义组件的模板中,需要使用 value
属性来绑定输入框的值。
2. 使用conputed实现
另一种在组件内实现v-model
的方式是使用一个可写的,同时具有getter
和setter
的computed
属性。get 方法需返回 modelValue prop
,而 set 方法需触发相应的事件:
// MyComponent.vue
<template>
<div>
<input v-model="value" />
<span>子组件:{{ props.modelValue }}</span>
</div>
</template>
<script setup lang="ts">
import { computed } from "vue";
const props = defineProps({ modelValue: String });
let emit = defineEmits(["update:modelValue"]);
const value = computed({
get() {
return props.modelValue;
},
set(value) {
emit("update:modelValue", value);
},
});
</script>
3. v-model 的参数
默认情况下,v-model
在组件上都是使用modelValue
作为 prop,并以update:modelValue
作为对应的事件。我们可以通过给v-model
指定一个参数来更改这些名字:
// parent.vue
<template>
<div>
<my-component v-model:test="data"></my-component>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import MyComponent from "./components/MyComponent.vue";
const data = ref("hello word");
</script>
子组件接收 test(就是之前的modelValue) 值,通过update:test更新父组件传递的数据:
// MyComponent.vue
<template>
<div>
<input :value="props.test" @input="updateValue" />
<span>子组件:{{ props.test }}</span>
</div>
</template>
<script setup lang="ts">
const props = defineProps({ test: String });
let emit = defineEmits(["update:test"]);
// 3.使用自定义参数
const updateValue = (event: any) => {
emit("update:test", event.target.value);
};
</script>
4. 多 v-model 的使用
通过v-model
可以传递参数的特性,我们可同时使用多个 v-model
,示例如下:
// parent.vue
<template>
<div>
<my-component v-model:hello="hello" v-model:word="word"></my-component>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import MyComponent from "./components/MyComponent.vue";
const hello = ref("hello");
const word = ref("word");
</script>
父组件使用多个 v-model,子组件可以接收多个参数并修改
// MyComponent.vue
<template>
<div>
<input :value="props.hello" @input="updateHello" />
<span>子组件:{{ props.hello }}</span>
<br />
<input :value="props.word" @input="updateWord" />
<span>子组件:{{ props.word }}</span>
</div>
</template>
<script setup lang="ts">
const props = defineProps({ hello: String, word: String });
let emit = defineEmits(["update:hello", "update:word"]);
// 4.使用多v-model
const updateHello = (event: any) => {
emit("update:hello", event.target.value);
};
const updateWord = (event: any) => {
emit("update:word", event.target.value);
};
</script>
5. v-model 修饰符
vue 官方提供了一些修饰符(如trim、number等等),但有时候我们可能需要一些特殊的功能,那么就可以使用自定义的修饰符来解决问题,如下:
<my-component v-model.mySplit="data"></my-component>
父组件传递的修饰符,可以在子组件中通过modelModifiers
访问到:
// MyComponent.vue
<template>
<div>
<input :value="props.modelValue" @input="updateModelValue" />
<span>子组件:{{ props.modelValue }}</span>
</div>
</template>
<script setup lang="ts">
const props = defineProps({
modelValue: String,
modelModifiers: { default: () => {} },
});
// console.log(props.modelModifiers); // {mySplit: true}
let emit = defineEmits(["update:modelValue"]);
// 5.使用v-model修饰符
const updateModelValue = (event: any) => {
emit("update:modelValue", event.target.value);
};
</script>
在子组件中通过modelModifiers
访问到传递的修饰符,那么我们就可以在用户每次输入时将输入内容变成数组:
// parent.vue
<template>
<div>
<my-component
v-model.mySplit="data"
v-model:title.mySplit="title"
></my-component>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import MyComponent from "./components/MyComponent.vue";
const data = ref<string>("");
const title = ref<string>("");
</script>
// MyComponent.vue
<template>
<div>
<input type="text" :value="props.modelValue" @input="updateModelValue" />
<span>子组件:{{ props.modelValue }}</span>
<hr />
<input type="text" :value="props.title" @input="updateTitle" />
<span>子组件:{{ props.title }}</span>
</div>
</template>
<script setup lang="ts">
type Props = {
modelValue?: string;
modelModifiers?: { mySplit: boolean };
title?: string;
titleModifiers?: { mySplit: boolean };
};
const props = defineProps<Props>();
let emit = defineEmits(["update:modelValue", "update:title"]);
// 5.使用v-model修饰符
const updateModelValue = (event: any) => {
let value = event.target.value;
console.log(value, "value");
if (props.modelModifiers?.mySplit) {
value = value.split("");
}
emit("update:modelValue", value);
};
const updateTitle = (event: any) => {
let value = event.target.value;
if (props.titleModifiers?.mySplit) {
value = value.split("");
}
emit("update:title", value);
};
</script>
注意:未给v-model传递参数,默认使用 modelModifiers
, 如果传递了参数,那就用 参数 +Modifiers