問題背景
項目中有用到樹組件用來做文件目錄,但是由于這個樹組件的節點越來越多,導致頁面在滾動這個樹組件的時候瀏覽器就很容易卡死。這種問題基本上都是因為dom節點太多,導致的瀏覽器卡頓,這里很明顯就需要用到虛擬列表的技術(即不渲染這么多的節點)。
解決方案
如果是vue3,那么直接使用element-plus提供的Tree V2 虛擬化樹形控件組件即可。但是因為這個項目是一個vue2的項目,并且它原先用的是iview的組件來實現的,我這邊不可能因為這個優化就把項目升級到vue3,所以有兩個解決思路: 1.從網上找輪子 2.自己造輪子(時間太緊,放棄) 。找了很久終于找到一個比較好用的輪子,分享給大家使用,以后有遇到相同問題的時候可以參考下。
解決過程:
使用vue-easy-tree來優化樹組件(文檔地址)
1.安裝虛擬樹組件,以及安裝sass和sass-loader
npm i @fortawesome/fontawesome-free@6.7.2 -s
由于這個項目依賴了saas,所以要把這個也安裝下
npm i sass@1.89.1 sass-loader@7.3.1 -D
2.導入使用
import VueEasyTree from '@wchbrad/vue-easy-tree'
import '@wchbrad/vue-easy-tree/src/assets/index.scss'components: {VueEasyTree},
3.替換el-tree來使用
注意:該組件和element-ui的tree組件的prop是一致的(所以使用的使用可以參考element的tree組件),但是加了height屬性時就會開啟虛擬列表
4.完整代碼
<template><div class="home"><div class="left_box"><!-- <el-tree :data="treeData" :props="props" ref="veTree" node-key="id" :default-expanded-keys="['Root']"class="op-tree" :render-content="treeRender"></el-tree> --><vue-easy-treeref="veTree"node-key="id"class="op-tree"height="calc(100vh - 110px)":default-expanded-keys="['Root']":data="treeData":props="props":render-content="treeRender"></vue-easy-tree></div></div>
</template><script>
import treeData from './treeData'
import VueEasyTree from '@wchbrad/vue-easy-tree'
import '@wchbrad/vue-easy-tree/src/assets/index.scss'export default {name: 'HomeView',components: {VueEasyTree},computed: {},data() {return {treeData: treeData,props: {children: 'children',label: 'title'},localFile: {title: '',nodeId: '',nodeType: '',pId: ''},}},created() {console.log('treeData', this.treeData)},methods: {treeRender(h, { data }) {// nodeType 'file','文件','dir','文件夾'return (<div class={this.localFile.nodeId === `${data.id === 'Root' ? '/' : data.id.replace('Root', '')}` ? 'active tree-item' : 'tree-item'}><span on-click={() => { this.changeCode(data, `${data.nodeType}Detail`) }} class={this.localFile.nodeId === `${data.id === 'Root' ? '/' : data.id.replace('Root', '')}` ? 'colorBlue tree-item-title textOverflow' : 'tree-item-title textOverflow'}>{data.nodeType === 'file' ? <i class="fa fa-file"></i> : data.nodeType === 'dir' ? <i class="fa fa-folder-open"></i> : <span></span>} {data.title}</span><div class="button-group">{data.nodeType !== 'file'? <tooltip content="新增" transfer placement="top"><i class="fa fa-plus" on-click={() => { this.changeCode(data, 'add') }}></i></tooltip> : <span></span>}{data.id !== 'Root'? <tooltip content="修改" transfer placement="top"><i class="fa fa-edit" on-click={() => { this.changeCode(data, 'modify') }}></i></tooltip> : <span></span>}{data.id !== 'Root'? <tooltip content="刪除" transfer placement="top"><i class="fa fa-trash" on-click={() => { this.changeCode(data, 'delete') }}></i></tooltip> : <span></span>}</div></div>)},changeCode(data = '', type) {this.view = ''this.$nextTick(() => {if (data.title && data.id) {this.localFile = {title: data.title,nodeId: `${data.id === 'Root' ? '/' : data.id.replace('Root', '')}`,nodeType: data.nodeType,pId: data.pId}type === `${data.nodeType}Detail` ? this.handleDetail(data.nodeType): type === 'add' ? this.handleAdd(): type === 'modify' ? this.handleEdit(): type === 'delete' ? this.handleDelete() : ''} else {this.$Notice.warning({title: '提醒',desc: '找不到當前信息',duration: 3})}})},handleDetail(){console.log('詳情')},handleEdit() {console.log('編輯')},handleAdd() {console.log('新增')},handleDelete() {console.log('刪除')},},};
</script>
<style lang="less" scoped>
.home {.left_box {width: 300px;height: 90vh;border: 1px solid #ccc;overflow-y: auto;}
}
</style>
總結
很多項目由于前期數據量不大,所以組件可以正常使用,但是當用戶量或者數據量大了之后,瀏覽器就會變得卡頓,這種優化就是必須的。大家可以把代碼拉下來運行對比下,沒有使用虛擬列表技術的樹真的很卡。
項目地址
gitHub:https://github.com/rui-rui-an/virtual_tree