vue使用Element的Tree樹形控件實(shí)現(xiàn)拖動(dòng)改變節(jié)點(diǎn)順序方式
項(xiàng)目完成后,產(chǎn)品又提新需求,
通過拖動(dòng)能夠改變下面的組織順序,又給我增加了好大的工作量!
先吐槽產(chǎn)品一波,怎么早先不想好呢!

首先要想實(shí)現(xiàn)拖動(dòng)改變順序,那我從后端查詢得來(lái)的數(shù)據(jù)
treeList
首先就必須有順序,
后端為了實(shí)現(xiàn)節(jié)點(diǎn)有順序—在實(shí)體類中又增加了一個(gè)字段
原先類實(shí)體
public class OrgNode {
private String id;
private String name;
private String parentId;
}
增加了一個(gè)brotherId
當(dāng)前類實(shí)體
public class OrgNode {
private String id;
private String name;
private String parentId;
private String brotherId;
}后端
1.新增節(jié)點(diǎn)
每當(dāng)我新增一個(gè)節(jié)點(diǎn)時(shí),就把他的brotherId設(shè)為 “-1”,
如果新增節(jié)點(diǎn)所在的層級(jí)之前沒有節(jié)點(diǎn),那不需要處理;
如果新增節(jié)點(diǎn)所在的層級(jí)之前有節(jié)點(diǎn),那么把之前brotherId為-1的節(jié)點(diǎn)的brotherId改為新增節(jié)點(diǎn)的id
2.刪除節(jié)點(diǎn)
當(dāng)刪除節(jié)點(diǎn)時(shí),為保證順序,需要把 被刪節(jié)點(diǎn) 后一個(gè)節(jié)點(diǎn)的brotherId 改為 被刪節(jié)點(diǎn)的 brotherId,
這樣這一層級(jí)的節(jié)點(diǎn)順序才不會(huì)出錯(cuò)
以上寫了一點(diǎn)后端的做法,下面來(lái)詳細(xì)講解前端實(shí)現(xiàn)

屬性結(jié)構(gòu)的代碼
<el-tree :draggable="true" @node-drop="testTrop" :allow-drop="dropPosition" :data="organization" node-key="id" :current-node-key="currentNode" :default-expanded-keys="keys" :expand-on-click-node="false"
@node-click="nodeClick" :props="defaultProps" ref='treeOrg' :filter-node-method='filterNode' highlight-current>
<span class="custom-tree-node" slot-scope="{ node, data }">
<el-tooltip v-if="node.label.length>10" :content='node.label' placement="top-start" effect="dark"
popper-class="atooltip">
<span>{{node.label | showTreeName}}</span>
</el-tooltip>
<span v-else>{{ node.label }}</span>
<span v-if="node.data.id==selectId">
<el-button type="text" icon="el-icon-edit" size="mini" @click.stop=" () => updateOrganization(data)"></el-button>
<el-button type="text" icon="el-icon-delete" size="mini" @click.stop="() => remove(node, data)"></el-button>
</span>
</span>
</el-tree>
該組織樹的使用
1.draggabl.是否開.拖拽功能
2.allow-dro.拖拽時(shí)判定目標(biāo)節(jié)點(diǎn)能否被放置。
3.node-dro.拖拽成功觸發(fā)的事. 主要是我們 把數(shù)據(jù)發(fā).后端
4.dat.我們要展示的數(shù). 從后端獲取. treeList
5.node-ke.每個(gè)樹節(jié)點(diǎn)用來(lái)作為唯一標(biāo)識(shí)的屬性,整棵樹應(yīng)該是唯一的
6.current-node-ke.當(dāng)前選中的節(jié)點(diǎn)
7.default-expanded-key.默認(rèn)展開的節(jié)點(diǎn).key 的數(shù).. 就是我們 想展開節(jié)點(diǎn).id 數(shù)組
8.expand-on-click-nod. 是否在點(diǎn)擊節(jié)點(diǎn)的時(shí)候展開或者收縮節(jié)點(diǎn), 默認(rèn)值為 true,如果為 false,則只有點(diǎn)箭頭圖標(biāo)的時(shí)候才會(huì)展開或者收縮節(jié)點(diǎn)。
9.node-clic.節(jié)點(diǎn)被點(diǎn)擊時(shí)的回.. 節(jié)點(diǎn)被點(diǎn)擊.我們想做什么. 一般是查詢
10.prop...主要用.指定 我們想展示節(jié)點(diǎn).的那兩個(gè)屬. 屬性.必須和 從后端得到數(shù)據(jù).屬性名 相對(duì)應(yīng)
11.re..ref被用來(lái)給元素或子組. 注. 引用信息.引用信息將會(huì)注冊(cè)在父組件的 $refs對(duì)象上。
12.filter-node-metho. 對(duì)樹節(jié)點(diǎn)進(jìn)行篩選時(shí)執(zhí)行的方法,返回 true 表示這個(gè)節(jié)點(diǎn)可以顯示,返回 false 則表示這個(gè)節(jié)點(diǎn)會(huì)被隱藏
13.highlight-curren. 是否高亮當(dāng)前選中節(jié)點(diǎn),默認(rèn)值是 false。
14.el-toolti. 文字提. 用法 <el-tooltip> 要展示的內(nèi).</el-tooltip. 給這個(gè) 內(nèi)容 做一些提示
. 當(dāng)前我們前端要達(dá)到的效果.如果文字過. 很后面以省略號(hào)結(jié). 但是有必須 讓用.看.該條數(shù)據(jù)的全部?jī)?nèi).所以.文字提示.方法去達(dá)到目的
. 當(dāng)前這個(gè)文字提. 已經(jīng)添..v-i.判斷字?jǐn)?shù)大于1.才會(huì)生效
........... v-els. 就顯示原本的字?jǐn)?shù)
這里主要講解拖拽的兩個(gè)屬性,一個(gè)事件
- 屬性 draggable 是否開啟 拖拽功能
- 屬性 allow-drop 拖拽時(shí)判定目標(biāo)節(jié)點(diǎn)能否被放置。
- 事件 node-drop 拖拽成功觸發(fā)的事件 主要是我們 把數(shù)據(jù)發(fā)給 后端


第一個(gè)draggable沒什么好講的
第三個(gè)node-drop用法也簡(jiǎn)單

本人主要是

我被該屬性卡住了
因?yàn)槲业氖怯幸粋€(gè)限制,同級(jí)中不能有同名組織,
所以需要判定 被拖組織 能否置于 目標(biāo)組織 前面,后面,或者內(nèi)部
dropPosition(draggingNode, dropNode, type) {
console.log(draggingNode);
console.log(dropNode);
console.log(type);
//這三個(gè)參數(shù) 是我們?cè)陧?yè)面拖動(dòng)時(shí) 我們停止拖動(dòng)時(shí) 會(huì)自動(dòng)生成的參數(shù)三個(gè)參數(shù)
// 轉(zhuǎn)移節(jié)點(diǎn)draggingNode 目標(biāo)節(jié)點(diǎn)dropNode 置于目標(biāo)節(jié)點(diǎn)的位置 type='prev'、'inner' 和 'next' 三個(gè)中其中一個(gè)
if (type === "inner") {
checkOrganizationName(draggingNode.data.id, draggingNode.data.name, dropNode.data.id).then(data => {
if (data.data.data === true) {
//說明目標(biāo)節(jié)點(diǎn)內(nèi)部存在 與轉(zhuǎn)移節(jié)點(diǎn) 相同名稱的 節(jié)點(diǎn),不能轉(zhuǎn)入
//那我們不設(shè)返回值 就不會(huì)觸發(fā)移動(dòng)事件
} else {
return "inner";
}
});
} else if (type === "prev" || type === "next") {
//判斷轉(zhuǎn)移節(jié)點(diǎn) 能否放置于 目標(biāo)節(jié)點(diǎn)的 前面或者后面
checkOrganizationName(draggingNode.data.id, draggingNode.data.name, dropNode.data.parentId).then(data => {
if (data.data.data === true) {
//說明 前后不能放
//那我們也不設(shè)返回值 就不會(huì)觸發(fā)移動(dòng)事件
} else {
return type;
}
});
}
},


所以不能通過向后端發(fā)請(qǐng)求的方式,判斷能否放于 目標(biāo)位置
應(yīng)該通過比較前端已經(jīng)有的數(shù)據(jù),判斷能否放于目標(biāo)位置

processDataTree(data) {
for (let index in data) {
let obj = data[index];
this.organizationTemp.push({id: obj.id, name: obj.name, parentId: obj.parentId});
if (obj.children !== null && obj.children.length > 0) {
this.processDataTree(obj.children);
}
}
},
getOrganizationTemp() {
getOrganization().then(data => {
this.organizationAfterMove = data.data.data;
this.organizationTemp = [];
this.processDataTree(this.organizationAfterMove);
});
},
dropPosition(draggingNode, dropNode, type) {
//這三個(gè)參數(shù) 是我們?cè)陧?yè)面拖動(dòng)時(shí) 我們停止拖動(dòng)時(shí) 會(huì)自動(dòng)生成的參數(shù)三個(gè)參數(shù)
// 轉(zhuǎn)移節(jié)點(diǎn)draggingNode 目標(biāo)節(jié)點(diǎn)dropNode 置于目標(biāo)節(jié)點(diǎn)的位置 type='prev'、'inner' 和 'next' 三個(gè)中其中一個(gè)
if (type === "inner") {
if (dropNode.data.children===null){
//目標(biāo)節(jié)點(diǎn)沒有子節(jié)點(diǎn) 可以直接放入
return "inner"
}else {
let childArray=dropNode.data.children;
for (let i = 0; i < childArray.length; i++) {
if (childArray[i].name===draggingNode.data.name){
return
}
}
return "inner"
}
} else if (type === "prev" || type === "next") {
let existObj;
for (let i = 0; i <this.organizationTemp.length; i++) {
let obj = this.organizationTemp[i];
if(obj.parentId === dropNode.data.parentId && obj.name === draggingNode.data.name && obj.id!==draggingNode.data.id){
existObj=obj;
}
}
if (existObj) {
} else {
return type;
}
}
},
testTrop(before,after,inner,event){
changeParentOrg(before.data.id,after.data.id,inner,this.$getCookie().getUserName());
setTimeout(()=>{this.getOrganizationTemp()},500);
},


總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Vue中使用elementui與Sortable.js實(shí)現(xiàn)列表拖動(dòng)排序
- 關(guān)于Element UI table 順序拖動(dòng)方式
- vue/Element?UI實(shí)現(xiàn)Element?UI?el-dialog自由拖動(dòng)功能實(shí)現(xiàn)
- 解決element-ui table設(shè)置列fixed時(shí)X軸滾動(dòng)條無(wú)法拖動(dòng)問題
- element plus tree拖動(dòng)節(jié)點(diǎn)交換位置和改變層級(jí)問題(解決方案)
- elementplus+splitpanes實(shí)現(xiàn)左右拖動(dòng)控制寬度的項(xiàng)目實(shí)踐
相關(guān)文章
vue再次進(jìn)入頁(yè)面不會(huì)再次調(diào)用接口請(qǐng)求問題
這篇文章主要介紹了vue再次進(jìn)入頁(yè)面不會(huì)再次調(diào)用接口請(qǐng)求問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
Vue實(shí)現(xiàn)Echarts圖表寬高自適應(yīng)的實(shí)踐
本文主要介紹了Vue實(shí)現(xiàn)Echarts圖表寬高自適應(yīng)的實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
uniapp微信小程序axios庫(kù)的封裝及使用詳細(xì)教程
這篇文章主要給大家介紹了關(guān)于uniapp微信小程序axios庫(kù)的封裝及使用的相關(guān)資料,Axios是一個(gè)基于promise網(wǎng)絡(luò)請(qǐng)求庫(kù),作用于node.js和瀏覽器中axios-miniprogram-adapteraxios的小程序適配器,需要的朋友可以參考下2023-08-08
Vue渲染器如何對(duì)節(jié)點(diǎn)進(jìn)行掛載和更新
這篇文章主要介紹了Vue 的渲染器是如何對(duì)節(jié)點(diǎn)進(jìn)行掛載和更新的,文中通過代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-05-05
如何實(shí)現(xiàn)vue加載指令 v-loading
在日常的開發(fā)中,加載效果是非常常見的,但是怎么才能方便的使用,本文介紹如何實(shí)現(xiàn)vue加載指令 v-loading,感興趣的朋友一起看看吧2024-01-01

