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
- 20 by default
- Scroll to the bottom and load another 20 or remaining data
- At the same time, it supports search (the data that meets the search conditions should also support rolling loading)
- Whether the data is loaded by scrolling or searching, it is loaded only once without repeated loading
- 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