element tree懒加载(自写)_element tree 懒加载-爱代码爱编程
-
需求:树形结构懒加载,一共三层,默认显示第一和第二层,第三层数据通过点击第二次数据层请求接口再显示(主要是第三层数据量大加载太慢,所以分开展示),点击第二次请求数据时该层需要有加载动画就是那个loading图标
-
接口:一共两个接口,第一个接口返回第一层和第二层数据,第二个接口返回第三层数据(通过点击第二层某个触发,请求参数为当前第二层的id)
-
环境:vue2,element ui
-
原理:主要是后端先写完接口了,但是接口不太符合tree自带的懒加载需要的格式,所以前端只能自己写个懒加载,懒加载说到底就是点击了才请求该层数据,所以只要第三层接口可以用就也行,
-
知识点
- 加载动画需要自己添加所以需要使用tree的插槽
- 使用tree的方法
@node-click
,点击层级触发该方法
-
代码
// html
<el-tree
:data="dataTree"
:props="defaultProps"
show-checkbox
@check-change="handleCheckChange"
check-strictly
node-key="id"
ref="tree"
:default-expand-all="true"
@node-click="nodeExpand"
>
<template slot-scope="{node,data}">
<div>
<span v-if="data.iState==1"><i class="el-icon-loading"></i></span>
<span >{{data.name}}</span>
</div>
</template>
</el-tree>
// js
import { searchParent,searChild} from '@/api/xxxx/tree.js'; // 接口js文件
created(){
this.getList()
},
data() {
return{
treeloading:true,// 树形结构加载
dialogVisible:false,
searchVal:'',// 搜索值
dataTree: [],
defaultProps: {
children: 'child',
label: 'name',
id:'id',
disabled: function (data, node) {//带子级的节点不能选中
if (node.level && node.level!==3) {
return true
} else {
return false
}
},
},
}
},
methods: {
/** */
//
getList(){
this.treeloading= true
searchParent().then(res=>{
if(res.code==200){
let acce = res.data.map(item=>{
if(item.child){
item.child.forEach(itemChild=>{
itemChild['iState']=false // 添加加载动画控制符 true显示,false隐藏,请求值加载,请求成功后隐藏
})
return item
}
})
this.dataTree = acce
this.$refs.tree.setCheckedKeys([])
this.treeloading = false
// this.dialogVisible = true
}
})
},
/** 展开节点 */
nodeExpand(obj,node,componentObj){
if(node.level==2){
if(obj.child.length>0) return // 如果有孩子了就说明刚才已经加载过,就不继续请求接口了
/** 点击第二层时请求接口 */
obj['iState'] =true
searChild(obj.id).then(res=>{
if(res.code==200){
obj.iState = false
obj.child = res.data // 这个地方感觉想到的非常棒!目前还没测出bug(把请求的第三层的数据直接加载点击的第二层的对象的孩子下!,利用了vue响应式数据的原理应该)
}
})
}
},
}
-
效果展示
- 点击第二层的某一个,请求接口出现加载动画
- 加载出数据
- 点击第二层的某一个,请求接口出现加载动画
-
第一个接口的数据结构模拟 searchParent, 一起返回的是第一层和第二层的数据
res.data =[ { "id": 1, "name": "Group1", "child": [ { "id": 128, "name": "qq", "child": [] }, { "id": 129, "name": "ww", "child": [] }, { "id": 130, "name": "ee", "child": [] }, { "id": 131, "name": "rr", "child": [] }, ] } ]
-
第二个接口返回数据格式模拟 searChild,仅仅返回第三层数据
res.data =[ { "id": 1233, "name": "cc" }, { "id": 123434, "name": "ff" }, ]
需求增加:
需求描述:第二层在没点击的情况下需要显示下拉箭头,点击下拉箭头请求第三层数据(默认不知道第二层是否有孩子的情况下是没下拉箭头的,因为这没有使用element自带的懒加载所以isLeaf属性无效,只能从数据方面下手),需要改动的地方有三处
-
tree的属性方法名由
node-click
改为node-expand
展开是请求数据,把树设置为默认不展开层级@node-expand="nodeExpand" :default-expand-all="false"
-
修改第一次请求数据后返回的数据结构,给第二层数据添加假孩子
getList(){ this.treeloading= true searchParent().then(res=>{ if(res.code==200){ let acce = res.data.map(item=>{ if(item.child){ item.child.forEach(itemChild=>{ itemChild['iState']=false // 添加加载动画控制符 true显示,false隐藏,请求值加载,请求成功后隐藏 itemChild['child'] = [{name:null}] // 修改处,后续有孩子就替换,无孩子就改为空数组 }) return item } }) this.dataTree = acce this.$refs.tree.setCheckedKeys([]) this.treeloading = false // this.dialogVisible = true } }) },
-
修改点击第二层下拉箭头时请求的方法逻辑,看是否有孩子,有孩子就替换,没孩子就把该层child设为【】
/** 展开节点 */ nodeExpand(obj,node,componentObj){ if(node.level==2){ if(obj.child[0].name!=null) return // 如果第一个孩子有名称就说明刚才已经加载过,就不继续请求接口了 /** 点击第二层时请求接口 */ obj['iState'] =true obj['child'] =[] searChild(obj.id).then(res=>{ if(res.code==200){ obj.iState = false if(res.data.length>0){ obj.child = res.data // 请求接口返回的有孩子才赋值,没孩子就把第二步加的假孩子child设为[],去除假数据 } } }) } },
-
改后效果:即在第一次请求接口给把第二层增加下拉箭头(无论第二层有没有孩子,后续请求第二层接口时会判断,没孩子就去掉箭头)