一,问题
在父组件和子组件中都使用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>