El select drop-down box lazy loading and search union processing + search anti shake processing

Problem description
An existing page is full of a large number of form elements. The first thing to know is vue about the update mechanism on the view. If an element changes in a component, the whole component will refresh and render. Therefore, putting a large number of form elements in one component will cause page jamming. If the drop-down box loads a large amount of data at one time, this phenomenon will be particularly obvious. Although it is helpful to split the form into multiple components, the effect will not be great. We must solve the root problem that the drop-down box loads a large number of elements at one time. Because the element itself does not lazy load the drop-down box (EL select) (it can also be combined with the infinite scroll of the element UI), we need to implement it manually.

demand

  1. 20 by default
  2. Scroll to the bottom and load another 20 or remaining data
  3. At the same time, it supports search (the data that meets the search conditions should also support rolling loading)
  4. Whether the data is loaded by scrolling or searching, it is loaded only once without repeated loading
  5. The search needs anti shake processing to avoid unnecessary search operations as much as possible

1, The user-defined instruction completes the function of rolling load

1. Step 1: bind the rolling event in the user-defined instruction to trigger the execution of the data loading method

 

directives: {
    "loadmmore": {
      bind (el, binding) {
        // Because El select will eventually be rendered as ul Li, we need to find the corresponding ul element node, because the bottom scroll bar is the ul
        const SELECTDOM = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap')
        // Bind the scroll bar scroll event for the corresponding ul
        SELECTDOM.addEventListener('scroll', function () {
          const condition = this.scrollHeight - this.scrollTop == this.clientHeight
          // Judge scroll to bottom
          if (condition) {
          // binding.value is the value bound by the user-defined instruction. Because the bound method is a method, this is a method call. After the instruction is triggered, the data is loaded
            binding.value()
          }
        })

      }
    }
  },

Using user-defined instructions, you can handle lazy loading of El select components that use instructions.
2. Step 2: method of loading data

props: {
    seleteOptions: {
      type: Array,
      default: function () {
        return []
      }
    }
  },
data () {
    return {
      seVal: '',
      
      initOption:[], // val sets that meet the filter criteria
      filterVal: '', // search criteria
      filterArray:[],  // All data that can be displayed (data that meets the search criteria & & newdata does not have)
      newData: [],  // Data being displayed or displayed
    }
},
mounted () {
    this.filterArray = [...this.seleteOptions]
    // Load once initially
    this.loadmore()
},
methods: {
    // Rolling load
    loadmore () {
      const oldArray = this.filterArray  // Preliminary data can be displayed
      const newArray = this.newData        // Displayed data
      let pushArray = []                 // New data

      // Exit the method directly when loading is complete
      if (newArray.length === oldArray.length) return

      // When there are less than 20 remaining to be loaded, all of them will be loaded
      if (newArray.length + 20 > oldArray.length) {
        pushArray = oldArray.slice(0)
        this.filterArray.splice(0)
      } else {
        pushArray = oldArray.slice(0,20)
        this.filterArray.splice(0,20)
      }
      // Data displayed after search
      this.newData = [...newArray, ...pushArray]
    },
}

Each time the loadmore method is executed, it will take 20 pieces or the remaining data from the preliminary data
3. Step 3: customize the search method

filterMethod (params) {
      // Record the search criteria
      this.filterVal = params

      // Search method
      let vals = []
      let filterArray = []
      this.seleteOptions.forEach((item, i) => {
        // Find qualified when there are search criteria
        if (params && item.label.includes(params)) {
          // Add all val values that match the search criteria
          vals.push(item.value)
          // Find data that meets the search criteria and does not appear in newData
          if(!this.newData.find(fin=>fin.value === item.value)){
           filterArray.push(item)
          }
        }else if(!params){  // When there is no search condition, get all data that does not appear in the remaining newData
          if(!this.newData.find(fin=>fin.value === item.value)){
           filterArray.push(item)
          }
        }
      })
      
      this.initOption = [...vals]
      this.filterArray = [...filterArray]

      this.loadmore()
      
    }

Because you want to combine search with lazy loading, you need to combine custom search methods with lazy loading data to do some logical processing.

4. Step 4: anti shake processing of} search

computed: {
    // Anti shake
    filterMethodThrottle(){
      var time = null
      return (param)=>{
        if(time){
          clearTimeout(time)
        }
        time = setTimeout(()=>{
          // Search method
            this.filterMethod(param)
            clearTimeout(time)
        },2000)
      }
    }
  }

Component use

<el-select v-model="seVal"
               filterable
               placeholder="Please select"
               v-loadmmore="loadmore"
               :filter-method="filterMethodThrottle">
      <el-option v-for="(item, i) in newData"
                 :label="item.label"
                 :value="item.value"
                 v-show="!filterVal || initOption.includes(item.value)"
                 :key="i + 'region2'">
      </el-option>
    </el-select>

 

Test data
Transfer the test data to the in props

 

[
	{
		label:'First item',
		value:'1'
	},...
]

 

problem

1, Use v-infinite-scroll

v-infinite-scroll is a user-defined instruction for scrolling and loading data of element, but it should be noted that this instruction needs to act directly on the scrollable parent element, just like the official example

1. First give El select a class name

 2. Let's look at the rendered dom node

 

However, it is worth noting that slots are set inside components such as the ement UI. The default slot can also be used to solve this problem

2, Anti shake and throttling

First of all, we only need to know what problems anti chattering and throttling mainly solve. Although their methods are different,

Anti shake can be simply understood as that in frequent operations, I only trigger the time when the interval reaches the specified value.

Throttling can be simply understood as that no matter how frequently you operate, I will trigger it according to my specified interval

In fact, every time an event is triggered, the method used for anti shake processing must also be executed once. It is just to encapsulate the logic code into the handle function, and then control the trigger frequency of the handle function. From this point of view, if the execution frequency of the control logic code block can be achieved, is it also a disguised anti shake processing?
1. Handling of rolling events

 2. Processing of search events
Because the search event cannot use the code limit to determine at which moment the event function should be executed, it is necessary to do anti shake processing and do anti shake for 2 seconds. In this way, if the user inputs word by word, the function will not be executed frequently every time the character is input. If it exceeds 2 seconds, it is considered that the user has completed the input and the event function will be executed

Conclusion

Reference: El select drop-down box lazy loading and search union processing + search anti shake processing_ Ignorant casual blog - CSDN blog_ El select Search

Keywords: Javascript Vue.js elementUI

Added by Codewarrior123 on Sat, 11 Dec 2021 11:34:02 +0200