Vue使用el-tree 懶加載進行增刪改查功能的實現(xiàn)
關于vue的樹形展示 使用到項目:以樹的形式異步展現(xiàn)
效果圖先放:

找到element-ui的官方文檔,el-tree。(地址:https://element.eleme.cn/#/zh-CN/component/tree )
項目需求:以懶加載的形式展示,目錄根據(jù)需求需要有新增 編輯 刪除 操作以及操作后的刷新樹結構
那我們現(xiàn)在開始吧
一、

懶加載:Tree的懶加載,用一個屬性控制:lazy。使用lazy,就要使用load來加載數(shù)據(jù)進行渲染樹
原理:初始化觸發(fā)load函數(shù)先加載初始數(shù)據(jù),通過點擊某個節(jié)點,觸發(fā)load函數(shù),來加載這個節(jié)點下的子節(jié)點。
優(yōu)點:適合數(shù)據(jù)量比較大的時候,對部分節(jié)點刷新也比較友好
二、

自定義節(jié)點:節(jié)點后添加操作按鈕


簡單例子官網上就有示例
**
主要講講更新節(jié)點
**
當對節(jié)點進行編輯、刪除時,需要更新樹,只需更新節(jié)點,不必更新全部的樹即可。
原理:更新節(jié)點,其實更新的是該節(jié)點的子節(jié)點,不包括本節(jié)點。刪除該節(jié)點的子節(jié)點,重新請求數(shù)據(jù)獲取本節(jié)點的子節(jié)點數(shù)據(jù)進行重新渲染。
// refreshNode:要刷新的節(jié)點;newNodeData:新的子節(jié)點數(shù)據(jù) refreshNode.splice(0, refreshNode.length); refreshNode.doCreateChildren(newNodeData);
理解一下:
1>.方法node-click調用函數(shù)menuNodeClick,記錄點擊的節(jié)點信息,對節(jié)點操作前,必然先點擊選中某個節(jié)點。此函數(shù)監(jiān)聽點擊節(jié)點事件,只要點擊了節(jié)點,就觸發(fā):
menuNodeClick(data, node, treeNode) {
this.selectNodeData = data
this.selectNode = node
}
2>.節(jié)點操作后刷新節(jié)點即可,通過不同場景可以選擇刷新本節(jié)點(node)還是刷新本節(jié)點的父節(jié)點(node.parent):
/**
* 刷新節(jié)點數(shù)據(jù)
* @node [node/Object]: 刷新的節(jié)點node,刷新node以下的所有節(jié)點
* @type [String]: node的類型,'node'表示node是樹的節(jié)點信息Node;'data'表示node是樹節(jié)點信息中的data數(shù)據(jù)
*/
refreshTreeNode(node, type) {
let refreshNode;
// 拿到要更新節(jié)點的子節(jié)點
if(type === 'node') {
refreshNode = node.childNodes
}else if(type === 'data') {
let getNode = this.$refs.tree.getNode(node)
refreshNode = getNode.childNodes
}
// 刪除原有的子節(jié)點
refreshNode.splice(0, refreshNode.length);
//重新請求數(shù)據(jù),更新節(jié)點
this.requestTreeNode(node)
}
3.選擇框checkBox:
如果懶加載中,有選擇框,需要將有選擇框的數(shù)據(jù)加載出來,然后通過屬性default-checked-keys來勾選,通過default-expanded-keys設置展開的節(jié)點。
4.單選:
如果在懶加載中,有單選項,則設置選中即可:
// 設置當前節(jié)點選中
this.$refs.tree.setCurrentKey(
this.selectNodeData[this.nodeKey]
)
不管是單選還是多選,在第一次加載時,后臺要給的,不只是選中信息,還需要選中節(jié)點所在分支的所有節(jié)點信息,賦值給default-expanded-keys以便可使節(jié)點所在分支從上到選擇項都展開。但往往,后臺可能給的,只是選中值的信息,這就要前端自己封裝數(shù)據(jù),獲取需要展開的分支信息。根據(jù)數(shù)據(jù)格式不同,用不同的方法
1)樹形單層數(shù)據(jù)格式:
[
{...},
{...},
{...}
]
這種格式的數(shù)據(jù),【點擊一層,加載一層】、【點擊一層,加載該點擊層的多層子節(jié)點】兩種情況都可以滿足。第一種不需要進行數(shù)據(jù)處理;第二種情況,需要在每條數(shù)據(jù)中注入一個字段,用來關聯(lián)父子節(jié)點,然后將數(shù)據(jù)封裝處理成el-tree所需要的格式,用一個遞歸函數(shù)整合數(shù)據(jù)(假設關聯(lián)字段為parentId,nodeKey為id,樹的子節(jié)點字段為children,需要加載id為'N'的多層子節(jié)點)(注:遞歸函數(shù)會影響性能,謹慎使用)
2).多層數(shù)據(jù)(假設子節(jié)點的屬性名是children)
[
{
...,
children: [
{
...,
children: [
{
...,
children: [...],
},
{
...,
children: [...],
}
]
},
{
...,
children: [
{
...,
children: [...],
}
]
}
]
}
]
這種格式的數(shù)據(jù),單層、多層都可以滿足,不需要做處理。
選中值整合并展開選中值所在的樹:多層數(shù)據(jù)可由后臺給出選中節(jié)點所在的整個分支的值,賦給default-expanded-keys進行展開。也可以自己做篩選,寫一個遞歸函數(shù),將多層數(shù)據(jù)循環(huán),找到選中值的節(jié)點的分支來設置展開(假設nodeKey為id,樹的子節(jié)點字段為children,需要展開id為'N'的節(jié)點所在的整個分支)
懶加載示例:
HTML控件:
<el-tree
:data="treeData"
:props="defaultProps"
:load="loadNodeTree"
@node-click="handleNodeClick"
lazy
:expand-on-click-node="false"
:default-expanded-keys="['1']"
node-key="id"
:highlight-current="true"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span class="treeLeft">{{ node.label }}</span>
<span class="treeRight">
<i
v-if="node.level === 1"
@click="() => appendNode(node, data)"
class="el-icon-plus"
style="color: blue"
></i>
<!--增加分組-->
<!-- 根節(jié)點不需要刪除和重命名 -->
<i
v-if="data.id !== 0"
@click="() => deleteNode(node, data)"
class="el-icon-delete"
style="color: red"
></i>
<!--刪除分組-->
<i
v-if="data.id !== 0"
@click="() => editNode(node, data)"
class="el-icon-edit"
style="color: blue"
></i>
<!--重命名分組-->
</span>
</span>
</el-tree>
vue:
data里面定義變量
// 樹形菜單
treeData: [], // 樹節(jié)點
defaultProps: { // 修改el-tree默認data數(shù)組參數(shù)
children: 'children',
label: 'name',
id: 'id',
parentId: 'parentId',
isLeaf: 'leaf' // 指定節(jié)點是否為葉子節(jié)點,僅在指定了 lazy 屬性的情況下生效
},
methods:
加載樹形菜單部分
// 加載 樹數(shù)據(jù)
loadNodeTree(node, resolve) {
const that = this
if (node.level === 0) {
that.loadtreeData(node, resolve)
} else if (node.level === 1) {
that.getChildByList(node, resolve)
}
},
// 獲取loadtreeData 就是父節(jié)點數(shù)據(jù),getChildByList就是異步獲取子節(jié)點數(shù)據(jù)
loadtreeData(nodeData, resolve) {
const dataType = {
pageIndex: 1,
pageSize: 100000
}
getAlltype(dataType)
.then(res => {
const rootChildren = []
if (res.code === 200) {
const data = res.data.list
data.map(item => {
rootChildren.push({
name: item.typeName,
parentId: '',
id: item.id,
leaf: false,
children: []
})
})
//如果resolve有內容就是懶加載走查詢 否則走的是修改
if (resolve) {
resolve(rootChildren)
} else {
nodeData.childNodes = []
nodeData.doCreateChildren(rootChildren)
}
} else {
resolve([])
}
})
},
// 獲取子節(jié)點請求
getChildByList(nodeData, resolve) {
var _parentID = nodeData.data.id
const typeSpec = {
typeId: _parentID,
pageIndex: 1,
pageSize: 100000
}
getAlltypeSpec(typeSpec).then(res => {
const rootChildren = []
if (res.code === 200) {
const data = res.data.list
data.map(item => {
rootChildren.push({
name: item.description,
parentId: item.typeId,
id: item.id,
leaf: true,
children: []
})
})
if (resolve) {
resolve(rootChildren)
} else {
nodeData.childNodes = []
nodeData.doCreateChildren(rootChildren)
}
} else {
return false
}
}).catch(err => {
console.log(err)
})
},
// 節(jié)點點擊事件
handleNodeClick(data, node) {
this.addnode = node
this.adddata = data
if (node.level === 1) {
this.queryForm.typeId = node.data.id
this.queryForm.typeSpecId = ''
} else if (node.level === 2) {
this.queryForm.typeId = node.data.parentId
this.queryForm.typeSpecId = node.data.id
}
this.query()
},
節(jié)點操作:增加節(jié)點 修改節(jié)點 刪除節(jié)點 (操作自己節(jié)點要傳父節(jié)點信息才能找到自己當前節(jié)點,操作子節(jié)點就傳當前節(jié)點 結論:父節(jié)點操作子節(jié)點)
// 樹節(jié)點增加 類型規(guī)格
appendNode(node, data) {
this.addTypesSpec = {
typeName: node.data.name,
typeId: node.data.id
}
this.createTypesSpecDialog = true
},
// 樹類型修改
editNode(node, data) {
const typeId = node.data.parentId
// 一級 類型
if (node.level === 1) {
this.editTypesDialog = true
this.editTypes = {
id: node.data.id,
typeName: node.data.name
}
} else {
this.editTypesSpecDialog = true
this.getSelectTypes()
// this.editTypesSpec = Object.assign({}, node.data)
this.editTypesSpec = {
typeId: typeId,
id: node.data.id,
description: node.data.name
}
}
},
// 樹類型刪除
deleteNode(node, data) {
// 一級 類型
if (node.level === 1) {
this.$msgbox.confirm('此操作將刪除資產類型數(shù)據(jù), 是否繼續(xù)?', '刪除提示', {
confirmButtonText: '確定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
typeDel(node.data.id).then(
resp => {
this.$message('刪除成功')
this.query()
this.loadNodeTree(node.parent)
},
err => {
console.log('err', err)
}
)
}).catch(() => {
this.$message.error('已取消')
})
} else {
this.$msgbox.confirm('此操作將刪除資產類型規(guī)格數(shù)據(jù), 是否繼續(xù)?', '刪除提示', {
confirmButtonText: '確定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
typeSpecDel(node.data.id).then(
resp => {
this.loadNodeTree(node.parent)
this.$message('刪除成功')
this.query()
},
err => {
console.log('err', err)
}
)
}).catch(() => {
this.$message.error('已取消')
})
}
},
節(jié)點觸發(fā)之后顯示彈框 走正常的彈框增加修改刪除操作,只不過在提交后臺請求返回操作成功之后需要再一次加載樹形結構 所以在這里再一次調用加載樹形方法,傳的node 當觸發(fā)點擊樹形的時候可以保存一下,我的是handleNodeClick這個方法 不管點擊修改 增加還是刪除都保存下點擊的node
this.$message('編輯成功')
this.loadNodeTree(this.addnode.parent)
1.設置展開和收縮
if (!node.expanded) {
node.expand();
}else {
node.collapse();
}
2.獲取父節(jié)點
node.parent
看得懂的就看吧 代碼可以優(yōu)化 但是最近沒啥時間 看不懂的能清楚這個邏輯也行啊 下次見
到此這篇關于Vue使用el-tree 懶加載進行增刪改查的文章就介紹到這了,更多相關Vue el-tree 懶加載內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Vue中mintui的field實現(xiàn)blur和focus事件的方法
今天小編就為大家分享一篇Vue中mintui的field實現(xiàn)blur和focus事件的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08
vue3中使用pinia(大菠蘿)狀態(tài)管理倉庫的項目實踐
本文主要介紹了vue3中使用pinia(大菠蘿)狀態(tài)管理倉庫,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-07-07
vue報錯"vue-cli-service‘不是內部或外部命令,也不是...”的解決辦法
這篇文章主要介紹了vue報錯"vue-cli-service‘不是內部或外部命令,也不是...”的解決辦法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-01-01

