拖拽树形节点到子节点时层级结构变乱怎么办?

宇文雨欣 阅读 13

在做部门管理树形结构拖拽时,遇到拖拽父节点到子节点位置,保存后的数据层级完全错乱。我用Vue3+Sortable.js实现,设置了group和animation,拖拽时视觉显示没问题,但更新数据时发现目标节点的children数组被错误挂载到顶层。尝试过用onAdd监听事件手动处理,但遇到TypeError: Cannot read properties of undefined (reading 'children')

代码大概是这样写的:


onAdd(rootEvent) {
  const { item, target } = rootEvent;
  const parent = target.parentNode; // 这里可能拿错了父节点
  this.updateTree(parent.id, item.id); // 更新父子关系时出错
}

调试发现当拖到叶子节点时,target.parentNode会变成同级元素,该怎么准确获取目标节点的父级?

我来解答 赞 5 收藏
二维码
手机扫码查看
1 条解答
峻成
峻成 Lv1
这个问题主要是因为拖拽时 target 的层级关系没处理对,Sortable.js 的事件对象里确实容易搞混。我一般会直接从数据源入手,而不是依赖 DOM 结构。代码放这了:

onAdd(rootEvent) {
const { item, to, from } = rootEvent;
const draggedId = item.dataset.id; // 拖拽节点的唯一id
const targetId = to.dataset.id; // 目标节点的唯一id

if (!draggedId || !targetId) return;

// 找到对应的树节点对象
const findNode = (tree, id) => {
for (let node of tree) {
if (node.id === id) return node;
if (node.children) {
const result = findNode(node.children, id);
if (result) return result;
}
}
return null;
};

// 先把拖拽节点移出原位置
const removeNode = (tree, id) => {
for (let i = 0; i < tree.length; i++) {
if (tree[i].id === id) {
return tree.splice(i, 1)[0];
}
if (tree[i].children) {
const removed = removeNode(tree[i].children, id);
if (removed) return removed;
}
}
return null;
};

// 添加到新位置
const draggedNode = removeNode(this.treeData, draggedId);
const targetNode = findNode(this.treeData, targetId);

if (draggedNode && targetNode) {
if (!targetNode.children) targetNode.children = [];
targetNode.children.push(draggedNode);
}

// 更新视图
this.treeData = [...this.treeData];
}


这里的关键是用数据驱动,别直接操作 DOM。先通过唯一标识找到对应的节点,然后在数据结构上重新挂载。记得给每个节点加个唯一的 id,比如 data-id 属性。这个方法能保证层级关系不出错,调试也简单。
点赞 3
2026-02-16 11:09