網(wǎng)站怎么做盈利萬網(wǎng)域名注冊查詢
文章目錄
- 一,拖拽后結(jié)點的parentCid的更新
- 二,拖拽后結(jié)點的父節(jié)點下所有結(jié)點的sort排序?qū)傩缘淖兓?/li>
- 更新排序的邏輯
- 代碼分析
- 三,拖拽后結(jié)點及其子節(jié)點catLevel的變化
- 判斷是否需要更新 `catLevel`
- 獲取拖動后的新節(jié)點
- 更新 `catLevel`
- 完整代碼
這一節(jié)的主要內(nèi)容是收集拖拽后的要更新的節(jié)點的數(shù)據(jù),邏輯比較復雜。
- 1,拖拽后結(jié)點的parentCid的更新;
- 2,拖拽后結(jié)點的父節(jié)點下所有結(jié)點的sort排序?qū)傩缘淖兓?#xff1b;
- 3,拖拽后結(jié)點及其子節(jié)點catLevel的變化;
所有這些數(shù)據(jù)都用收集到,然后發(fā)送給后臺更新。
拖拽結(jié)束后,觸發(fā)拖拽結(jié)束事件,所以要在el-tree上綁定這個事件。
事件函數(shù)nodeDrop定義如下。
然后定義一個全局數(shù)組,用來收集需要更新的節(jié)點數(shù)據(jù)。
一,拖拽后結(jié)點的parentCid的更新
var draggingNodeNewPId = 0;// 1,更新draggingNode的parentCid,根據(jù)dropPosition的不同值,分為兩種情況if (dropPosition === "before" || dropPosition === "after") {draggingNodeNewPId = dropNode.data.parentCid;} else {draggingNodeNewPId = dropNode.data.cid;}
這段代碼是在處理 el-tree
組件中拖拽結(jié)束后的邏輯,特別是更新被拖動節(jié)點的 parentCid
字段,以反映新的父節(jié)點關(guān)系。parentCid
假設(shè)是數(shù)據(jù)庫中用來標識父節(jié)點的一個字段,通常在樹形結(jié)構(gòu)的數(shù)據(jù)模型中使用。
代碼中的邏輯分為兩種情況:
-
當拖動節(jié)點放置在目標節(jié)點之前 (
prev
) 或之后 (next
):if (dropPosition === "prev" || dropPosition === "next") {draggingNode.parentCid = dropNode.data.parentCid; }
在這種情況下,拖動的節(jié)點將變?yōu)榕c目標節(jié)點同級,但它們共同的父節(jié)點會成為新的父節(jié)點。因此,
draggingNode
的parentCid
被設(shè)置為dropNode.data.parentCid
,即目標節(jié)點的父節(jié)點ID。這種寫法還兼容了沒有父節(jié)點的情況,沒有父節(jié)點時,parentCid為0。 -
當拖動節(jié)點放置在目標節(jié)點內(nèi)部 (
inner
):else if (dropPosition === "inner") {draggingNode.parentCid = dropNode.data.cid; }
如果拖動的節(jié)點被放置在目標節(jié)點內(nèi)部,那么它將成為目標節(jié)點的子節(jié)點。因此,
draggingNode
的parentCid
被設(shè)置為dropNode.data.cid
,即目標節(jié)點自身的ID。
這段代碼確保了在拖拽結(jié)束后,樹形結(jié)構(gòu)在邏輯上保持一致,parentCid
的更新反映了新的父子關(guān)系。這在維護樹形數(shù)據(jù)結(jié)構(gòu)的完整性方面非常重要,特別是在需要同步這些變化到后端數(shù)據(jù)庫的場景下。
二,拖拽后結(jié)點的父節(jié)點下所有結(jié)點的sort排序?qū)傩缘淖兓?/h2>
// 2,更新draggingNode及其子節(jié)點的sort// 2.1如果draggingNode的parentCid沒有更新,只需要重排draggingNode的兄弟結(jié)點的sort;// 2.2如果draggingNode的parentCid有更新,不僅需要重排draggingNode的原來的兄弟結(jié)點的sort,還需要重排draggingNode新的兄弟結(jié)點的sortvar siblingNodesOld = [];var siblingNodesNew = [];// draggingNode.parent為空,所以要根據(jù)parentCid找到其parent。// 寫一個根據(jù)cid從menus中查詢結(jié)點的函數(shù)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);
// 2,更新draggingNode及其子節(jié)點的sort// 2.1如果draggingNode的parentCid沒有更新,只需要重排draggingNode的兄弟結(jié)點的sort;// 2.2如果draggingNode的parentCid有更新,不僅需要重排draggingNode的原來的兄弟結(jié)點的sort,還需要重排draggingNode新的兄弟結(jié)點的sortvar siblingNodesOld = [];var siblingNodesNew = [];// draggingNode.parent為空,所以要根據(jù)parentCid找到其parent。// 寫一個根據(jù)cid從menus中查詢結(jié)點的函數(shù)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
拖拽操作后更新節(jié)點排序(sort
屬性)的邏輯,以便反映節(jié)點在樹結(jié)構(gòu)中的新位置。這里主要關(guān)注兩個方面:更新拖動節(jié)點 draggingNode
及其子節(jié)點的排序,以及根據(jù) draggingNode
的父節(jié)點是否改變來決定哪些節(jié)點的排序需要被更新。
更新排序的邏輯
-
確定舊的和新的兄弟節(jié)點集合:
siblingNodesOld
是拖動前draggingNode
的兄弟節(jié)點集合,即它原本的同級節(jié)點。siblingNodesNew
是拖動后draggingNode
的兄弟節(jié)點集合,這取決于拖動的目標位置(放置在目標節(jié)點之前、之后還是內(nèi)部)。
-
判斷是否需要更新新的兄弟節(jié)點集合:
- 如果
draggingNode
的父節(jié)點ID(parentCid
)沒有改變,意味著拖動只改變了順序而沒有改變層級,此時只需要更新舊的兄弟節(jié)點集合的排序。 - 如果
draggingNode
的父節(jié)點ID改變了,意味著節(jié)點的層級發(fā)生了變化,此時需要更新舊的和新的兄弟節(jié)點集合的排序。
- 如果
-
更新兄弟節(jié)點的排序:
- 遍歷
siblingNodesOld
和siblingNodesNew
集合,將每個節(jié)點的sort
屬性設(shè)置為其在集合中的索引。這是因為索引反映了節(jié)點在數(shù)組中的位置,可以作為排序的依據(jù)。
- 遍歷
代碼分析
-
在
siblingNodesNew
的賦值中,對于放置在目標節(jié)點之前或之后的情況,代碼似乎直接將dropNode.data.parentCid
賦值給了siblingNodesNew
,但實際上dropNode.data.parentCid
不應(yīng)直接作為節(jié)點集合,這看起來像是一個錯誤或代碼片段的不完整展示。正確的做法應(yīng)該是獲取dropNode
的父節(jié)點的子節(jié)點集合。 -
對于放置在目標節(jié)點內(nèi)部的情況,代碼正確地從
dropNode
的父節(jié)點獲取了子節(jié)點集合。
三,拖拽后結(jié)點及其子節(jié)點catLevel的變化
// 3,更新draggingNode及其子節(jié)點的catLevelvar 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及其子節(jié)點的catLevel
updateCatLevel(node) {node.catLevel = node.level;if (node.childNodes && node.childNodes.length > 0) {node.childNodes.forEach((child) => {this.updateCatLevel(child);});}
},
這段代碼的主要作用是,在 el-tree
組件的拖拽操作完成后,更新拖動節(jié)點 draggingNode
及其所有子節(jié)點的 catLevel
屬性,以反映新的層級關(guān)系。catLevel
通常用于表示節(jié)點在樹結(jié)構(gòu)中的層級深度,這對于保持樹結(jié)構(gòu)的一致性和完整性是非常重要的。
判斷是否需要更新 catLevel
首先,代碼檢查是否需要更新 catLevel
:
var catLevelNeedUpdate = true;
if (draggingNode.data.catLevel === dropNode.data.catLevel && (dropPosition === "prev" || dropPosition === "next")) {catLevelNeedUpdate = false;
}
如果拖動節(jié)點和目標節(jié)點的層級相同,并且拖動位置是目標節(jié)點的前后,那么 catLevel
不需要更新,因為拖動操作不會改變節(jié)點的層級深度。
獲取拖動后的新節(jié)點
接下來,代碼嘗試獲取拖動操作完成后的拖動節(jié)點 draggingNodeAfterDrop
,這通常是通過查找父節(jié)點的子節(jié)點列表來完成的:
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
根據(jù)拖動位置確定,然后遍歷其子節(jié)點找到具有相同 cid
的節(jié)點,即拖動后的拖動節(jié)點。
更新 catLevel
最后,如果需要更新 catLevel
,調(diào)用 updateCatLevel
方法來遞歸更新拖動節(jié)點及其所有子節(jié)點的 catLevel
:
this.updateCatLevel(draggingNodeAfterDrop, dropNode.data.catLevel + deep);
updateCatLevel
方法如下:
// 遞歸更新draggingNode及其子節(jié)點的catLevelupdateCatLevel(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
被設(shè)置為 node.level
,后者通常反映了節(jié)點的實際層級深度。如果節(jié)點有子節(jié)點,遞歸地調(diào)用 updateCatLevel
方法來更新所有子節(jié)點的 catLevel
。
完整代碼
<template><div><el-treenode-key="catId":data="menus":props="defaultProps":expand-on-click-node="false"show-checkbox:default-expanded-keys="expandedKeys":allow-drop="allowDrag"@node-drop="nodeDrop"draggable><span class="custom-tree-node" slot-scope="{ node, data }"><span>{{ node.label }}</span><span><el-buttonv-if="node.level <= 2"size="mini"@click="() => append(data)">Append</el-button><el-button size="mini" @click="() => edit(data)"> Edit </el-button><el-buttonv-if="node.childNodes.length == 0"type="text"size="mini"@click="() => remove(node, data)">Delete</el-button></span></span></el-tree><el-dialog:title="dialogTitle":visible.sync="dialogFormVisible":close-on-click-modal="false"><el-form :model="category"><el-form-item label="分類名稱"><el-input v-model="category.name" autocomplete="off"></el-input></el-form-item><el-form-item label="圖標"><el-input v-model="category.icon" autocomplete="off"></el-input></el-form-item><el-form-item label="計量單位"><el-inputv-model="category.productUnit"autocomplete="off"></el-input></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="dialogFormVisible = false">取 消</el-button><el-button type="primary" @click="submitCategory">確 定</el-button></div></el-dialog></div>
</template><script>
export default {components: {},props: {},data() {return {nodesInfoAfterDrop: [],dialogTitle: "", // 編輯窗口標題,新增分類,修改分類dialogType: "", // 編輯窗口類型,create表示append,edit表示editdialogFormVisible: false,menus: [],category: {name: "",parentCid: 0,catLevel: 0,sort: 0,showStatus: 1,icon: "",productUnit: "",catId: null,},expandedKeys: [],defaultProps: {children: "children",label: "name",},};},methods: {nodeDrop(draggingNode, dropNode, dropPosition) {console.log("draggingNode:", draggingNode, dropNode, dropPosition);var draggingNodeNewPId = 0;// 1,更新draggingNode的parentCid,根據(jù)dropPosition的不同值,分為兩種情況if (dropPosition === "before" || dropPosition === "after") {draggingNodeNewPId = dropNode.data.parentCid;} else {draggingNodeNewPId = dropNode.data.cid;}// 2,更新draggingNode及其子節(jié)點的sort// 2.1如果draggingNode的parentCid沒有更新,只需要重排draggingNode的兄弟結(jié)點的sort;// 2.2如果draggingNode的parentCid有更新,不僅需要重排draggingNode的原來的兄弟結(jié)點的sort,還需要重排draggingNode新的兄弟結(jié)點的sortvar siblingNodesOld = [];var siblingNodesNew = [];// draggingNode.parent為空,所以要根據(jù)parentCid找到其parent。// 寫一個根據(jù)cid從menus中查詢結(jié)點的函數(shù)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);// 3,更新draggingNode及其子節(jié)點的catLevelvar catLevelNeedUpdate = true;if (draggingNode.data.catLevel === dropNode.data.catLevel && (dropPosition === "before" || dropPosition === "after")) {catLevelNeedUpdate = false;}var draggingNodeAfterDrop = null;if (catLevelNeedUpdate) {var draggingParentNodeAfterDrop = {};if (dropPosition === "before" || dropPosition === "after") {draggingParentNodeAfterDrop = dropNode.parent;} else {draggingParentNodeAfterDrop = dropNode;}draggingParentNodeAfterDrop.childNodes.forEach((child) => {if (child.data.catId === draggingNode.data.catId) {draggingNodeAfterDrop = child;}})// 遞歸變量draggingNodeAfterDrop及其childNodes,將其data屬性的cateLevel置為level屬性值this.updateCatLevel(draggingNodeAfterDrop);}this.nodesInfoAfterDrop.push({catId: draggingNode.data.catId, parentCid: draggingNodeNewPId});console.log(this.nodesInfoAfterDrop);// 4,調(diào)用后端接口,將數(shù)組nodesInfoAfterDrop發(fā)送給后端this.$http({url: this.$http.adornUrl("/product/category/update/sort"),method: "post",data: this.$http.adornData(this.nodesInfoAfterDrop, false),}).then(({ data }) => {if (data && data.code === 0) {this.$message({message: "操作成功",type: "success",duration: 1500,onClose: () => {console.log("刪除成功,關(guān)閉消息提示");this.getMenus(); // 重新獲取數(shù)據(jù)this.expandedKeys = [draggingNodeNewPId]; // 重置展開節(jié)點},});} else {this.$message.error(data.msg);}});},getLevel1Nodes(node) {var tmpNode = node;while(tmpNode.parent) {tmpNode = tmpNode.parent;}return tmpNode.childNodes;},// 寫一個根據(jù)cid從menus中查詢結(jié)點的函數(shù)getNodeByCid(cid, nodes) {if (cid === 0) {return null;}// 遞歸查詢for (var i = 0; i < nodes.length; i++) {if (nodes[i].data.catId === cid) {return nodes[i];}if (nodes[i].childNodes && nodes[i].childNodes.length > 0) {var node = this.getNodeByCid(cid, nodes[i].childNodes);if (node) {return node;}}}return null;},// 遞歸更新draggingNode及其子節(jié)點的catLevelupdateCatLevel(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);});}},allowDrag(draggingNode, dropNode, dropPosition) {var deep = this.countDraggingNodeDeep(draggingNode);// 根據(jù)dropPosition結(jié)合dropNode.catLevel來判斷draggingNode新位置的位置是否合法if (dropPosition === "prev" || dropPosition === "next") {return dropNode.data.catLevel + deep - 1 <= 3;} else if (dropPosition === "inner") {return dropNode.data.catLevel + deep <= 3;}},// 遞歸計算draggingNode子樹的深度countDraggingNodeDeep(draggingNode) {var deep = 0;if (draggingNode.childNodes && draggingNode.childNodes.length > 0) {debugger;draggingNode.childNodes.forEach((child) => {deep = Math.max(deep, this.countDraggingNodeDeep(child));});}return deep + 1;},append(data) {console.log(data);this.dialogType = "create";this.dialogTitle = "新增分類";this.dialogFormVisible = true;this.category = {name: "",parentCid: data.catId,catLevel: data.level + 1,sort: 0,showStatus: 1,};},edit(data) {console.log(data);this.dialogType = "edit";this.dialogTitle = "修改分類";this.dialogFormVisible = true;// 根據(jù)catId查詢最新數(shù)據(jù)this.$http({url: this.$http.adornUrl(`/product/category/info/${data.catId}`),method: "get",data: this.$http.adornData({ catId: data.catId }, false),}).then(({ data }) => {if (data && data.code === 0) {this.category = { ...data.data };} else {this.$message.error(data.msg);}});},submitCategory() {if (this.dialogType === "create") {this.addCategory();} else if (this.dialogType === "edit") {this.updateCategory();}},updateCategory() {var { catId, name, icon, productUnit } = this.category;console.log(this.category);this.$http({url: this.$http.adornUrl("/product/category/update"),method: "post",data: this.$http.adornData({ catId, name, icon, productUnit }, false),}).then(({ data }) => {if (data && data.code === 0) {this.$message({message: "修改成功",type: "success",duration: 1500,onClose: () => {console.log("修改成功,關(guān)閉消息提示");this.dialogFormVisible = false;this.getMenus(); // 重新獲取數(shù)據(jù)this.expandedKeys = [this.category.parentCid == 0? this.category.catId: this.category.parentCid,]; // 重置展開節(jié)點console.log(this.expandedKeys);},});} else {this.$message.error(data.msg);}});},addCategory() {this.$http({url: this.$http.adornUrl("/product/category/save"),method: "post",data: this.$http.adornData(this.category, false),}).then(({ data }) => {if (data && data.code === 0) {this.$message({message: "添加成功",type: "success",duration: 1500,onClose: () => {console.log("添加成功,關(guān)閉消息提示");this.dialogFormVisible = false;this.getMenus(); // 重新獲取數(shù)據(jù)this.expandedKeys = [this.category.parentCid]; // 重置展開節(jié)點},});} else {this.$message.error(data.msg);}});},remove(node, data) {console.log(node, data);var ids = [node.data.catId];this.$confirm(`確定對[id=${ids.join(",")}]進行[${ids.length == 1 ? "刪除" : "批量刪除"}]操作?`,"提示",{confirmButtonText: "確定",cancelButtonText: "取消",type: "warning",}).then(() => {this.$http({url: this.$http.adornUrl("/product/category/delete"),method: "post",data: this.$http.adornData(ids, false),}).then(({ data }) => {if (data && data.code === 0) {this.$message({message: "操作成功",type: "success",duration: 1500,onClose: () => {console.log("刪除成功,關(guān)閉消息提示");this.getMenus(); // 重新獲取數(shù)據(jù)this.expandedKeys = [node.parent.data.catId]; // 重置展開節(jié)點},});} else {this.$message.error(data.msg);}});}).catch(() => {});},// 獲取分類數(shù)據(jù)getMenus() {this.dataListLoading = true;this.$http({url: this.$http.adornUrl("/product/category/list/tree"),method: "get",}).then(({ data }) => {console.log(data);this.dataListLoading = false;this.menus = data.data;});},},created() {this.getMenus(); // 獲取分類數(shù)據(jù)},
};
</script>
<style scoped>
</style>