Element 穿梭框性能优化

本文转载自微信公众号「微医大前端技术」,梭框作者陈建波。优化转载本文请联系微医大前端技术公众号。梭框

element 穿梭框性能优化

背景

穿梭框处理大数据量时,优化由于渲染的 DOM 节点过多,造成页面卡顿的梭框问题。在尽量不改变组件原有逻辑的优化前提下,进行优化。梭框

解决思路

懒加载 - InfiniteScroll 组件

先从 packages/transfer 中将原组件拷出(或者改源码重新打包维护私有库使用

v-infinite-scroll="pageDown" :infinite-scroll-immediate="false" 

添加到

<el-checkbox-group         v-show="!hasNoMatch && data.length > 0"         v-model="checked"         :size="size"         :class="{  is-filterable: filterable }"         class="el-transfer-panel__list"         v-infinite-scroll="pageDown"         :infinite-scroll-immediate="false"       >         <el-checkbox           class="el-transfer-panel__item"           :label="item[keyProp]"           :disabled="item[disabledProp]"           :key="item[keyProp]"           v-for="item in filteredData">             <option-content :option="item"></option-content>         </el-checkbox> </el-checkbox-group> 

在data中定义pageSize: 20 用来表示每页数据个数showData: [] 仅用来展示使用,优化替换上述代码中实际需要操作的梭框数据 filteredData

v-for="item in showData"> 

同时在watch中相应的处理

data (data) {      const checked = [];     this.showData = data.slice(0, this.pageSize);     const filteredDataKeys = this.filteredData.map(     (item) => item[this.keyProp]     );     this.checked.forEach((item) => {      if (filteredDataKeys.indexOf(item) > -1) {          checked.push(item);     }     });     this.checkChangeByUser = false;     this.checked = checked; }, filteredData (filteredData) {      this.showData = filteredData.slice(0, this.pageSize);  } 

初始化展示数量随意这里取 20。

最后添加滚动到底部时调用的优化方法

pageDown () {      const l = this.showData.length;     const totalLength = this.filteredData.length     l < totalLength &&      (this.showData = this.filteredData.slice(0, l + this.pageSize > totalLength ?     totalLength : l + this.pageSize)); }, 

往下滚动的时候 展示的数据长度增加 20(数量随意), 超出时展示最大长度。

由此基本解决大数据量操作卡顿的源码库梭框问题。由于展示和逻辑层分开,优化组件的梭框所有操作逻辑无须修改,最小程度减少差异。优化

新问题

手动滚动到列表末端,梭框再进行搜索操作依然存在卡顿问题。

进阶

在滚动过程中,实际上顶端的数据依旧无法看见,该数据不展示,对用户体验也没有影响, 所以只需展示当前页的 20 条数据。我们为el-checkbox-group添加一个 ref=scrollContainer 以便操作滚动条,

在data中定义当前页数 curIndex: 1

并对 pageDown 方法进行修改

pageDown () {    const totalLength = this.filteredData.length   if((this.curIndex*this.pageSize) < totalLength){      this.curIndex ++     const targetLength = this.curIndex * this.pageSize      const endPoint = targetLength > totalLength ? totalLength : targetLength     const startPoint = endPoint - this.pageSize  > 0 ? endPoint - this.pageSize : 0     this.showData = this.filteredData.slice(startPoint, endPoint);     this.$refs.scrollContainer.$el.scrollTop = "1px" //滚动条到最上端,衔接下一页,为 0 可能会触发边界问题   } } 

为此我们还需要添加向上翻页的服务器托管方法 InfiniteScroll 指令 只提供向下滚动,我们可以拓展该指令亦可自行添加上滑滚动监听

mounted(){          this.$refs.scrollContainer.$el.addEventListener(scroll, this.pageUp)     },     beforeDestroy(){          this.$refs.scrollContainer.$el.removeEventListener(scroll, this.pageUp)     }, 

注册pageUp 方法

pageUp(e){        if(e.target.scrollTop ===0 && this.curIndex>1){          this.curIndex --         const endPoint = this.curIndex * this.pageSize          const startPoint = (this.curIndex-1)* this.pageSize          this.showData = this.filteredData.slice(startPoint, endPoint);         const el = this.$refs.scrollContainer.$el         el.scrollTop = el.scrollHeight - el.clientHeight - 1 // 滚动到最底部,衔接上一页, -1 防止边界问题。       }     }, 

当进行数据操作的时候,页面内容变化,滚动条也会随之变化,为防止不能预知的翻页,数据改变时,重置滚动条和当前页码。

initScroll(){          this.curIndex = 1         this.$refs.scrollContainer.$el.scrollTop = 0     }, 

同时地,在watch中相应时候执行 initScroll

data(){        ...       this.initScroll()       ...   },   filteredData (filteredData) {      ...     this.initScroll()   } 

至此大数据量的穿梭框,性能大为改善。

人工智能
上一篇:4、club娱乐
下一篇:最后提醒我们,域名到期后要及时更新域名,否则可能会丢掉域名,每次抢先注册都不会成功。