- 在实际项目开发中,当 tree 的某个节点大于 2000 个时,dom 渲染起来就非常慢,整个页面就会卡了起来.
- 基于 vue elementUI 来开发,用到了 InfiniteScroll 无限滚动 Tree 树形控件
- 来个 demo,具体看下 tree 子节点过多时的卡顿吧。
- 优化思路就是 前端刚开始只加载 10 个子节点,当滚动到底部时,再增加 10 个。
<div id="app">
<div
class="tree-box1"
:infinite-scroll-immediate="false"
v-infinite-scroll="load"
>
<el-tree
:data="curList"
v-loading="loading"
default-expand-all
:props="defaultProps"
@node-click="handleNodeClick"
></el-tree>
</div>
</div>
<style>
.tree-box1 {
height: 200px;
overflow: auto;
}
</style>
<script>
var Main = {
data() {
return {
loading: false,
curtreePageSize: 10,
allList: [],
curList: [],
defaultProps: {
children: 'children',
label: 'label',
},
}
},
methods: {
load() {
if (this.allList.length) {
console.log('滚动')
this.curtreePageSize += 10
this.curList = this.sliceTree(this.allList, this.curtreePageSize)
}
},
handleNodeClick(data) {
console.log(data)
},
sliceTree(data, len = 10) {
return [
{
label: '一级 1',
children: data.slice(0, len),
},
]
},
impersonationRequest() {
this.loading = true
let arr = []
for (let i = 1; i < 4000; i++) {
arr.push({ label: `二级 1-${i}` })
}
setTimeout(() => {
this.allList = arr
this.curList = this.sliceTree(this.allList)
this.loading = false
}, 1000)
},
},
mounted() {
this.impersonationRequest()
},
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
</script>
- 好了基本完结,假如你不用el-tree自带的关键字过滤树节点的话。
又或者后端大佬愿意帮你写个接口,返回过滤后的tree给你;
不然的话,你就自己来实现了。el-tree本身的过滤是没有问题的,但是你用了懒加载,例如只加载了10个,它只会在你10个里面来进行搜索;你就需要自己写个算法来实现;
核心代码如下
const filterTree = (data, name) => {
if (!name) {
this.curList = this.sliceTree(this.allList)
return
}
const PrimaryNode = [...data]
function traverse (node) {
node.forEach(v => {
v.visible = v.label.includes(name)
if (v.children) {
traverse(v.children)
}
if (!v.visible && v.children) {
v.visible = v.children.some(child => child.visible)
}
})
}
function filterName (node) {
const newNode = node.filter(v => v.visible)
newNode.forEach(v => {
if (v.children) {
v.children = filterName(v.children)
}
})
return newNode
}
traverse(PrimaryNode)
const filterNode = filterName(PrimaryNode).slice(0,100)
if(filterNode.length) {
this.curList = [{
label: '一级 1',
children: filterNode
}]
}else {
this.curList = []
}
},