溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么解決Element的穿梭框數據量大時點擊全選卡頓問題

發布時間:2021-11-01 09:12:30 來源:億速云 閱讀:312 作者:iii 欄目:開發技術

本篇內容介紹了“怎么解決Element的穿梭框數據量大時點擊全選卡頓問題”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

現象:我們渲染了9999條數據,由于transfer組件會一次性渲染所有數據,所以一次性渲染這么多,卡個幾十秒很正常好吧。所以懶加載或者分頁是基本操作,方案二是分頁操作。

懶加載的方式可以用EUI的無限滾動

即便我們做了懶加載之后,點擊全選依舊是卡頓6秒以上,所以方案一解決的是:即便做了懶加載或者分頁操作后,用戶點擊分頁,依舊會卡頓幾秒的情況。

這個是因為transfer的源碼中‘全選判斷'代碼性能差的原因,方案一就是修改transfer的源碼。

我提交了一個pr,地址是: hhttps://github.com/ElemeFE/element/pull/20282

怎么解決Element的穿梭框數據量大時點擊全選卡頓問題

方案一:復制EUI的transfer組件,然后進行修改,再引入項目目錄

EUI的transfer組件目錄路徑:node_modules\element-ui\packages\transfer,復制文件夾,然后放入vue項目路徑的

怎么解決Element的穿梭框數據量大時點擊全選卡頓問題

在調用EUI的transfer的地方引入公共的組件transfer,

<template>
  <Transfer v-model="value" :data="data"></Transfer>
</template>

<script>
import Transfer from '../common/transfer'
export default {
  components:{
    Transfer:Transfer
  },
 //省略
</script>

開始修改transfer代碼:

打開src/common\transfer\src\transfer-panel.vue的組件,

找到updateAllChecked函數,updateAllChecked函數作用是:我們點擊一個item就需要判斷,看代碼注釋。

updateAllChecked() {
      /*
        源碼
        this.checkableData是對象數組  我們需要的是每個對象中的key
        所以checkableDataKeys保存著對象的key的數組 含義是'可通過點擊進行選擇的item項'的集合
      */
      let start = new Date().getTime();
      const checkableDataKeys = this.checkableData.map(
        item => item[this.keyProp]
      );

      this.allChecked =
        checkableDataKeys.length > 0 &&
      /*
        從2.4.0到現在都沒改變 誒,不得不說開發團隊是真的忙啊
        this.checked保存著'用戶通過點擊item選中的item數組'
        如果this.checked存在著checkableDataKeys的每一項的話,那么allChecked就是true,但凡有一項不存在就為false。allChecked代表是否全部選中了。
        這里的時間復雜度是n^2,狠垃圾
      */
      checkableDataKeys.every(item => this.checked.indexOf(item) > -1);
      console.log("updateAllCheckedEnd", new Date().getTime() - start);

    },

來看源碼的耗時:

怎么解決Element的穿梭框數據量大時點擊全選卡頓問題

然后我們開始重寫updateAllChecked函數:

updateAllChecked() {
      /*
        修改
        這里就是高效數組中含有另一個數組的元素的算法
        構建元素對象
      */
      let start = new Date().getTime();
      let checkableDataKeys = this.checkableData.map((item) => {
        let keyProps = {};
        keyProps[item[this.keyProp]] = true;
        return keyProps;
      });
      // 通過對象的k-v對應,n(1)的方式尋找數組中是否存在某元素
      this.allChecked =
        checkableDataKeys.length > 0 &&
        this.checked.length > 0 &&
        this.checked.every((item) => checkableDataKeys[item]);
      // 上面被注釋的源碼是最耗時的,所有一直看耗時就可以了
      console.log("updateAllCheckedEnd", new Date().getTime() - start);
    },

這樣性能就高好多了,其實就是基本的前端算法題,目測EUI的開發者是因為懶才不寫的。

來看修改代碼后的耗時:

怎么解決Element的穿梭框數據量大時點擊全選卡頓問題

明顯快多了。

接下來是文件:\src\common\transfer\src\main.vue,找到addToRight函數

addToRight() {
      let currentValue = this.value.slice();
      const itemsToBeMoved = [];
      const key = this.props.key;
      let start = new Date().getTime();
      // 此處套了兩層循環,耗時長
      this.data.forEach((item) => {
        const itemKey = item[key];
        if (
          this.leftChecked.indexOf(itemKey) > -1 &&
          this.value.indexOf(itemKey) === -1
        ) {
          itemsToBeMoved.push(itemKey);
        }
      });
      console.log("addToRightEnd", new Date().getTime() - start);

      currentValue =
        this.targetOrder === "unshift"
          ? itemsToBeMoved.concat(currentValue)
          : currentValue.concat(itemsToBeMoved);
      this.$emit("input", currentValue);
      this.$emit("change", currentValue, "right", this.leftChecked);
    },

移動選中的耗時:

怎么解決Element的穿梭框數據量大時點擊全選卡頓問題

修改addToRight函數,

addToRight() {
      let start = new Date().getTime();
      let currentValue = this.value.slice();
      const itemsToBeMoved = [];
      const key = this.props.key;

      // 修改
      let leftCheckedKeyPropsObj = {};
      this.leftChecked.forEach((item, index) => {
        leftCheckedKeyPropsObj[item] = true;
      });

      let valueKeyPropsObj = {};
      this.value.forEach((item, index) => {
        valueKeyPropsObj[item] = true;
      });
      this.data.forEach((item) => {
        const itemKey = item[key];
        if ( leftCheckedKeyPropsObj[itemKey] && !valueKeyPropsObj[itemKey] ) {
          itemsToBeMoved.push(itemKey);
        }
      });
      console.log("addToRightEnd", new Date().getTime() - start);

      currentValue =
        this.targetOrder === "unshift"
          ? itemsToBeMoved.concat(currentValue)
          : currentValue.concat(itemsToBeMoved);
      this.$emit("input", currentValue);
      this.$emit("change", currentValue, "right", this.leftChecked);
    },

移動選中耗時:

怎么解決Element的穿梭框數據量大時點擊全選卡頓問題

耗時明顯減少了,這方案的前提就是懶加載或者分頁,我試了一下10w的數據量,依舊是不錯的。

方案二:分頁操作

分析

checkBox-group有個check數組(用來記錄已經選中的item數組)和renderItem數組(實際渲染的item,由于是分頁,所有不會渲染所有),如果`check數組`中有`renderItem數組`的一項,那么該項就會被標記為已選,否則是未選。實現原理就是單純的check數組和renderItem數組進行比較。

當用戶點擊全選的時候,check數組變成上萬條數據的數組,此時我們渲染了100條數據,那么就要進行10000x100級別的循環,這就是耗時的原因所在。

其實,頁面只渲染了100條數據,我們沒必要將上萬條數據一次性放入check數組中,我們只需要把這100條數組放入check數組,顯示這100條數據為已選即可。當頁面渲染了更多數據的同時,將新增的數據添加進check數組即可。這樣性能大大提升。

方案

我采用的方案如下:

1.只顯示100條數據。

2.下拉顯示下100條數據,上拉顯示上100條數據。

3.當下拉或者上拉增加渲染數據的同時,把新增數據添加進check數組。

這些只是大致思路,我已經實現了。還有很多細節要處理,想要完善,還得利用對象的鍵值對實現刪除等。

“怎么解決Element的穿梭框數據量大時點擊全選卡頓問題”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女