序言
只要二次封装组件必然少不了v-model进行双向数据传递,本文只介绍常用写法,不讲八股文。只需一文,让你的v-model炉火纯青。(3.4的宏真的很方便!)
一、使用计算属性(Vue3.4之前)
1.传递单值或多值
防止有少部分人不知道,特意强调下:v-model是可以写多个的。后续不再举例多个的用法
<!--父组件-->
<template>
<ChildComponent v-model="message1" v-model:title="message2"/>
</template>
<script setup>
import { ref } from 'vue';
const message1 = ref('');
const message2 = ref('');
</script>
<!--子组件-->
<template>
<input v-model="childMsg1" v-model:title="childMsg2"/>
</template>
<script setup>
import { ref, computed } from 'vue';
const props = defineProps({
message1: String,
message2: String
});
const emit = defineEmits(['update:modelValue','update:title']);
const childMsg1 = computed({
get() {
return props.message1;
},
set(val) {
emit("update:modelValue", val);
}
});
const childMsg2 = computed({
get() {
return props.message2;
},
set(val) {
emit("update:title", val);
}
});
</script>
2.传递对象
<!--父组件-->
<template>
<ChildComponent v-model="obj"/>
</template>
<script setup>
import { ref } from 'vue';
const obj = ref({
foo: '',
bar: ''
});
</script>
<!--子组件-->
<template>
<input v-model="childFoo" />
<input v-model="childBar" />
</template>
<script setup>
import { ref, computed } from 'vue';
const props = defineProps({
obj: Object
});
const emit = defineEmits(['update:modelValue']);
const childFoo = computed({
get() {
return props.obj;
},
set(val) {
emit("update:modelValue", {
...props.obj,
val
});
}
});
const childBar = computed({
get() {
return props.obj;
},
set(val) {
emit("update:modelValue", {
...props.obj,
val
});
}
});
</script>
二、使用侦听器(Vue3.4之前)
1.传递单值或多值
<!--父组件-->
<template>
<ChildComponent v-model="message" />
</template>
<script setup>
import { ref } from 'vue';
const message = ref('');
</script>
<!--子组件-->
<template>
<input v-model="childMsg" />
</template>
<script setup>
import { ref, watch } from 'vue';
const props = defineProps({
message: String
});
const emit = defineEmits(['update:modelValue']);
const childMsg = ref(props.message);
watch(childMsg, val => {
emit("update:modelValue", val);
});
</script>
2.传递对象
<!--父组件-->
<template>
<ChildComponent v-model="obj"/>
</template>
<script setup>
import { ref } from 'vue';
const obj = ref({
foo: '',
bar: ''
});
</script>
<!--子组件-->
<template>
<input v-model="childFoo" />
<input v-model="childBar" />
</template>
<script setup>
import { ref, watch, watchEffect } from 'vue';
const props = defineProps({
obj: Object
});
const emit = defineEmits(['update:modelValue']);
const childFoo = ref(props.obj.foo);
const childBar = ref(props.obj.bar);
watchEffect(() => {
emit("update:modelValue", {
foo: childFoo.value,
bar: childBar.value
});
});
</script>
三、defineModel宏(Vue3.4之后)
从 Vue 3.4 开始,推荐的实现方式是使用 defineModel() 宏。 官网机票
1.传递单值
<!--父组件-->
<template>
<ChildComponent v-model="message" />
</template>
<script setup>
import { ref } from 'vue';
const message = ref('');
</script>
<!--子组件-->
<template>
<input v-model="childMsg" />
</template>
<script setup>
const childMsg = defineModel()
</script>
是的你没看错,子组件就是如此简单,无需props!无需emits!
2.传递多值
<!--子组件-->
<template>
<input v-model="childMsg1" />
<input v-model="childMsg2" />
</template>
<script setup>
const childMsg1 = defineModel()
const childMsg2 = defineModel('title')
</script>
3.传递对象
<!--子组件-->
<template>
<input v-model="obj.foo" />
<input v-model="obj.bar" />
</template>
<script setup>
const obj = defineModel()
</script>
总结
目前开发中还没有遇见过必须要将v-model拆成@input和:value的场景,所以父子组件都直接使用的v-model真的很方便。Vue3.4的宏更方便!建议大家升级。
如果对你有帮助,感谢点赞、收藏、关注