Element中select多數據加載優化的實現

場景

近期著手開發基於ElementUI的後臺管理系統,偶然間發現「el-select」下拉選擇時候遇到一個問題,當渲染下拉選項的「options」的數據量過多時「本項目中的數據條目已過萬」,就會出現下拉選擇器卡頓的情況,尤其是在模糊匹配過濾的情況下,顯得十分的卡頓。初始化選擇器的時候,也會點擊無反應,有時候需要點擊多次才可出現「dialog」彈窗(本次下拉篩選在彈窗中實現)。 翻閱多篇博客筆記之後,最終找到一個可以解決問題的方案,現將此次優化方案記錄成為筆記,以便於日後遇到類似問題的時候便於查閱。

註:基於select的下拉篩選,通過自定義事件來實現模糊搜索匹配。

一共兩種方案:

  • 一是獲取所有數據,通過輸入的關鍵字自己對獲取的數據進行過濾處理;
  • 二是通過輸入的關鍵字來動態請求後臺接口,通過接口返回的數據來動態渲染下拉選項;

代碼實現

Vue組件實例

<template>
  <div class="app">
    <el-dialog title="標題" :visible.sync="relatedOpen" :append-to-body="true" width="500px">
      <el-row :gutter="16">
        <el-col :span="20">
          <el-select
            v-model="value"
            filterable
            clearable
            style="width:100%"
            placeholder="請選擇"
            :loading="searchLoad"
            :filter-method="filterMethod"
            v-el-select-loadmore="loadMore(rangeNumber)"
            @visible-change="visibleChange"
          >
            <el-option v-for="item in options.slice(0, rangeNumber)" :key="item.key" :label="item.value" :value="item.key"></el-option>
          </el-select>
        </el-col>
        <el-col :span="4">
          <el-button type="primary" @click="submit">確定</el-button>
        </el-col>
      </el-row>
    </el-dialog>
  </div>
</template>
  • 「v-el-select-loadmore」為自定義指令封裝的數據加載指令,是為瞭解決和優化elementUI下拉選擇器加載數據過多出現卡頓問題的。
  • 「filter-method」是下拉選擇器的一個自定義屬性,可以監聽輸入的變量,從而依據變量來實現數據的動態獲取;
  // 自定義指令
  directives: {
    "el-select-loadmore": (el, binding) => {
      // 獲取element UI定義好的scroll元素
      const SELECTWRAP_ROM = el.querySelector(".el-select-dropdown .el-select-dropdown__wrap");
      if (SELECTWRAP_ROM) {
    // 添加scroll事件
        SELECTWRAP_ROM.addEventListener("scroll", function() {
      // 判斷滾動
          const condition = this.scrollHeight - this.scrollTop <= this.clientHeight;
          condition && binding.value();
        });
      }
    }
  }

相應的數據函數

export default {
  data() {
    return {
      relatedOpen: false,
      options: [] /* 選擇下拉框的值 */,
      courseList: [],
      rangeNumber: 10,
      searchLoad: false /* 下拉框的loading狀態 */,
      value: "",
      timer: null
    };
  },
  created() {
    this.getOptions();
  },
  methods: {
    // 按需加載
    loadMore(n) {
      return () => (this.rangeNumber += 5);
    },
    // 過濾課件
    filterMethod(query) {
      if (this.timer != null) clearTimeout(this.timer);
      !this.searchLoad && (this.searchLoad = true);
      this.timer = setTimeout(() => {
        this.options = !!query ? this.courseList.filter(el => el.value.toLowerCase().includes(query.toLowerCase())) : this.courseList;
        clearTimeout(this.timer);
        this.searchLoad = false;
        this.rangeNumber = 10;
        this.timer = null;
      }, 500);
    },
    // 監聽select下拉框的顯示和隱藏
    visibleChange(flag) {
      // 顯示時初始化列表
      flag && this.filterMethod("");
      // 初始化默認值
      this.rangeNumber = 10;
    },
    // 獲取選項
    async getOptions() {
      await searchCourseware().then(res => {
        let list = res.data || [];
        // 默認展示的數據
        this.options = list;
        // 原始數據
        this.courseList = list;
      });
    }
  }
}

註:

  • 定時器作用是防止輸入篩選的關鍵字太過頻繁,從而造成數據響應不及時;因為本次是一次性獲取瞭全部的數據,所以這裡隻是用做渲染加載數據;
  • 選擇器的事件函數主要是用來初始化“獲取焦點”和“失去焦點”時處理默認展示數據用的,若是獲取的網絡請求,此處需要做“函數截流”處理;目的是減少接口請求次數。

總結:

換瞭新的工作環境,現開始著手做後臺管理系統,或多或少會遇到各種各樣的問題。一如即往,會在筆記中記錄開發中遇到的問題。好記性不如爛筆頭,希望現在埋下種子,等到來年秋天的時候會收獲🍒果實。JY

到此這篇關於Element中select多數據加載優化的實現的文章就介紹到這瞭,更多相關Element select多數據加載內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: