vue组件含有v-model的props,当对其进行封装,想对该属性进行双向绑定时,可以采用computed的方式包一层get(){return props.xxx},set(v)=>{emit('update:xxx',v)}
,或者使用vueuse
的useModel
来深层代理,但是只适合要封装的组件prop的内部的变量数据类型一致,不一致就只能拆开写,通过watch
监听prop
更新内部变量, 然后内部变量在内部的v-model
变化时抛出事件通知父组件.
father.vue
<template>
<div>
<Child v-model:form-state="obj" @change="onChange"></Child>
</div>
</template>
<script setup>
import { ref } from "vue";
import Child from "./Child.vue";
const obj = ref({
test: "xihu"
});
const onChange = state => {
console.log("父组件监听", state);
};
</script>
<style lang="less" scoped></style>
Child.vue
<template>
<div>
<a-form :model="_formState">
<a-form-item label="tewst">
<a-cascader
v-model:value="_formState.test"
:options="options"
placeholder="Please select"
/>
</a-form-item>
</a-form>
</div>
</template>
<script setup>
import { ref, watch } from "vue";
import { cloneDeep } from "lodash-es";
const props = defineProps({
formState: {
type: Object,
default: () => ({ test: "" })
},
transform: {
type: Function
}
});
const emit = defineEmits(["change", "update:formState"]);
const _formState = ref({
test: []
});
const options = [
{
value: "zhejiang",
label: "Zhejiang",
children: [
{
value: "hangzhou",
label: "Hangzhou",
children: [
{
value: "xihu",
label: "West Lake"
}
]
}
]
},
{
value: "jiangsu",
label: "Jiangsu",
children: [
{
value: "nanjing",
label: "Nanjing",
children: [
{
value: "zhonghuamen",
label: "Zhong Hua Men"
}
]
}
]
}
];
watch(
() => props.formState,
v => {
const findPathById = (treeArr, id) => {
const path = [];
let isFind = false;
const traverse = nodes => {
if (!Array.isArray(nodes)) return;
for (const node of nodes) {
if (isFind) return;
const { value, children } = node;
path.push(value);
if (value == id) {
isFind = true;
return;
}
if (children && children.length) {
traverse(children);
}
if (!isFind) {
path.pop();
}
}
};
traverse(treeArr);
return path;
};
if (props.formState && props.formState.test) {
_formState.value.test = findPathById(options, props.formState?.test);
}
},
{
immediate: true
}
);
watch(
() => _formState.value,
newState => {
emit("change", newState);
// ? emit("update:formState",newState) 这里如果进行双向绑定,会触发上面的watch无限循环
},
{
deep: true,
immediate: true
}
);
</script>
<style lang="less" scoped></style>