SOURCE

console 命令行工具 X clear

                    
>
console
// 将全局模态窗口挂载到 vue 实例中
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;
}