一:背景
我們這個穿梭框獲取的是項目的全量數據,在左邊大概有5000條,自己測試了一下5000條數據的效果,發現異常的卡頓,本來打算像el-select一樣去解決的(只顯示一部分,在搜索的時候去全量搜索,奈何這個搜索方法不支持遠程搜索,只能棄用該解決方案),一頓百度跟ai搜索,感覺答案都比較模糊,所以記錄一下該解決方案。
二:解決方案一(最簡單):
參考:el-transffer大數據量頁面卡頓優化
a.安裝
npm install el-virtual-transfer --save
b.使用
組件內導入注冊一下即可使用:
import ElTransferVirtual from 'element-transfer-virtual'
components: { ElTransferVirtual }
c.替換組件名
直接用ElTransferVirtual替換你的el-transfer組件名就行了。其他的都不用變
<template><div class="home"><el-virtual-transferfilterable:filter-method="filterMethod"filter-placeholder="請輸入城市拼音"v-model="value":data="data"></el-virtual-transfer></div>
</template><script>
import ElVirtualTransfer from 'el-virtual-transfer';
export default {name: 'HomeView',data() {const generateData = _ => {const data = [];// 生成 3000 個數據for (let i = 0; i < 3000; i++) {const label = `城市${i + 1}`;const key = i;const pinyin = `chengshi${i + 1}`;data.push({label: label,key: key,pinyin: pinyin});}return data;};return {data: generateData(),value: [],filterMethod(query, item) {return item.pinyin.indexOf(query) > -1;}};},created() {},methods: {},components: {ElVirtualTransfer}
};
</script>
d.優缺點:
優點:使用十分的簡單,只需要安裝依賴替換組件名即可
缺點:該組件方案只上傳到了npm,但是并沒有開源。我的意思是,如果你的數據是全量數據(獲取全量數據不卡的話),就可以直接使用這個方案,畢竟簡單。( 如果獲取全量數據卡的話,你可以在用戶進入頁面時就去靜默分批的獲取這個數據,也是一種解決方案)
三:解決方案二(拓展性強):
參考: Element-UI的transfer穿梭框組件數據量大解決方案
a.在components下面新建一個文件夾,用來存放組件
main.vue , transfer-checkbox-item.vue ,transfer-panel.vue的內容我就不貼了。可以直接去我的demo上復制過來就可以用了。
這里還要安裝一個插件(代碼里用到了虛擬滾動的插件):
npm i vue-virtual-scroll-list
b.自定義指令代碼
因為組件內用到了一個自定義指令,所以需要把這個自定義指令的代碼復制過來,在directives文件夾下,直接把我的代碼(infinite-scroll整個文件夾)復制過來就行。并且在main.js上注冊一下:
c.main.js注冊自定義指令:
import InfiniteScroll from '@/directives/infinite-scroll'; // 替換為實際路徑
InfiniteScroll.install(Vue);
d.替換組件名,并且傳入 :virtual-scroll="true"激活虛擬列表
直接用Transfer替換你的el-transfer組件名就行了,并且一定要傳入:virtual-scroll=“true”,不然跟原來的el-transfer沒有區別,還是會很卡。
<template><div class="about"><Transferfilterable:filter-method="filterMethod"filter-placeholder="請輸入城市拼音"v-model="value":data="data":virtual-scroll="true"></Transfer></div>
</template><script>
import Transfer from '@/components/Transfer/main.vue';
export default {name: 'HomeView',data() {const generateData = _ => {const data = [];// 生成 3000 個數據for (let i = 0; i < 9000; i++) {const label = `城市${i + 1}`;const key = i;const pinyin = `chengshi${i + 1}`;data.push({label: label,key: key,pinyin: pinyin});}return data;};return {data: generateData(),value: [],filterMethod(query, item) {return item.pinyin.indexOf(query) > -1;}};},created() {},methods: {},components: {Transfer}
};
</script>
e.優缺點:
優點:1.源碼都已經給你了,可以根據自己的項目來自定義 2.上面那個方案只能傳入全量的數據,但是這個方案因為源碼都給你了,你可以修改源碼,在一開始的時候只加載部分數據,然后用戶下拉的時候再去加載更多的數據,搜索的話,你可以用全量數據來搜索
缺點: 需要復制的內容過多
四.原理
大家可以把項目demo跑起來看一下,其實都是修改了el-transfer的源碼,然后結合虛擬列表的組件來使dom渲染的結構更少。具體虛擬列表的原理,大家可以自行百度下: 其核心思想就是在處理用戶滾動時,只改變列表在可視區域的渲染部分,然后translate來讓渲染的列表偏移到可視區域中,給用戶平滑滾動的感覺。
其實原理都是一樣的,大家如果能采用的話,還是盡量采用第一種方案,因為已經壓縮過了,代碼體積更小。
五.demo源碼地址
github: https://github.com/rui-rui-an/el_transfer_big_data