一、场景:一个下拉框中加载上百条、上千条数据,导致下拉框数据卡顿
二、解决方案:
1、初次加载30条左右(这个数量自己决定),当用户滚动下拉列表时,去加载更多数据。
2、合理运用Select组件的popupScroll函数。为了节流控制,我们需要引入lodash库里面的debounce,达到防抖动的目的。
3、使用局部混入,在需要的地方引入即可
4、关键点:任意一个下拉框,主要要使用search、popupScroll、select三个操作事件,同时添加下拉框可搜索filterOption方法
filterOption(input, option) {// 下拉框可搜索
return (
option.componentOptions.children[0].text
.toLowerCase()
.indexOf(input.toLowerCase()) >= 0
);
},
三、代码示例:
vue:
js:
1、把js代码写在了局部混入selectOptions.js文件中,在需要的vue页面引入局部混入,如下图所示
2、使用:
3、selectOptions.js文件代码如下:
为方便大家复制,这里将selectOption.js粘贴如下
import debounce from 'lodash/debounce'
const LOAD_NUM = 30 // 加载条数--可自定义
export const selectOptions = {
data(){
return{
selectedVal: '', // Select框选中的值
oriDataList: [], // 原数据列表 -- 从接口获取
dataLoading: false, // 原数据列表的加载状态 -- 接口的响应状态
searchVal: '', // 搜索的内容
filterDataList: [], // 过滤的数据列表 -- 从dataList中过滤出含搜索内容的数据
}
},
methods: {
// 获取数据源,并取数据源的前n条作为下拉列表的可选项
getSelectList (resData) {
this.oriDataList = resData // 该接口返回的数据存放在res.result(根据实际自行修改)
return this.oriDataList.slice(0, LOAD_NUM)
},
// 文本框值变化时触发 -- 从数据源中过滤出含搜索内容的数据,并取过滤结果的前n条作为下拉列表的可选项
handleSearch (val) {
this.searchVal = val
let filterList = []
if (val) {
filterList = (this.oriDataList).filter(item => item.name.indexOf(val) > -1)
} else {
filterList = this.oriDataList
}
this.filterDataList = filterList
this.tagList = filterList.length < LOAD_NUM ? filterList : filterList.slice(0, LOAD_NUM)
},
// 滚动时触发(防止抖动)
handlePopupScroll: debounce(function () {
if (this.searchVal === '') {
this.loadMoreData(this.oriDataList)
} else {
this.loadMoreData(this.filterDataList)
}
}, 400),
// 加载更多数据到select框
loadMoreData (dataList) {
const renderedLen = this.tagList.length // 已渲染的下拉列表长度
const totalLen = dataList.length // 当前数据源的长度
let addList = []
if (renderedLen < totalLen) {
if (renderedLen + LOAD_NUM <= totalLen) {
addList = dataList.slice(renderedLen, renderedLen + LOAD_NUM)
} else {
addList = dataList.slice(renderedLen, renderedLen + (totalLen % LOAD_NUM))
}
this.tagList = (this.tagList).concat(addList)
}
},
// 被选中时调用,参数为选中项的 value (或 key) 值
handleSelect (val) {
if (this.searchVal) {
const selectedArr = (this.oriDataList).filter(item => item.name === this.searchVal) // 从数据源中过滤出下拉框选中的值,并返回一个数组
const restList = (this.oriDataList).filter(item => item.name !== this.searchVal) // 从数据源中过滤出其他的值,返回一个数组
const newList = selectedArr.concat(restList).slice(0, LOAD_NUM) // 将选中的元素放到下拉列表的第一位
this.tagList = newList // 更新已渲染的下拉列表
this.oriDataList = selectedArr.concat(restList) // 更新数据源
this.searchVal = '' // 因为触发handleSelect函数时,会自动清空用户输入的内容。因此,searchVal需要重置。
}
}
}
}