Nonsense at the beginning

As a front page, it is often necessary to use long lists to display large amounts of data, even if you have used paging, but in extreme cases, when there are enough pages, the data will be too much and you will have performance problems such as stalling. Of course, some people think they usually have to deal with the data is not so much, do not use this. But as the saying goes, you don’t have to use something, but you can’t. Performance optimization is an important part of the front end progression, and I don’t need to use it every time, but I can’t.

For example, wechat small program also has the following suggestions in their official documents, of course, you said you do not accept the suggestions of wechat when I did not say…Before this, oneself had checked a lot of information and article on the net. It doesn’t feel right. Until later saw the bridge in the cloud big guy”Front-end Advanced” high-performance rendering of 100,000 pieces of data (virtual list). In this special thanks to the cloud bridge big guy to provide ideas. I’m just tweaking it a little bit.

Let’s cut to the chase.

Ideas and Principles

First come Lao Lao to realize the train of thought. To prevent node overload, control the number of render nodes. The window is that big, rendering 100,000 pieces of data at a time can only see what’s in the window, so we can only render a fraction of it dynamically. Of course, this involves a lot of DOM manipulation, but this is nothing compared to rendering hundreds of millions of pieces of data simultaneously.

List_scroll, list, and list_Container are all class names in the implementation code.

The specific implementation principle is shown as follows:

The virtual list list_Scroll is essentially a DIV with the same data height but no content, so z-index=-1 is set to block it from the page.

To simulate the actual scrolling effect, obtain the height of the virtual list list_Scroll and then calculate where the actual list needs to move. The list_Scroll you see is actually moving down the list. For every node that the virtual list_Scroll moves up, the actual list moves down one node, and vice versa.

The implementation code

<template> <div> <div ref="list" class="list_container" @scroll="scrollEvent"> <div class="list_scroll" :style="{ height: listHeight + 'px' }"></div> <div class="list" :style="{ transform: `translateY(${this.startOffset}px)` }" > <div class="list_item" v-for="item in visibleData" :key="item"> {{ item }} </div> </div> </div> </div> </template> <script> export default { data() { return { listData: [], // itemHeight: 200, // screenHeight: 0, // offset startOffset: 0, // start index start: 0, // end index end: null,}; }, computed: {// list total height listHeight() {return this.listdata.length * this.itemheight; }, // The number of list items that can be displayed //+2 is to render two more nodes, VisibleCount () {return math.ceil (this.screenheight/this.itemHeight) + 2; VisibleData () {return this.listdata.slice (this.start, math.min (this.end, this.listdata.length)); }, }, created() { this.onPullDownRefresh(); }, mounted() { this.screenHeight = this.$refs.list.clientHeight; this.start = 0; this.end = this.start + this.visibleCount; }, methods: {scrollEvent() {// let scrollTop = this.refs.list.scrollTop; If (this.screenheight + scrollTop == this.listheight) {// loadthis.onreachBottom (); } else if (scrollTop == 0) {this.onpullDownRefresh (); } if (this.start! = Math.floor(scrollTop / this.itemHeight)) { this.start = Math.floor(scrollTop / this.itemHeight); this.end = this.start + this.visibleCount; this.startOffset = scrollTop - (scrollTop % this.itemHeight); }}, onPullDownRefresh() {let d = []; for (let i = 1; i <= 10; i++) { d.push(i); } this.listData = d; }, onReachBottom() {let d = []; let k = this.listData.length; for (let i = k + 1; i <= 10 + k; i++) { d.push(i); } this.listData = this.listData.concat(d); ,}}}; </script> <style scoped> .list_container { height: 700px; overflow: auto; position: relative; -webkit-overflow-scrolling: touch; } .list_scroll { position: absolute; left: 0; top: 0; right: 0; z-index: -1; } .list { left: 0; right: 0; top: 0; position: absolute; text-align: center; } .list_item { color: #333; height: 200px; line-height: 200px; box-sizing: border-box; border-bottom: 1px solid #999; } </style>Copy the code

Temporary problems

  • If you only render the number of nodes with the height of the visible view, you will have white screen effects during quick refresh, so render more nodes to avoid this.
  • This is a slightly worse experience than native scrolling, so it’s usually only used when you need it again. The trade-off depends on the project requirements;

Other options

There are many mature third-party frameworks that can be used directly for similar scrolling components, and the experience is much better. Such as:

  • better-scroll
  • Swiper