select multi data loading optimization of ElementUI

「 🚀」 scene

Recently, I started to develop the background management system based on ElementUI. I accidentally found a problem in the "El select" drop-down selection. When the amount of data in the "options" of the rendering drop-down options is too large, "there are more than 10000 data items in this project" , the drop-down selector will be stuck, especially in the case of fuzzy matching filtering. When initializing the selector, it will also click no response. Sometimes it needs to click multiple times to appear the "dialog" pop-up window (this drop-down filtering is implemented in the pop-up window) After reading several blog notes, we finally found a solution to the problem. Now we record the optimization scheme into notes for easy reference in case of similar problems in the future.

「 📷」 Illustration

⚠️ Note: Based on the drop-down filter of select, fuzzy search matching is realized through user-defined events.

  • There are two schemes:

    • First, obtain all data and filter the obtained data through the entered keywords;
    • Second, dynamically request the background interface through the entered keywords, and dynamically render the drop-down options through the data returned by the interface;

「 🍵」 code implementation

  • 🌰 Vue component instance
<template>
  <div class="app">
    <el-dialog title="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="Please select"
            :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">determine</el-button>
        </el-col>
      </el-row>
    </el-dialog>
  </div>
</template>
  • 🚗 "v-el-select-loadmore" is a data loading instruction encapsulated by user-defined instructions to solve and optimize the problem of excessive loading data in the elementUI drop-down selector.
  • 🚴 "Filter method" is a user-defined attribute of the drop-down selector, which can listen to the input variables, so as to realize the dynamic acquisition of data according to the variables;
  // Custom instruction
  directives: {
    "el-select-loadmore": (el, binding) => {
      // Get the scroll element defined by the element UI
      const SELECTWRAP_ROM = el.querySelector(".el-select-dropdown .el-select-dropdown__wrap");
      if (SELECTWRAP_ROM) {
    // Add scroll event
        SELECTWRAP_ROM.addEventListener("scroll", function() {
      // Judge scrolling
          const condition = this.scrollHeight - this.scrollTop <= this.clientHeight;
          condition && binding.value();
        });
      }
    }
  }
  • Corresponding data function
export default {
  data() {
    return {
      relatedOpen: false,
      options: [] /* Select the value of the drop-down box */,
      courseList: [],
      rangeNumber: 10,
      searchLoad: false /* loading status of the drop-down box */,
      value: "",
      timer: null
    };
  },
  created() {
    this.getOptions();
  },
  methods: {
    // Load on demand
    loadMore(n) {
      return () => (this.rangeNumber += 5);
    },
    // Filtering courseware
    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);
    },
    // Monitor the display and hiding of the select drop-down box
    visibleChange(flag) {
      // Initialize list on display
      flag && this.filterMethod("");
      // Initialize defaults
      this.rangeNumber = 10;
    },
    // Get options
    async getOptions() {
      await searchCourseware().then(res => {
        let list = res.data || [];
        // Data displayed by default
        this.options = list;
        // raw data
        this.courseList = list;
      });
    }
  }
}

Note:

  • The timer is used to prevent too frequent input of filtered keywords, resulting in untimely data response; because all data is obtained at one time, it is only used for rendering and loading data here;
  • The event function of the selector is mainly used to process the default display data when initializing "get focus" and "lose focus". If the network request is obtained, the "function interception" process needs to be done here to reduce the number of interface requests.

「 🍎」 Summary:

With a new working environment, I now start to work on the background management system. I will encounter more or less various problems. As always, I will record the problems encountered in development in my notes. A good memory is not as good as a bad pen. I hope to plant seeds now and harvest them in the autumn of next year 🍒 Fruit. JY

Keywords: Javascript Vue.js elementUI

Added by awared on Sat, 25 Sep 2021 10:01:32 +0300