vue 3 第二十八章:组件十二(组件的v-model、多v-model)
文章目录
- 1. 基本使用
- 2. 使用conputed实现
- 3. v-model 的参数
- 4. 多 v-model 的使用
- 5. 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-componentv-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