所有这些数据都用收集到,然后发送给后台更新。
拖拽结束后,触发拖拽结束事件,所以要在el-tree上绑定这个事件。
事件函数nodeDrop定义如下。
然后定义一个全局数组,用来收集需要更新的节点数据。
var draggingNodeNewPId = 0; // 1,更新draggingNode的parentCid,根据dropPosition的不同值,分为两种情况 if (dropPosition === "before" || dropPosition === "after") { draggingNodeNewPId = dropNode.data.parentCid; } else { draggingNodeNewPId = dropNode.data.cid; }
这段代码是在处理 el-tree
组件中拖拽结束后的逻辑,特别是更新被拖动节点的 parentCid
字段,以反映新的父节点关系。parentCid
假设是数据库中用来标识父节点的一个字段,通常在树形结构的数据模型中使用。
代码中的逻辑分为两种情况:
当拖动节点放置在目标节点之前 (prev
) 或之后 (next
):
if (dropPosition === "prev" || dropPosition === "next") { draggingNode.parentCid = dropNode.data.parentCid; }
在这种情况下,拖动的节点将变为与目标节点同级,但它们共同的父节点会成为新的父节点。因此,draggingNode
的 parentCid
被设置为 dropNode.data.parentCid
,即目标节点的父节点ID。这种写法还兼容了没有父节点的情况,没有父节点时,parentCid为0。
当拖动节点放置在目标节点内部 (inner
):
else if (dropPosition === "inner") { draggingNode.parentCid = dropNode.data.cid; }
如果拖动的节点被放置在目标节点内部,那么它将成为目标节点的子节点。因此,draggingNode
的 parentCid
被设置为 dropNode.data.cid
,即目标节点自身的ID。
这段代码确保了在拖拽结束后,树形结构在逻辑上保持一致,parentCid
的更新反映了新的父子关系。这在维护树形数据结构的完整性方面非常重要,特别是在需要同步这些变化到后端数据库的场景下。
// 2,更新draggingNode及其子节点的sort // 2.1如果draggingNode的parentCid没有更新,只需要重排draggingNode的兄弟结点的sort; // 2.2如果draggingNode的parentCid有更新,不仅需要重排draggingNode的原来的兄弟结点的sort,还需要重排draggingNode新的兄弟结点的sort var siblingNodesOld = []; var siblingNodesNew = []; // draggingNode.parent为空,所以要根据parentCid找到其parent。 // 写一个根据cid从menus中查询结点的函数 let draggingNodeOldParentNode = this.getNodeByCid(draggingNode.data.parentCid, this.getLevel1Nodes(dropNode)); console.log("draggingNodeOldParentNode:", draggingNodeOldParentNode); siblingNodesOld = draggingNodeOldParentNode.childNodes;; console.log("siblingNodesOld:", siblingNodesOld); if (draggingNode.data.parentCid !== draggingNodeNewPId) { if (dropPosition === "before" || dropPosition === "after") { siblingNodesNew = dropNode.parent.childNodes; } else { siblingNodesNew = dropNode.childNodes; } } for (var i = 0; i < siblingNodesOld.length; i++) { this.nodesInfoAfterDrop.push({catId: siblingNodesOld[i].data.catId, sort: i}); } console.log("update sortu0....", siblingNodesNew, siblingNodesOld, dropNode, dropPosition); for (var i = 0; i < siblingNodesNew.length; i++) { this.nodesInfoAfterDrop.push({catId: siblingNodesNew[i].data.catId, sort: i}); } console.log("update sort....", siblingNodesNew, siblingNodesOld, dropNode, dropPosition);
这段代码涉及到了在 el-tree
拖拽操作后更新节点排序(sort
属性)的逻辑,以便反映节点在树结构中的新位置。这里主要关注两个方面:更新拖动节点 draggingNode
及其子节点的排序,以及根据 draggingNode
的父节点是否改变来决定哪些节点的排序需要被更新。
确定旧的和新的兄弟节点集合:
siblingNodesOld
是拖动前 draggingNode
的兄弟节点集合,即它原本的同级节点。siblingNodesNew
是拖动后 draggingNode
的兄弟节点集合,这取决于拖动的目标位置(放置在目标节点之前、之后还是内部)。判断是否需要更新新的兄弟节点集合:
draggingNode
的父节点ID(parentCid
)没有改变,意味着拖动只改变了顺序而没有改变层级,此时只需要更新旧的兄弟节点集合的排序。draggingNode
的父节点ID改变了,意味着节点的层级发生了变化,此时需要更新旧的和新的兄弟节点集合的排序。更新兄弟节点的排序:
siblingNodesOld
和 siblingNodesNew
集合,将每个节点的 sort
属性设置为其在集合中的索引。这是因为索引反映了节点在数组中的位置,可以作为排序的依据。在 siblingNodesNew
的赋值中,对于放置在目标节点之前或之后的情况,代码似乎直接将 dropNode.data.parentCid
赋值给了 siblingNodesNew
,但实际上 dropNode.data.parentCid
不应直接作为节点集合,这看起来像是一个错误或代码片段的不完整展示。正确的做法应该是获取 dropNode
的父节点的子节点集合。
对于放置在目标节点内部的情况,代码正确地从 dropNode
的父节点获取了子节点集合。
// 3,更新draggingNode及其子节点的catLevel var catLevelNeedUpdate = true; if (draggingNode.data.catLevel === dropNode.data.catLevel && (dropPosition === "before" || dropPosition === "after")) { catLevelNeedUpdate = false; } var draggingNodeAfterDrop = {}; if (catLevelNeedUpdate) { var draggingParentNodeAfterDrop = {}; if (dropPosition === "before" || dropPosition === "after") { draggingParentNodeAfterDrop = dropNode.parent; } else { draggingParentNodeAfterDrop = dropNode; } draggingParentNodeAfterDrop.childNodes.forEach((child) => { if (child.cid === draggingNode.data.cid) { draggingNodeAfterDrop = child; } }) // 递归变量draggingNodeAfterDrop及其childNodes,将其data属性的cateLevel置为level属性值 this.updateCatLevel(draggingNodeAfterDrop); }
updateCatLevel的定义如下:
// 递归更新draggingNode及其子节点的catLevel updateCatLevel(node) { node.catLevel = node.level; if (node.childNodes && node.childNodes.length > 0) { node.childNodes.forEach((child) => { this.updateCatLevel(child); }); } },
这段代码的主要作用是,在 el-tree
组件的拖拽操作完成后,更新拖动节点 draggingNode
及其所有子节点的 catLevel
属性,以反映新的层级关系。catLevel
通常用于表示节点在树结构中的层级深度,这对于保持树结构的一致性和完整性是非常重要的。
catLevel
首先,代码检查是否需要更新 catLevel
:
var catLevelNeedUpdate = true; if (draggingNode.data.catLevel === dropNode.data.catLevel && (dropPosition === "prev" || dropPosition === "next")) { catLevelNeedUpdate = false; }
如果拖动节点和目标节点的层级相同,并且拖动位置是目标节点的前后,那么 catLevel
不需要更新,因为拖动操作不会改变节点的层级深度。
接下来,代码尝试获取拖动操作完成后的拖动节点 draggingNodeAfterDrop
,这通常是通过查找父节点的子节点列表来完成的:
var draggingNodeAfterDrop = {}; if (catLevelNeedUpdate) { var draggingParentNodeAfterDrop = {}; if (dropPosition === "prev" || dropPosition === "next") { draggingParentNodeAfterDrop = dropNode.parent; } else { draggingParentNodeAfterDrop = dropNode; } draggingParentNodeAfterDrop.childNodes.forEach((child) => { if (child.cid === draggingNode.data.cid) { draggingNodeAfterDrop = child; } }) }
这里,draggingParentNodeAfterDrop
根据拖动位置确定,然后遍历其子节点找到具有相同 cid
的节点,即拖动后的拖动节点。
catLevel
最后,如果需要更新 catLevel
,调用 updateCatLevel
方法来递归更新拖动节点及其所有子节点的 catLevel
:
this.updateCatLevel(draggingNodeAfterDrop, dropNode.data.catLevel + deep);
updateCatLevel
方法如下:
// 递归更新draggingNode及其子节点的catLevel updateCatLevel(node) { if (!node) { return; } this.nodesInfoAfterDrop.push({catId: node.data.catId, catLevel: node.level}); if (node.childNodes && node.childNodes.length > 0) { node.childNodes.forEach((child) => { this.updateCatLevel(child); }); } },
在这个方法中,node.catLevel
被设置为 node.level
,后者通常反映了节点的实际层级深度。如果节点有子节点,递归地调用 updateCatLevel
方法来更新所有子节点的 catLevel
。
{{ node.label }} append(data)" > Append edit(data)"> Edit remove(node, data)" > Delete 取 消 确 定