A brief discussion on the solution to excessive data in ElementUI el-select

A brief discussion on the solution to excessive data in ElementUI el-select

1. Scenario Description

I don’t know if you have had this experience before. There are many options in the drop-down box, tens of thousands of options or even more. At this time, if you put all the data into the drop-down box and render it, the browser will freeze and the experience will be particularly bad.

Some users may say that element-ui's select has a remote-method that supports remote search. Can't we just ask the server to support it? Of course, this is a solution. But sometimes this method may not be applicable

(1) Sometimes the server-side data is returned to us after calculation, and the return may not be very fast, so the experience is not very good. (2) Sometimes there may be only a few thousand pieces of data, and it is not appropriate to render all of them. It is not very good to keep the interface down. (3) Can it be solved only by the front-end? If it can be solved, wouldn’t it reduce the work and pressure on the server?

2. Solution

1) Segmented loading: The drop-down items are not loaded. When you click the drop-down box, they are loaded. At this time, all the options are loaded. This situation is only applicable to slow loading. You need to click to load before you can drop down the options. The experience is average.
2) Tip: element-ui's select has a filter-method method, which we can use to filter the drop-down items. Suppose we have a drop-down box to select the user

<el-select
  v-model="userId"
  filterable
  :filter-method="userFilter"
  clearable>
  <el-option
    v-for="item in userList"
    :key="item.userId"
    :label="item.username"
    :value="item.userId"
  ></el-option>
</el-select>
userFilter(query = '') {
  let arr = this.allUserList.filter((item) => {
    return item.username.includes(query) || item.userId.includes(query)
  })
  if (arr.length > 50) {
    this.userList = arr.slice(0, 50)
  } else {
    this.userList = arr
  }
},
getUserWhiteList() {
  HttpRequest.post("/api/admin/community/getUserWhiteList").then(
    response => {
      this.allUserList = response.data.list;
      this.userFilter()
    }
  );
},

As shown above, we get the user list from the background. After our own filtering, we only render 50 data at a time. No matter how much data there is, it supports a variable for us and takes up memory. Of course, the more data there is, the slower the array traversal will be, but this has little impact.
We can not only filter names, but also optimize any of the items we set: We can also optimize the above code appropriately. We will stop traversing only when we find that the length of the array exceeds 50 items.

Solution for el-select component with too many options

Business Scenario

When using the el-select component, if there are too many options, there will be disadvantages:

The page renders a large number of el-option nodes, which will cause the page to freeze or even freeze, resulting in a very poor user experience.
There are too many items to choose from, making it difficult to find.

The scenario I encountered this time was a situation where the number of options was 6-9 thousand.

Solution

Take out the small option (renderOption) of the fixed item from the total options for page rendering, using the
The filter-method method performs search filtering and updates renderOption with the filter results during the search.

Code implementation Below is the component encapsulation of Vue

<template>
    <el-select
        class="yt-select"
        v-model="currValue"
        filterable
        v-bind="$attrs"
        :filter-method="userFilter"
        :disabled="disabled"
        :clearable="clearable"
        @change="change"
    >
        <el-option
            v-for="option in renderOption"
            :key="option.value"
            :value="option.value"
            :label="option.label"
        >{{ option.label }}</el-option>
    </el-select>
</template>

<script>

export default {
    name: 'easy-select',
    props: {
        value: {
            type: [String, Number],
            default: ''
        },
        max: {
            type: Number,
            default: 30
        },
        disabled:
            type: Boolean,
            default: false
        },
        clearable: {
            type: Boolean,
            default: true
        },
        options:
            type: Array,
            default: () => []
        }
    },
    data () {
        return {
            renderOption: []
        }
    },
    computed: {
        currValue: {
            get () {
                return this.value || ''
            },
            set (value) {
                this.$emit('input', value)
            }
        }
    },
    watch:
        value () {
            this.addValueOptions()
        },
        options:
            handler (V) {
                this.init()
            },
            deep: true
        }
    },
    created () {
        this.init()
    },
    methods: {
        async init () {
            this.userFilter()
            this.addValueOptions()
        },
        addValueOptions () {
            if (this.currValue) {
                let target = this.options.find((item) => { // Find the current item from the big option return item.value === this.currValue
                })
                if (target) { // Compare the current item with the small option, if not, add if (this.renderOption.every(item => item.value !== target.value)) {
                        this.renderOption.unshift(target)
                    }
                }
            }
        },
        addFilterOptions (label) {
         // Each time you search for an input, if there is an exact match, make sure that the item is in renderOption let target = this.options.find((item) => { // Find the current item from the big option return item.label === label
            })
            if (target) { // Compare the current item with the small option, if not, add if (this.renderOption.every(item => item.label !== target.label)) {
                    this.renderOption.unshift(target)
                }
            }
        },
        userFilter (query = '') {
            let arr = this.options.filter((item) => {
                return item.label.includes(query) || item.value.includes(query)
            })
            if (arr.length > this.max) {
                this.renderOption = arr.slice(0, this.max)
                this.addFilterOptions(query)
            } else {
                this.renderOption = arr
            }
        },
        change (value) {
            this.$emit('change', value)
            if (!value) { // Single-select clear-optons initialize this.userFilter()
            }
        }
    }
}
</script>

Precautions

  • When initializing and changing the value, you need to find the specific item corresponding to the value and add it to renderOptions
  • When searching, it is possible that none of the n data items filtered out contain the specific item the user is looking for. Therefore, an accurate search is required when filtering, and the matching items are placed in the renderOptions header.

This is the end of this article about the solution to the problem of too much data in ElementUI el-select. For more information about the problem of too much data in ElementUI el-select, please search for previous articles on 123WORDPRESS.COM or continue to browse the related articles below. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Solve the triggering problem of change event when vue elementUI uses el-select
  • Solve the problem that the default value cannot be deleted when using the drop-down multiple-select box el-select in element-ui
  • Detailed explanation of getting additional parameters for the drop-down box el-select of Vue + Element-ui
  • Element-ui remote search component el-select componentized implementation code in the project
  • Detailed explanation of the default selection issue of el-select in element-ui
  • The el-select selector in vue2.0 element-ui cannot display the selected content (solution)

<<:  How to install ROS Noetic in Ubuntu 20.04

>>:  Solve the problem of MySQL server actively disconnecting when there is no operation timeout

Recommend

Summary of @ usage in CSS (with examples and explanations)

An at-rule is a declaration that provides instruc...

12 Javascript table controls (DataGrid) are sorted out

When the DataSource property of a DataGrid control...

vue-cli configuration uses Vuex's full process record

Table of contents Preface Installation and Usage ...

Detailed explanation of the difference between uniapp and vue

Table of contents 1. Simple page example 2.uni-ap...

Vue implements dynamic routing details

Table of contents 1. Front-end control 1. In the ...

25 CSS frameworks, tools, software and templates shared

Sprite Cow download CSS Lint download Prefixr dow...

Specific use of Linux dirname command

01. Command Overview dirname - strip non-director...

Detailed explanation of Vue project packaging

Table of contents 1. Related configuration Case 1...

A brief discussion on the design of Tomcat multi-layer container

Table of contents Container Hierarchy The process...

MySQL advanced learning index advantages and disadvantages and rules of use

1. Advantages and Disadvantages of Indexes Advant...

JavaScript to achieve uniform animation effect

This article example shares the specific code for...

How to use flat style to design websites

The essence of a flat website structure is simpli...

Use href in html to pop up a file download dialog box when clicking a link

I learned a new trick today. I didn’t know it befo...

Vue implements real-time refresh of the time display in the upper right corner

This article example shares the specific code of ...