A recent requirement is that when there are about 50000 pieces of data in the list, it is not allowed to be paged. If the page directly renders 50000 pieces of data, the page may get stuck on some low configuration computers. Based on this requirement, research and analyze the reasons for the front-end rendering jamming, and prepare to hand write a virtual list.
1. Implementation ideas
- Only a small amount of data is displayed in the list, such as 60 items
- When the list scrolls, you constantly insert and delete DOMS
- startIndex, endIndex, and constantly change this value to obtain the latest display list
- paddingTop and paddingBottom open the rolling area of the container
First, let's look at the performance of the page when 100000 lists are inserted directly.
2. Mode comparison
Situation 1
-
Directly render 50000 pieces of data
You can see that there is already a red part in the flame diagram, and dom rendering takes more than 5s
-
Effect before optimization
Situation II
-
Virtual list loading mode is adopted
Suppose there is a container with a height of 600px and the height of each list item is 30px, then we can calculate the total height of the scrolling container according to the length of the list, and we can also know the height of displaying 60 pieces of data. At this time, we can add a paddingBottom to the container to open the container to simulate the height that the page should scroll
this.paddingBottom = this.allHeight - this.scrollList.length * 30
The container also needs paddingTop to support the scrollTop when the data at the top of the container is removed
Finally, we need to listen to the rolling events of the container to constantly modify paddingTop, paddingBottom, startIndex and endIndex.
After adjusting to the virtual list, you can see that the loading rendering is about 1 second!
-
Optimized effect
3. Implementation code
<!doctype html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .container { width: 500px; height: 600px; overflow: auto; border: 1px solid; margin: 100px auto; } .item { height: 29px; line-height: 30px; border-bottom: 1px solid #aaa; padding-left: 20px; display: flex; text-align: center; } .item span{ flex: 1; } </style> </head> <body> <div id="app"> <button @click="add">Add data</button> <div class="container" ref="container"> <div class="scroll-wrapper" :style="style"> <div v-for="(item, index) in scrollList" :key="index" class="item"> <span>{{item.name}}</span> <span>{{item.price}}</span> <span>{{item.category}}</span> </div> </div> </div> </div> <script src="./js/vue.js"></script> <script> new Vue({ el: '#app', data: { list: [ {name:'name',price:'Unit Price',category:'type'} ], startIndex: 0, endIndex: 60, paddingTop: 0, paddingBottom: 0, allHeight: 0 }, computed: { scrollList() { return this.list.slice(this.startIndex, this.endIndex) }, style() { return { paddingTop: this.paddingTop + 'px', paddingBottom: this.paddingBottom + 'px' } } }, watch: { list(val) { const valLen = val.length this.allHeight = valLen * 30 this.paddingBottom = this.allHeight - this.scrollList.length * 30 } }, mounted() { const container = this.$refs.container container.addEventListener('scroll', () => { const top = container.scrollTop this.startIndex = Math.floor(top / 30) this.endIndex = this.startIndex + 60 this.paddingTop = top if (this.endIndex >= this.list.length - 1) { this.paddingBottom = 0 return } this.paddingBottom = this.allHeight - 600 - top }) }, methods: { add() { let arr = new Array(100000).fill(0) arr = arr.map((item, index) => { return { name: "name_" + index, price: Math.ceil(Math.random()*10)+'element', category: Math.random() > 0.5 ? 'Vegetables' : 'Fruits' } }) this.list = [ ...this.list, ...arr ] } } }) </script> </body> </html>
Summary: the continuous operation of dom nodes will lead to slow rendering and very stuck scrolling. The rendering efficiency and scrolling fluency are greatly improved by means of virtual list!