实际需求:在项目中一个下拉框中需要展示10000条数据,这10000条数据去后端查询虽然比较快,但是将查询结果返回给前端需要进行渲染,前端就会造成卡顿的现象,这时候就可以使用滑动加载只渲染总数据前100条数据以保证不卡顿。
然后当需要搜索的时候对从后台拿到的数据进行过滤,也只取前100条,然后通过select下拉框popupScroll事件,下拉列表滚动时的回调,每次回调时都添加一部分数据来解决下拉框的卡顿问题。
虽然解决了卡顿问题,但是非常的不方便查询数据,这时候就需要对下拉框实现一个模糊查询的功能,从而解决了滑动加载所带来的不便,满足需求。
官方文档
https://www.antdv.com/components/select-cn/#API
效果图
模板
代码部分:
html:【滑动加载主要跟@popupScroll="handlePopupScroll"有关,模糊查询与showSearch和@search有关】
@search 可以获取到当前输入的Value值
<a-select
allowClear
mode="multiple"
placeholder="供应商"
style="width: 100%"
:value="sourceOwnerSystems"
showSearch
@change="onTreeSelect"
@popupScroll="handlePopupScroll"
@search="handleSearch"
>
<a-select-option v-for="frontSelect in frontDataZ.filter(item=>item.sourceOwnerSystems)" :key="frontSelect.sourceOwnerSystems"> //过滤一下数据是否为空
{{ frontSelect.sourceOwnerSystems }}
</a-select-option>
</a-select>
js:
(1).data中定义变量与数组
data(){
return {
dataZ: [],//总数据(不会改变),从后端查询的所有数据。
frontDataZ: [], //存放前100的数据
sourceOwnerSystems: [], //集合(过滤后的)
valueData: '',
treePageSize: 100,
scrollPage: 1
}
}
(2).methods:
//通过接口获取数据
showTabelCiList () {
// 发送请求
listSimpleInfos({sourceOwnerSystems: this.sourceOwnerSystems}).then(res => {
if (res && res.data) {
this.dataZ = res.data // 获取所有的数据赋值给dataZ
this.frontDataZ = res.data.slice(0, 100) // 只渲染100条数据
}
}).catch(e => {
this.$message.error('查询维护信息失败:' + e)
})
},
// 搜索的时候执行的方法,val就是输入的时候的内容,可以去后端进行查询数据最后赋值给dataZ或者frontDataZ
handleSearch (val) {
this.valueData = val
if (!val) {
this.showTabelCiList()
} else {
this.frontDataZ = []
this.scrollPage = 1
this.dataZ.forEach(item => {
if (item.instanceId.indexOf(val) >= 0) {
this.frontDataZ.push(item)
}
})
this.allDataZ = this.frontDataZ
this.frontDataZ = this.frontDataZ.slice(0, 100) // 只渲染100条数据
}
},
//下拉框下滑事件
handlePopupScroll (e) {
const { target } = e
const scrollHeight = target.scrollHeight - target.scrollTop
const clientHeight = target.clientHeight
// 下拉框不下拉的时候
if (scrollHeight === 0 && clientHeight === 0) {
this.scrollPage = 1
console.log(this.scrollPage)
} else {
// 当下拉框滚动条到达底部的时候
if (scrollHeight < clientHeight + 5) {
this.scrollPage = this.scrollPage + 1
const scrollPage = this.scrollPage// 获取当前页
const treePageSize = this.treePageSize * (scrollPage || 1)// 新增数据量
const newData = [] // 存储新增数据
let max = '' // max 为能展示的数据的最大条数
if (this.dataZ.length > treePageSize) {
// 如果总数据的条数大于需要展示的数据
max = treePageSize
} else {
// 否则
max = this.dataZ.length
}
// 判断是否有搜索
if (this.valueData) {
this.allDataZ.forEach((item, index) => {
if (index < max) { // 当data数组的下标小于max时
newData.push(item)
}
})
} else {
this.dataZ.forEach((item, index) => {
if (index < max) { // 当data数组的下标小于max时
newData.push(item)
}
})
}
this.frontDataZ = newData // 将新增的数据赋值到要显示的数组中
}
}
}
实际项目代码改造
代码部分:
html:
<!--下拉框 -->
<a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="供应商" data-step="1" data-title="供应商">
<!-- @popupScroll="handlePopupScroll"滑动加载 -->
<a-select placeholder="选择供应商"
v-decorator="[ 'organId',validatorRules.organId]"
:dropdownMatchSelectWidth="false"
showSearch
optionFilterProp="children"
@popupScroll="handlePopupScroll"
allowClear
@search="supValue"
>
<!--上面就多加了一个@popupScroll="handlePopupScroll"滑动加载和@search="supValue"获取输入框的值-->
<!--这个是下拉框 frontDataZSupplier 供应商-->
<!-- 原本的代码 <a-select-option v-for="(item,index) in supList" :key="index" :value="item.id">
{{ item.supplier }}
</a-select-option>-->
<a-select-option v-for="item in frontDataZSupplier.filter(item=>item.supplier)" :key="item.supplier" :value="item.id">
{{ item.supplier }}
</a-select-option>
</a-select>
</a-form-item>
js:
(1).data中定义变量与数组
data() {
return {
/**
* 滑动加载
* */
supList: [], //从后端查询的所有数据(不会改变)
frontDataZSupplier:[], // 供应商 100条数据的集合
sourceOwnerSystems: [], // 供应商名称的集合(过滤)
treePageSize: 100,
scrollPage: 1,
}
}
(2).methods:
/**
* 点击编辑页面,页面初始化的时候就会发送请求去后端进行查询供应商
* */
initSupplier() {
let that = this;
findBySelectSup({}).then((res) => {
if (res) {
// 将查询到的数据直接赋值给supList集合
that.supList = res;
// add 滑动加载数据
that.frontDataZSupplier = res.slice(0, 100) // 展示100条数据,如果100条还是卡顿,可以改小
}
});
},
Vue页面:下面方法我只将以前的dataZ(总数据)改成我自己的supList,frontDataZ改成了frontDataZSupplier。
//下拉框下滑事件
handlePopupScroll (e) {
const { target } = e
const scrollHeight = target.scrollHeight - target.scrollTop
const clientHeight = target.clientHeight
// 下拉框不下拉的时候
if (scrollHeight === 0 && clientHeight === 0) {
this.scrollPage = 1
console.log(this.scrollPage)
} else {
// 当下拉框滚动条到达底部的时候
if (scrollHeight < clientHeight + 5) {
this.scrollPage = this.scrollPage + 1
const scrollPage = this.scrollPage// 获取当前页
const treePageSize = this.treePageSize * (scrollPage || 1)// 新增数据量
const newData = [] // 存储新增数据
let max = '' // max 为能展示的数据的最大条数
if (this.supList.length > treePageSize) {
// 如果总数据的条数大于需要展示的数据
max = treePageSize
} else {
// 否则
max = this.supList.length
}
// 判断是否有搜索
if (this.valueData) {
this.allDataZ.forEach((item, index) => {
if (index < max) { // 当data数组的下标小于max时
newData.push(item)
}
})
} else {
this.supList.forEach((item, index) => {
if (index < max) { // 当data数组的下标小于max时
newData.push(item)
}
})
}
this.frontDataZSupplier= newData // 将新增的数据赋值到要显示的数组中
}
}
}
Vue页面:将输入框中的内容获取到去后端进行模糊查询,然后将查询的数据赋值给下拉框
/**
* 获取到输入框中的内容
* */
supValue(value) {
if (value) {
// BillModalMixin.js中的方法去后端进行查询数据
this.getSupplier(value);
}
},
js:
methods:{
/**
* 模糊查询去后端查询供应商集合数据
* */
getSupplier(value){
let parms ={
supplierName:value
}
getAction('/supplier/getSupplier',parms).then((res) => {
if (true) {
this.supList=res // 所有数据
this.frontDataZSupplier = res.slice(0,30) // 滑动加载的数据(30条)
}
})
},
}