一,问题
在父组件和子组件中都使用v-model
会打破单项数据流。
二,方法
基于上述问题采用computed
拦截v-model
<!-- 父组件 -->
<template>
<div>
<my-component v-model="form"></my-component>
</div>
</template>
<script setup>
import myComponent from "./components/MyComponent.vue";
import { ref } from "vue";
const form = ref({
name:'coderkey',
age:18,
sex:'男'
})
</script>
<!-- 子组件 -->
<template>
<div>
<el-input v-model="form.name"></el-input>
<el-input v-model="form.age"></el-input>
<el-input v-model="form.sex"></el-input>
</div>
</template>
<script setup>
import { computed } from "vue";
const props = defineProps({
modelValue: {
type: Object,
default: () => {},
},
});
// const emit = defineEmits(["update:modelValue"]);
const emit = defineEmits();
const form = computed({
get() {
return props.modelValue;
},
set(newValue) {
console.log('属性改变了')
emit("update:modelValue", newValue);
},
});
</script>
三,注意
最后发现问题:form.xxx = xxx
时,并不会触发computed
的set
,只有form = xxx
时,才会触发set
。
解决方法:用watch
监听器或者用Proxy
代理对象。
四,Proxy + computed拦截v-model的对象
<!-- 父组件 -->
<template>
<div>
<my-component v-model="form"></my-component>
</div>
</template>
<script setup>
import myComponent from "./components/MyComponent.vue";
import { ref } from "vue";
const form = ref({
name: "coderkey",
age: 18,
sex: "男",
});
</script>
<!-- 子组件 -->
<template>
<div>
<el-input v-model="form.name"></el-input>
<el-input v-model="form.age"></el-input>
<el-input v-model="form.sex"></el-input>
</div>
</template>
<script setup>
import { computed } from "vue";
const props = defineProps({
modelValue: {
type: Object,
default: () => {},
},
});
// const emit = defineEmits(["update:modelValue"]);
const emit = defineEmits();
const form = computed({
get() {
return new Proxy(props.modelValue, {
get(target, key) {
return Reflect.get(target, key);
},
set(target, key, value) {
emit("update:modelValue", {
...target,
[key]: value,
});
return true;
},
});
}
});
</script>