制作网站的心得,下载安装百度一下,中国建设银行网站查余额,网站建设的目的和意义在准备上线的后台管理系统中#xff0c;我们发现有两个下拉框#xff08;select#xff09;#xff0c;其选项数据量超过 1 万条#xff0c;而在测试环境中这些数据量只有几百条。这导致在页面加载时#xff0c;浏览器性能出现瓶颈#xff0c;页面卡顿甚至崩溃。 想了一… 在准备上线的后台管理系统中我们发现有两个下拉框select其选项数据量超过 1 万条而在测试环境中这些数据量只有几百条。这导致在页面加载时浏览器性能出现瓶颈页面卡顿甚至崩溃。 想了一下如果接口支持搜索和分页那直接通过上拉加载就可以了。但后端不太愿意改。行吧前端搞也是可以的。
这个故事还有个后续 过了一周上线后发现有一个下拉框的数据有30w加载都加载不出来哈哈哈哈接口直接超时报错了所以又cuocuocuo改了一遍最后改成了
接口翻页请求前端使用自定义指令实现上拉加载更多搜索直接走的后端接口
方案
通过一顿搜索加联想总结了3种方法以下方法都需要支持开启filterable支持搜索。
标题具体问题方案1只展示前100条数据这个的话配合filter-method每次只返回前100条数据。限制展示的条数可能不全搜索需要多搜索点内容方案2分页方式通过指令实现上拉加载不断上拉数据展示数据。仅过滤加载出来的数据需要配合filterMethod过滤数据方案3options列表采用虚拟列表实现。成本高需要引入虚拟列表组件或者自己手写。经掘友指点发现element-plus提供了对应的实现如果是plus则可以直接使用select-v2。
方案一、 filterMethod直接过滤数据量
templateel-select v-modelvalue clearable filterable :filter-methodfilterMethodel-optionv-for(item, index) in options.slice(0, 100):keyindex:labelitem.label:valueitem.value/el-option/el-select/templateexport default {name: Demo,data() {return {options: [],value: }},beforeMount() {this.getList();},methods: {// 模拟获取大量数据getList() {for (let i 0; i 25000; i) {this.options.push({label: 选择i,value:选择i});} },filterMethod(val) {console.log(filterMethod, val);this.options this.options.filter(item item.value.indexOf(val) -1).slice(0, 100);},visibleChange() {console.log(visibleChange);}}
}方案二、自定义滚动指令实现翻页加载
写自定义滚动指令options列表滚动到底部后再加载下一页。但这时候筛选出来的是已经滚动出来的值。
这里如果直接使用filterable来搜索搜索出来的内容是已经滑动出来的内容。如果想筛选全部的就需要重写filterMethod方法来自定义过滤功能。可以根据情况选择是否要重写filterMethod。 templatediv classdashboard-editor-containerel-select v-modelvalue clearablefilterable v-el-select-loadmoreloadMore:filter-methodfilterMethodel-optionv-for(item, index) in options:keyindex:labelitem.label:valueitem.value/el-option/el-select/div
/template
script
export default {name: Demo,data() {return {options: [],value: ,pageNo: 0}},beforeMount() {this.getList();},methods: {// 模拟获取大量数据getList() {const data [];for (let i 0; i 25000; i) {data.push({label: 选择i,value:选择i});}this.allData data;this.data data;this.getPageList()},getPageList(pageSize 10) {this.pageNo;const list this.data.slice(0, pageSize * (this.pageNo));this.options list;},loadMore() {this.getPageList();},filterMethod(val) {this.data val ? this.allData.filter(item item.label.indexOf(val) -1) : this.allData;this.getPageList();}},directives:{el-select-loadmore:(el, binding) {// 获取element-ui定义好的scroll父元素const wrapEl el.querySelector(.el-select-dropdown .el-select-dropdown__wrap);if(wrapEl){wrapEl.addEventListener(scroll, function () {/*** scrollHeight 获取元素内容高度(只读)* scrollTop 获取或者设置元素的偏移值,* 常用于:计算滚动条的位置, 当一个元素的容器没有产生垂直方向的滚动条, 那它的scrollTop的值默认为0.* clientHeight 读取元素的可见高度(只读)* 如果元素滚动到底, 下面等式返回true, 没有则返回false:* ele.scrollHeight - ele.scrollTop ele.clientHeight;*/if (this.scrollTop this.clientHeight this.scrollHeight) {// binding的value就是绑定的loadmore函数binding.value();}});}},},
}
/script
/script方案三、虚拟列表
引入社区的vue-virtual-scroll-list 支持虚拟列表。这里想的自己再实现一遍虚拟列表后续再写吧。
另外element-plus提供了对应的实现如果是使用的是plus则可以直接使用 select-v2组件。
templatediv classdashboard-editor-containerel-select v-modelvalue clearablefilterable virtual-listclassliststyleheight: 360px; overflow-y: auto;:data-keyvalue:data-sourcesdata:data-componentitem:estimate-size50//el-select/div
/template
script
import VirtualList from vue-virtual-scroll-list;
import Item from ./item;
export default {name: Demo,components: {VirtualList, Item},data() {return {options: [],data: [],value: ,pageNo: 0,item: Item,}},beforeMount() {this.getList();},methods: {// 模拟获取大量数据getList() {const data [];for (let i 0; i 25000; i) {data.push({label: 选择i,value:选择i});}this.allData data;this.data data;this.getPageList()},getPageList(pageSize 10) {this.pageNo;const list this.data.slice(0, pageSize * (this.pageNo));this.options list;},loadMore() {this.getPageList();}}
}
/script// item组件
templateel-option :labelsource.label :valuesource.value/el-option
/templatescriptexport default {name: item,props: {source: {type: Object,default() {return {}}}}}/scriptstyle scoped/style 总结
最后我们项目中使用的虚拟列表为啥因为忽然发现组件库支持select是虚拟列表那就直接使用这个啦。
最后的最后
没有用虚拟列表因为接口数据量过大你见过返回30w的接口吗。。后端接口改成分页前端支持自定义指令上拉加载引用的参数增加了remote、remote-method设置为远端的方法。
templatediv classdashboard-editor-containerel-select v-modelvalue clearablefilterable v-el-select-loadmoreloadMoreremote:remote-methodremoteMethodel-optionv-for(item, index) in options:keyindex:labelitem.label:valueitem.value/el-option/el-select/div
/template参考文章
解决 Element-ui中 选择器Select因options 数据量大导致渲染慢、页面卡顿的问题对el-select进行二次封装解决数据量过大造成页面卡顿问题