13-Vue long list optimization vue-virtual-scroller

answer:

In large-scale enterprise-level projects, a large amount of data is often rendered. This kind of long list is a very common scenario. When the content of the list increases, it will lead to problems such as page sliding freeze, white screen , and slow data rendering ;

This situation mainly occurs in small programs, mobile terminals or background management pages;

Usually we use paging to gradually acquire content , but when there are more and more content;

For example, the pull-down refresh on the mobile terminal keeps flipping up, and more content will be loaded at the bottom, so that many elements will be added to the list . Occupancy or GPU rendering will bring a lot of performance loss, resulting in page sliding freezes and slow data rendering ;

Different processing should be done according to the situation:

  • Avoid large amounts of data: take pagination to obtain
  • Avoid rendering large amounts of data: vue-virtual-scroller plug-ins and other virtual list solutions only render data within the viewport range
  • Avoid updates: use v-once to render only once
  • Optimized update: Cache subtrees through v-memo , conditionally update, improve reuse, and avoid unnecessary updates
  • Load data on demand: use lazy loading, such as lazy loading of tree component subtrees

In short, it still depends on the specific needs. First, avoid large data acquisition and rendering from the design ; if you really need to do this , you can optimize the number of renderings by using a virtual list ; finally optimize the update. V-memo can be used to further optimize the performance of big data updates. Other methods that can be used are interactive optimization, infinite scrolling, and lazy loading solutions.

Causes of page lag

Root cause: reflow and repaint of a large number of DOM elements

Modification is a modification to the current DOM element, while updating is updating all DOM elements

Optimization idea:

1. Lazy rendering
  • Lazy loading, a common long list optimization solution, is common on mobile terminals
  • Principle: Only a part is rendered at a time, and when the rendered data is about to be scrolled, the following part is rendered
  • Advantages: Render a part of data each time, fast
  • Disadvantages: When the amount of data is large, there are still a large number of DOM nodes in the page, which takes up too much memory, reduces the rendering performance of the browser, and causes the page to freeze
  • Usage scenario: When the amount of data is not large (for example, 1000 pieces, depending on the complexity of each piece of data)
2. Page rendering

Generally, the backend gives us the data, we only need to give the number of pages and the amount of data displayed on each page to the backend, and the backend gives us the data for us to display.

3. Visual area rendering

Principle: Only the list items in the visible area of ​​the page are rendered, and the data in the non-visible area is "not rendered at all" (the first few items and the next few items are preloaded), and the list items are dynamically updated when the list is scrolled. In order to prevent the white screen, so A few more pieces of data will actually be loaded

Implement viewport rendering yourself

in the parent component

  • Use computed cache to simulate 10,000 pieces of data,
  • Pass item (data), size (height of each piece of data) and showNumber (number of pieces of data rendered each time) to subcomponents through property binding

in subcomponent

  • Receive the properties passed by the parent component through props;
  • The outermost box is set overflow-y: scroll; to achieve vertical scrolling;
  • Outermost box fixed height (outermost box height = size * showNumber);
  • Listen to the scrolling event for the outer box, and calculate the height of the data being rolled up;
  • Calculate the starting index of the data in the visible area, start = rolled height/height of a single piece of data;
  • Calculate the end index of the data in the viewable area, end = start index + the number of items that can be displayed in the viewable area;
  • Take the data of the start index start and the end index end of the visible area and display them in the visible area;

parent component

Simulate 10,000 pieces of data

Create an empty array with 10,000 elements, use the fill() function to initialize, all the values ​​​​are empty, and then use map to return the id and content to the array, which realizes the array assignment;

computed: {
	item () {
		return Array(10000).fill('').map((item, index) => ({
			id: index,
			content: `列表内容`+ index
		}))
	}
}

 Subassembly

ui structure

list is the visible area

bar is to open the box so that it can scroll vertically

  • Visual area container: It can be seen as a box at the bottom that holds all elements.
  • Scrollable area: It can be regarded as the middle layer. Suppose there are 10000 pieces of data and the height of each list item is 50, then the height of the scrollable area is 10000 * 50. The elements of this layer are invisible, and the purpose is to produce scroll bars exactly like the real list.
  • Visual area list: It can be regarded as the top layer, displaying the currently processed data, and the height is the same as the visual area container. The position of the visible area list is changed dynamically, in order to make it always appear in the visible area.

After understanding the above concepts, let's look at what we need to do when the scroll bar scrolls:

  1. According to the scrolling distance and  item height, calculate the current list that needs to be displayed startIndex
  2. startIndex Calculate the height of the list currently to be displayed  according to  the height of the viewable areaendIndex
  3. According to  startIndex and  endIndex intercepting the corresponding list data, assign it to the viewable area list and render it on the page
  4. According to the scrolling distance and  item height, calculate the offset distance of the visible area list  startOffsetand set it on the list

 

 Receive the data passed by the parent component, define the initial subscript and end subscript

Calculate container height and rolled data height

Monitor the scrolling event for the container, the initial subscript is the number of data strips rolled, rounded down

The end subscript is the start subscript + the number of data items to be displayed

Implemented using virtual list  vue-virtual-scroller

For long lists, most of our operations are:

1. Lazy loading, pagination,

2. Object.freeze freezes the array to cancel the response, because most of the time it is displayed

3. Replace high-definition pictures with thumbnails, because many times the size of pictures in long lists is relatively small, so you can use small pictures instead

The above can solve most of the long list problems, in the case of pagination

When pagination is not possible, render in the visible area

The height of items is fixed (RecycleScroller)

download plugin

yarn add vue-virtual-scroller --save

 Register in main.js

import "vue-virtual-scroller/dist/vue-virtual-scroller.css";
import VueVirtualScroller from "vue-virtual-scroller";

Vue.use(VueVirtualScroller);

 The following are required

Props

explain

Defaults

items
List of data to be rendered in the visible area --
item-size
The height of each data null
style
The outer box height of the visible area --
v-slot = { item }
Slot, get each data item --

 Modify as needed

Props

explain

Defaults

prerender
Tell the server (SSR) how many pieces of data to render each time 0
buffer
The data height of multi-rendering outside the visible area to avoid scrolling blank 200
keyField
Fields for identifying items and optimally managing rendered views id

Fixed-height scoped slot parameters

Slot

explain

Defaults

item
each data --
index
The subscript of each data --
active
Whether the view is active. The active view is considered a visible view and is positioned by the RecycleScroller. Inactive views are not considered visible and are hidden from the user. If the view is inactive, any rendering-related calculations should be skipped. --

The height of items is fixed (RecycleScroller), which can be pulled up and loaded

Events

explain

Defaults

resize
Triggered when the size is recalculated --
visible
Fired when the scrollbar thinks it is visible in the page --
hidden
Triggered when the scrollbar is hidden in the page --
update (startIndex, endIndex)
Emitted every time the view is updated, only if :  emitUpdate="true" false

Implementation idea:

  • Add :emitUpdate="true" and @update events;
  • The update function passes in two formal parameters, start and end, and judges that when end is equal to the length of the array list, it requests the interface to obtain new data, and then adds it to the array.

 The height of items is not fixed (DynamicScroller), which can be pulled up and loaded

Props(参数)

解释

默认值

item(必填)
每项数据 --
active(必填)
保持视图,数据处于 active 状态,将防止不必要的大小重新计算。 --
sizeDependencies
影响高度的值,如果发生变化,则重新计算 --
watchData
深入监视更改以重新计算大小(不推荐,可能会影响性能) false
tag
组件要呈现的元素 div
emitResize
每次重新计算大小时发出事件(可能会影响性能) false
minItemSize
列表项初次渲染使用的最小高度

Events(事件)

解释

默认值

resize
重新计算大小时触发,仅当 :emitUpdate=“true” false

小程序长列表优化实践 - 知乎

Guess you like

Origin blog.csdn.net/iaz999/article/details/131527796