我尝试使用 Draggable 插件制作拖放列表,但取决于我如何从负责嵌套它的组件(第二个代码块)中的观察程序中获取新值,该组件仅以一种方式工作
Codesandbox - https://codesandbox.io/s/bold-aj-jwvh93?file=/src/App.vue
主要部件清单
<script setup>
import { ref, watch, reactive, onMounted } from 'vue';
import DraggableListNesting from 'COMPONENT/cms/DraggableListNesting.vue';
const props = defineProps(
{
list:
{
type: Array,
required: true,
default: [],
},
});
const list = ref(props.list);
const emits = defineEmits(
[
'getChildrens',
'updateList',
'listUpdated',
]);
watch(() => props.list, (newList) =>
{
list.value = newList;
},
{
deep: true,
flush: 'post'
});
const childrensUpdated = (args) =>
{
for(let i = 0; i < list.value.length; i++)
{
if(list.value[i].id == args.parentElementId)
{
list.value[i].childrens = args.list;
list.value[i].childrens_count = args.list.length;
}
}
// list.value = Object.assign(args.list, list.value);
};
</script>
<template>
<div>
<DraggableListNesting
v-model="list"
:childrensUpdated="childrensUpdated"
@getChildrens="(args) => emits('getChildrens', args)"
@childrensUpdated="(args) => childrensUpdated(args)"
/>
</div>
</template>
嵌套组件 - DraggableListNesting
<script setup>
import { ref, watch } from 'vue';
import Draggable from 'vuedraggable';
import DraggableItem from 'COMPONENT/cms/DraggableItem.vue';
import DraggableListNesting from 'COMPONENT/cms/DraggableListNesting.vue';
const props = defineProps(
{
modelValue:
{
type: Array,
required: true,
default: [],
},
parentId:
{
type: [Number, Boolean],
required: false,
default: false,
},
childrensUpdated:
{
type: Function,
required: true,
},
});
const emits = defineEmits(
[
'getChildrens',
'childrensUpdated',
]);
const list = ref(props.modelValue);
const parentId = ref(props.parentId);
watch(() => props.modelValue, (newList) =>
{
console.log('list before update by watch');
console.log(list.value);
console.log(newList);
list.value = newList;
// list.value = Object.assign(newList, list.value);
},
{
deep: true,
flush: 'post'
});
</script>
<template>
<Draggable
v-model="list"
tag="ul"
:item-key="item => item.id"
:group="{name: 'edit_list_draggable_nested'}"
@end="(...args) =>
{
emits('childrensUpdated', {list: list, parentElementId: parentId, depth: nestDepth});
}"
>
<template #item="{ element }" :key="element.id">
<div>
{{ element.name }}
</div>
<li :data-draggable-item-id="element.id">
<DraggableListNesting
v-model="element.childrens"
:parentId="element.id"
:childrensUpdated="childrensUpdated"
@getChildrens="(args) => emits('getChildrens', args)"
@childrensUpdated="(args) => childrensUpdated(args)"
></DraggableListNesting>
</li>
</template>
</Draggable>
</template>
列表属性中的一些示例数据
[
{
"id": 16,
"name": "Settings",
"parent_id": null,
"order": 16,
'childrens': [
{
"id": 18,
"name": "Logs",
"parent_id": 16,
"order": 18,
childrens: [],
"childrens_count": 1
},
{
"id": 17,
"name": "Backups",
"parent_id": 16,
"order": 17,
childrens: [],
"childrens_count": 0
}
],
"childrens_count": 2
},
{
"id": 12,
"name": "Analytics",
"parent_id": null,
"order": 12,
childrens: [],
"childrens_count": 0
},
]
因此,为了测试,我将“备份”(“设置”的子项)从子项拖到主列表中
那么如果我坚持“list.value = newList”
否则,如果我尝试执行“list.value = Object.assign(newList, list.value);” (已注释掉)
成功移动后,还需要发送带有父ID的axios请求,因此列表值必须更新
当您使用 Object.assign(newList, list.value) 时,它将 newList 中的属性合并到 list.value 中,但它不会用新对象替换 list.value,这可能是 Vue 将其检测为所需的改变。
考虑在将 newList 分配给 list.value 之前创建其深层副本。这可以使用 JSON 方法 (JSON.parse(JSON.stringify(newList))) 或深层复制实用程序函数来完成。这确保您正在使用新的对象,这可以帮助 Vue 的反应系统检测更改。