700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > elementUi——Cascader 级联选择器渲染数据很多时卡顿问题解决

elementUi——Cascader 级联选择器渲染数据很多时卡顿问题解决

时间:2022-09-27 23:03:14

相关推荐

elementUi——Cascader 级联选择器渲染数据很多时卡顿问题解决

上周在做后台管理系统时,有用到了级联选择器,这个级联选择器主要用于分组展示的数据,比如省市区三级两级联动等。

elementUi中的cascader级联选择器官网链接:/#/zh-CN/component/cascader

使用方法也是比较的简单,主要有以下几个参数:

一个最基本的级联选择器代码如下:

<el-cascader v-model="value" :options="options" @change="handleChange"></el-cascader>

参数如下:

v-model:绑定的值,单面板时是个一维数组,多面板时是个多维数组options:就是选择器下拉面板中需要展示的内容,是个数组,里面的结构是:value/label/children三项,children里面同理如果要监听级联选择器中选值的方法,则需要使用change事件。

我需要实现的是:多选并且可以检索筛选下拉面板内容的功能,而且是双面板的结构。

我刚开始是用了级联选择器,但是由于后端给我的数据有2000+数据,导致面板在进行搜索筛选时,页面卡顿。这个效果跟之前的一篇文章《elementUi——select组件渲染数据很多时卡顿问题解决》提到的一样。因为数据是同一个接口返回的。

我考虑过很多方法:

select组件有个远程搜索,cascader是否可以用(失败)

select组件由于数据量过多,导致页面卡顿,最终的解决方案就是:使用了select组件的远程搜索功能,就是刚开始选择组件的时候,下拉面板是没有数据的,监听到输入框中输入内容后,再根据输入值筛选内容,将筛选后的内容展示在面板中。

在查看cascader组件的官网解释后,只发现了可搜索功能,并没有远程搜索功能。

可搜索功能与远程搜索功能是不一样的,可搜索功能是在组件渲染时,就将全部的内容渲染出来。所以并不能完全实现远程搜索的功能。

动态加载数据(失败)

动态加载数据的思路是好的,它主要适用于多级面板的情况,而且二级及后面的面板数据量足够大的情况。

因为这里的动态加载,是加载的后面面板的数据,而非一级面板的数据。

而我现在的情况是,一级面板的数据有2000+数据,二级面板只有2项内容,所以并不符合使用动态加载数据的情况,在实验后,也发现对数据卡顿并无帮助。

分页获取数据(失败)

当数据量过大时,通常我们会想到分页获取数据,后端一次性将2000+数据全部返回给我,我分页去获取。百度后发现有大佬已经实现此功能:

参考大神链接:

分页获取数据解决select组件数据量大卡顿问题:/ZYS10000/article/details/111822862

分页获取数据主要难点是:** 什么时候分页获取?如何触发分页?以及filter-method方法的使用**

刚开始拿到数据时,通过数组的slice方法,只截取前几十条数据展示,下拉触底后加载下一个几十条的数据,一次类推。

如果判断是否下拉触底???

大佬的处理方法就是:通过一个vue的自定义指令,判断下拉框的高度与下拉框中滚动条的高度来判断是否滚动到底,滚动到底则加载数据。

我通过此方法,的确能减免数据量大导致的卡顿问题,但是新的问题也出现了:因为数据量大,用户在使用时,更倾向于使用搜索的方式,此时,如果需要检索的数据在第三页,在没有触底加载更多数据的时候,通过输入关键字筛选,是无法检索到对应的数据的。

此方法也是不可行的。

异步加载数据(失败)

看到有个钩子函数,是筛选之前的钩子。想到可以开始给面板的数据options赋值为空,然后通过输入关键字后,筛选到对应的内容后,赋值给options,但是经过实验发现,筛选只能是从已有的options中筛选,通过自定义的数据中筛选是无法实现的。

自己写一个类似的级联选择器(成功)

用到的组件如下:

<div><el-tag v-for="(tag,tagIndex) in dailiOptions" :key="tagIndex" :closable="!disabled" color="#f4f4f5" v-on:close="closeDailiTag(tagIndex)">{{tag.label}}/层级{{tag.level}}</el-tag></div><div class="dailiCls" style="display:flex;flex-direction:column;position:relative;margin-top:10px;" v-if="!disabled"><el-input v-model="searchWord" placeholder="请输入品牌关键词" clearable size="mini" :disabled="disabled" v-on:input="searchWordChange" v-on:focus="inputFocus" v-on:blur="inputBlur"><i slot="suffix" :class="choosePinpai==null&&!dailiFocusFlag?'el-icon-arrow-down':'el-icon-arrow-up'" v-on:click="flagClick"></i></el-input><div class="ppListCls" v-if="choosePinpai!=null||dailiFocusFlag"><div class="ppLeft"><p v-for="(p,pIndex) in agentBrandOptions" :key="pIndex" style="cursor:pointer;" v-on:click="selectPinpai(pIndex)" :class="choosePinpai==pIndex?'active':''">{{p.label}}</p></div><div class="ppRight" v-show="showGrapeFlag"><p v-on:click="selectGrape(2)" :class="chooseGrape==2?'active':''" style="cursor:pointer;">层级2</p><p v-on:click="selectGrape(3)" :class="chooseGrape==3?'active':''" style="cursor:pointer;">层级3</p></div></div></div>

input组件——监听组件内容的输入

通过setTimeout实现防抖,延迟500毫秒后,将根据input组件中输入的内容进行筛选。然后将筛选后的内容赋值给options

searchWordChange2(val) {setTimeout(() => {if (val) {this.xianhuoFocusFlag = true;this.showGrapeFlag2 = false;this.choosePinpai2 = null;var dailiOptions = this.pinPaiData.filter(a => {return a.label.toLowerCase().indexOf(val.toLowerCase()) > -1})this.tradeBrandOptions = dailiOptions;} else {this.tradeBrandOptions = this.pinPaiData;this.showGrapeFlag2 = false;this.choosePinpai2 = null;this.xianhuoFocusFlag = false;}}, 500)},

其他的都是一些小细节:

下拉框的显示与隐藏选中状态后样式的改变,通过动态绑定class的方式,选中状态后面有个是通过伪元素的方式来实现

……

关于选中后的√对号样式

p.active {color:#ff9900;position:relative;}p.active::after {display:block;position:absolute;right:4px;top:0;content:"√";color:#ff9900;}

最终效果完成,终于完成了!!!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。