console
Vue.prototype.$XModal = VXETable.modal
var Main = {
data () {
return {
loading: false,
list: []
}
},
created () {
this.loadTree(10)
},
methods: {
getTree (size) {
const result = []
let idKey = 0
for (let index = 0; index < size; index++) {
const item = {
id: ++idKey,
label: `节点 ${index}`
}
if (index) {
if (index % 33 === 0) {
const childList = []
for (let cIndex = 0; cIndex < 1000; cIndex++) {
childList.push({
id: ++idKey,
label: `子节点 ${index}-${cIndex}`,
children: [
{ label: `子节点 ${index}-${cIndex}-0` },
{ label: `子节点 ${index}-${cIndex}-1` },
{ label: `子节点 ${index}-${cIndex}-2` },
{ label: `子节点 ${index}-${cIndex}-3` },
{ label: `子节点 ${index}-${cIndex}-4` },
{ label: `子节点 ${index}-${cIndex}-5` },
{ label: `子节点 ${index}-${cIndex}-6` },
{ label: `子节点 ${index}-${cIndex}-7` }
]
})
}
item.children = childList
} else if (index % 22 === 0) {
const childList = []
for (let cIndex = 0; cIndex < 500; cIndex++) {
childList.push({
id: ++idKey,
label: `子节点 ${index}-${cIndex}`,
children: [
{ label: `子节点 ${index}-${cIndex}-0` },
{ label: `子节点 ${index}-${cIndex}-1` },
{ label: `子节点 ${index}-${cIndex}-2` }
]
})
}
item.children = childList
} else if (index % 9 === 0) {
const childList = []
for (let cIndex = 0; cIndex < 200; cIndex++) {
childList.push({
id: ++idKey,
label: `子节点 ${index}-${cIndex}`,
children: [
{ label: `子节点 ${index}-${cIndex}-0` },
{ label: `子节点 ${index}-${cIndex}-1` },
{ label: `子节点 ${index}-${cIndex}-2` },
{ label: `子节点 ${index}-${cIndex}-4` },
{ label: `子节点 ${index}-${cIndex}-5` }
]
})
}
item.children = childList
} else if (index % 6 === 0) {
const childList = []
for (let cIndex = 0; cIndex < 100; cIndex++) {
childList.push({
id: ++idKey,
label: `子节点 ${index}-${cIndex}`,
children: [
{ label: `子节点 ${index}-${cIndex}-0` },
{ label: `子节点 ${index}-${cIndex}-1` },
{ label: `子节点 ${index}-${cIndex}-2` },
{ label: `子节点 ${index}-${cIndex}-3` }
]
})
}
item.children = childList
} else if (index % 3 === 0) {
const childList = []
for (let cIndex = 0; cIndex < 10; cIndex++) {
childList.push({
id: ++idKey,
label: `子节点 ${index}-${cIndex}`,
children: [
{ label: `子节点 ${index}-${cIndex}-0` },
{ label: `子节点 ${index}-${cIndex}-1` }
]
})
}
item.children = childList
}
}
result.push(item)
}
return result
},
loadTree (size) {
this.loading = true
setTimeout(() => {
const startTime = Date.now()
const trerData = this.getTree(size)
XEUtils.eachTree(trerData, (item, index, items, paths, parent, nodes) => {
item._LEVEL = nodes.length - 1
item._EXPAND = false
item._VISIBLE = !item._LEVEL
item._HAS_CHILDREN = item.children && item.children.length > 0
item._IS_LEAF = !item._HAS_CHILDREN
})
this.tree = trerData
this.refreshTree()
this.loading = false
this.$nextTick(() => {
this.$XModal.message({ message: `渲染 ${this.fullList.length} 行,用时 ${Date.now() - startTime}毫秒`, status: 'info' })
})
}, 200)
},
toggleTreeNode (row) {
if (row._HAS_CHILDREN) {
this.setTreeExpand(row, !row._EXPAND)
}
},
setTreeExpand (row, isExpand) {
const matchObj = XEUtils.findTree(this.tree, item => item === row)
row._EXPAND = isExpand
if (matchObj) {
XEUtils.eachTree(matchObj.item.children, (item, index, items, path, parent) => {
item._VISIBLE = parent ? parent._EXPAND && parent._VISIBLE : isExpand
})
}
this.refreshTree()
},
allTreeExpand (isExpand) {
if (isExpand) {
XEUtils.eachTree(this.tree, item => {
item._EXPAND = item._HAS_CHILDREN
item._VISIBLE = true
})
} else {
XEUtils.eachTree(this.tree, item => {
item._EXPAND = false
item._VISIBLE = !item._LEVEL
})
}
this.refreshTree()
},
refreshTree () {
const treeList = XEUtils.toTreeArray(this.tree)
this.fullList = treeList
this.list = treeList.filter(item => item._VISIBLE)
}
}
};
var Ctor = Vue.extend(Main);
new Ctor().$mount('#app')
<script src="//unpkg.com/vue"></script>
<script src="//unpkg.com/xe-utils"></script>
<script src="//unpkg.com/vxe-table"></script>
<div id="app">
<template>
<div>
<p>
<vxe-button @click="loadTree(6)">加载30条</vxe-button>
<vxe-button @click="loadTree(15)">加载2000条</vxe-button>
<vxe-button @click="loadTree(45)">加载2w条</vxe-button>
<vxe-button @click="loadTree(100)">加载5w条</vxe-button>
<vxe-button @click="loadTree(200)">加载10w条</vxe-button>
<vxe-button @click="allTreeExpand(true)">全部展开</vxe-button>
<vxe-button @click="allTreeExpand(false)">全部收起</vxe-button>
</p>
<p>
<vxe-list height="400" class="my-tree" :loading="loading" :data="list">
<template v-slot="{ items }">
<div
class="my-tree-item"
v-for="item in items"
:key="item.id"
:class="[`level-${item._LEVEL}`, {'has-child': item._HAS_CHILDREN, 'is-expand': item._EXPAND}]"
:style="{paddingLeft: `${item._LEVEL * 20}px`}">
<i class="tree-icon fa fa-chevron-right" @click="toggleTreeNode(item)"></i>
<span class="tree-label">{{ item.label }}</span>
</div>
</template>
</vxe-list>
</p>
</div>
</template>
</div>
@import url("//unpkg.com/vxe-table/lib/index.css");
@import url("//unpkg.com/font-awesome/css/font-awesome.css");
.my-tree {
padding: 0 10px;
border: 1px solid #e8eaec;
background-color: #fff;
}
.my-tree .my-tree-item {
height: 32px;
line-height: 32px;
}
.my-tree .my-tree-item.has-child .tree-icon {
visibility: visible;
transition: all 0.3s;
}
.my-tree .my-tree-item.is-expand .tree-icon {
transform: rotate(90deg);
}
.my-tree .tree-icon {
cursor: pointer;
width: 20px;
line-height: 20px;
text-align: center;
visibility: hidden;
user-select: none;
}