效果
前情提要:
最近使用element-ui開發的一個頁面,在打開的時候占用cpu非常高,有時候都能達到90%↑。在調試時發現其中一個下拉框的接口返回2k↑的數據。本着有問題問百度的精神,看到主要的解決方案有如下兩種:
-
監聽下拉框滾動事件,去服務端請求數據 https://blog.csdn.net/zhangshineng/article/details/89676413?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
-
渲染一部分數據,其余部分需要手動篩選 https://www.cnblogs.com/mianbaodaxia/p/11153341.html
方案1:分頁獲取數據,根據select觸發事件去接口獲取下一頁。方案2:渲染一部分數據,其余數據需手動輸入篩選。兩種方案的核心都是將數據獲取與渲染dom分開(渲染時性能消耗較大),我的數據最多有2K條左右,讓后端加一個接口感覺不太合適,參考以上兩種方案,本地進行優化
1.前端獲所有數據實現本地分頁
2.可輸入文字篩選待選項
代碼 https://github.com/dadademo/demo/blob/main/src/components/select.vue
<template>
<div>
<el-select class="order-cover-select" v-model="selectModel" clearable placeholder="請選擇設備名稱" filterable multiple collapse-tags v-el-select-loadmore="loadmore" :filter-method="filterVmModel">
<el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</div>
</template>
<script>
// select 分頁
export default {
name: 'selectDemo',
// 此處詳見:https://blog.csdn.net/zhangshineng/article/details/89676413?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
// 文檔:https://cn.vuejs.org/v2/guide/custom-directive.html
directives: {
// 計算是否滾動到最下面
'el-select-loadmore': {
bind (el, binding) {
// 獲取element-ui定義好的scroll盒子
const SELECTWRAP_DOM = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap');
SELECTWRAP_DOM.addEventListener('scroll', function () {
/**
* scrollHeight 獲取元素內容高度(只讀)
* scrollTop 獲取或者設置元素的偏移值,常用於, 計算滾動條的位置, 當一個元素的容器沒有產生垂直方向的滾動條, 那它的scrollTop的值默認為0.
* clientHeight 讀取元素的可見高度(只讀)
* 如果元素滾動到底, 下面等式返回true, 沒有則返回false:
*/
const condition = Math.round(this.scrollHeight - this.scrollTop) <= this.clientHeight;
if (condition) {
binding.value();
}
});
}
}
},
data () {
return {
selectModel: '',// select 選擇的數據
optionAll: [], // 全部的數據
options: [], // 分頁數據
// 分頁參數
query: {
page: 1,
limit: 10
},
filterText: '' // 篩選文本
}
},
created () {
this.initData()
},
methods: {
// 初始化數據
initData () {
// http request....
// 模擬2k條數據
let demoData = []
for (let index = 0; index < 2000; index++) {
demoData.push({ name: `測試${index}`, id: index })
}
this.optionAll = demoData
this.loadmore(true)
},
// 分頁方法 詳見 directives
loadmore (firstTag) {
// 篩選時下拉不觸發分頁
if (!this.filterText) {
if (!firstTag) {
this.query.page++
}
// 前端分頁簡單版本
// 分頁開始坐標
const begin = this.query.limit * (this.query.page - 1)
// 分頁結束坐標
const end = (this.query.limit * (this.query.page - 1)) + this.query.limit
// 這里使用slice 進行分頁
this.options.push(...this.optionAll.slice(begin, end))
}
},
// 篩選方法
// 此處詳見:https://www.cnblogs.com/mianbaodaxia/p/11153341.html
filterVmModel (value) {
this.filterText = value
// 篩選數據
if (value) {
this.options = this.optionAll.filter(item => {
if (item.name && item.name.indexOf(value) !== -1) {
return true
} else {
return false
}
})
} else {
// 直接賦值會連續觸發 loadmore 分頁事件
this.options = []
this.$nextTick(() => {
this.options = this.optionAll.slice(0, this.query.limit * this.query.page)
})
}
},
}
}
</script>
注:參考鏈接只是在百度搜索到的,有的未找到原文鏈接,如有問題私信我修改或刪除
以上代碼還可以優化,在搜索的結果也進行分頁(有興趣的可以搞一下)