Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize virtual scrolling effect with vue

2025-01-14 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly explains "vue how to achieve virtual scrolling effect", the content of the article is simple and clear, easy to learn and understand, the following please follow the editor's ideas slowly in depth, together to study and learn "vue how to achieve virtual scrolling effect" bar!

Effect picture:

Rolling principle

To understand the principle of virtual scrolling, first look at the following picture. As you swipe your finger down, the HTML page scrolls up with it.

From the distance marked by the picture, we can draw such a conclusion. When the top edge of the screen viewport coincides with the top edge of the div element whose id is item, the distance of the item element from the top of the long list is exactly equal to the scrolling distance of the page (this conclusion will be used later when calculating the distance).

In order to simulate a realistic scrolling effect, virtual scrolling should first meet the following two requirements.

The scroll bar of the virtual scrolling list is consistent with the normal list. For example, if the list contains 1000 pieces of data, when the browser uses normal rendering, suppose the scroll bar needs to scroll down to the bottom of the 5000px. Then after the application of virtual scrolling technology, the scroll bar should also be guaranteed to have the same characteristics, scrolling down to the bottom of the 5000px.

Virtual scrolling only renders viewports and some Dom elements on the upper and lower sides. As the scroll bar slides down, the contents of the view are updated in real time to ensure that they are consistent with what you see when rendering a long list.

In order to meet the above requirements, the html design structure is as follows.

Wrapper is the outermost container element, position is set to absolute or relative, and child elements are positioned according to it.

The child elements .background and .list are the key to virtual scrolling. Background is an empty div, but it needs to set the height, which is equal to the sum of the heights of all the list items in the long list. In addition, it should be set to absolute positioning, and the value of z-index is-1.

Inside the .list is responsible for dynamically rendering the Dom elements observed by the viewport, and position is set to absolute.

BEIJING Beijing shanghai Shanghai guangzhou Guangzhou. / / omitted .wrapper {position: absolute; left: 0; right: 0; bottom: 0; top: 60px; overflow-y: scroll; .background {position: absolute; top: 0; left: 0; right: 0; z-index:-1 .list {position: absolute; top: 0; left: 0; right: 0;}}

If the above code total_height equals 10000px, the running effect of the page is shown below.

Because the child element .background sets the height, the parent element .wrapper is supported by the child element and a scroll bar appears.

If you slide down at this time, the two child elements .background and .list scroll up at the same time. When the scrolling distance reaches 9324px, the scroll bar also reaches the bottom.

This is because the height of the parent element .wrapper itself is 676px, plus the sliding distance 9324px, the result is exactly equal to the total height of the list 10000px.

By observing the above behavior, we can see that .background is only an empty div, but by giving it the total height of the list, we can make the scroll bar on the right and the scroll bar generated by ordinary long list rendering consistent in appearance and behavior.

The problem with the scroll bar is solved, but as the scroll bar slides down, the data list moves up, and after the list is all off the screen, the next slide is all white screen.

To solve the white screen problem, viewports must always show sliding data. Then the .list element dynamically updates its absolute positioning top value according to the sliding distance, which ensures that the .list is not scratched off the screen. At the same time, it also dynamically renders the data that the current viewport should display according to the sliding distance.

Looking at the dynamic effect diagram below, the Dom structure on the right shows the change during sliding.

After the scroll bar slides down quickly, the Dom element of the list is quickly rendered and refreshed. At this time, in addition to the constant replacement of the Dom element inside the .list, the .list element itself is constantly modifying transform: translate3d (0,? Px, 0) style value (modifying translate3d can achieve the same effect as modifying top attribute value).

After the above explanation, the implementation logic of virtual scrolling has been clear. First, js listens for the sliding event of the scroll bar, then calculates which child elements to render by the sliding distance, and then updates the location of the .list element. As the scroll bar slides, the child elements and positions are updated, and the scrolling effect is simulated in the viewport.

Realize

The developed Demo page is shown in the following figure. List items contain the following three structures:

Small list item with city initials on a separate line and height of 50px

Normal list item, left English name, right Chinese name, height is 100px

Large list item, left English name, middle Chinese name, a picture on the right, height is 150px

The json structure of the list data city_data is similar to the following. A type of 1 represents the rendering of a small list item style, 2 represents a normal list item, and 3 represents a large list item.

[{"name": "A", "value": "," type ": 1}, {" name ":" Al l "Ayn", "value": "Ain", "type": 2}, {"name": "Aana", "value": "Ana", "type": 3}.]

City_data contains all the data in the long list. After getting it, city_data traverses and adjusts the data structure of each item (the code is as follows).

Each list item ends up with a top and height value. Top represents the length at the top of the distance long list, and the height value refers to the height of the item.

Total_height is the total height of the entire list, which will eventually be assigned to the .background element mentioned above. After processing, the data is stored in this.list, and the height of the smallest list item is recorded, this.min_height.

Mounted () {function getHeight (type) {/ / returns the height switch (type) {case 1: return 50; case 2: return 100; case 3: return 150; default: return ";}} let total_height = 0 based on the type value Const list = city_data.map ((data, index) = > {const height = getHeight (data.type); const ob = {index, height, top: total_height, data} total_height + = height; return ob;}) this.total_height = total_height; / / list Total height this.list = list This.min_height = 50; / / the minimum height is 50 / / the maximum number of list items that the screen can hold. ContainerHeight is the height of the parent container, and this.maxNum = Math.ceil (containerHeight / this.min_height) is calculated according to the minimum height;}

Html renders different style structures according to type values (the code is as follows). The parent container .wrapper binds a sliding event onScroll, and the list element .list does not traverse the this.list array, because this.list is the raw data and contains all the list items.

The template only needs to traverse the data runList that the viewport needs to display, and the data contained in the array runList will be updated with scrolling events.

{{item.data.name}} {{item.data.value}}

The scrolling event triggers the onScroll method (the code is as follows). Because the trigger frequency of the scroll bar is very high, in order to reduce the amount of calculation of the browser, use the requestAnimationFrame function to do throttling.

The scrolling event object e can get the distance the current scroll bar slides distance. According to distance, as long as you calculate the list data of runList and modify the location information of .list, you are done.

OnScroll (e) {if (this.ticking) {return;} this.ticking = true; requestAnimationFrame (() = > {this.ticking = false;}) const distance = e.target.scrolltop; this.distance = distance; this.getRunData (distance);}

How can I quickly find the first list item element that should be rendered under the screen viewport according to the scrolling distance?

This.list is a data source for long lists, where each list item stores its own distance top from the top of the long list and its own height height.

One conclusion mentioned above is that during page scrolling, if the top edge of a viewport coincides with the top edge of a list item, the sliding distance scrollTop is exactly equal to the distance of the list item at the top of the long list.

At this point, if the page moves up a little bit, the first list item under the viewport is only partially displayed, while the other part is not visible off the screen. At this point, we still decide that the starting element under the viewport is still the list item unless it continues to move up until it is completely removed from the screen.

So we decide that the standard of the first element rendered in the viewport is that the scrolling distance of the page scrollTop is between the top and top + height of the list element.

According to the above principle, we can use dichotomy to achieve fast query (the code is as follows).

/ / the starting index is calculated by dichotomy. ScrollTop is the rolling distance getStartIndex (scrollTop) {let start = 0, end = this.list.length-1; while (start)

< end) { const mid = Math.floor((start + end) / 2); const { top, height } = this.list[mid]; if (scrollTop >

= top & & scrollTop

< top + height) { start = mid; break; } else if (scrollTop >

= top + height) {start = mid + 1;} else if (scrollTop

< top) { end = mid - 1; } } return start;} 二分法计算出了视口下渲染的第一个元素位于this.list数组中的索引,命名为起始索引start_index.接下来进入核心函数getRunData(代码如下).它主要做了以下两件事. 动态更新runList列表数据 动态更新.list长列表元素的的位置 实际开发中,假设屏幕高度为1000px,最小的列表项为50px,那么屏幕所能容纳的最大列表项数量this.maxNum为20个. 根据滑动距离计算出起始索引start_index,再从数据源this.list依据start_index截取20个元素赋予this.runList不就完成数据更新了吗? this.runList如果只盛放刚好一个屏幕容纳的最大数量,当滚动条快速滚动后,界面的渲染速度会跟不上手指滑动速度,底部会有白屏闪烁. 解决此问题的方法可以在HTML文档上多渲染一点缓冲数据.比如下面getRunData函数会渲染能容纳三张屏幕高度的列表项数量,分别对应上屏、中屏和下屏. 中屏即当前视口对应的屏幕,上屏和下屏存放着视口上下两边没有展现的缓冲Dom.首先利用二分法可以查询到屏幕视口下第一个列表项元素索引start_index,那么上屏和下屏的首个列表项索引也能依据start_index轻松得出. getRunData (distance = null) { //滚动距离 const scrollTop = distance ? distance : this.$refs.container.scrollTop; //在哪个范围内不执行滚动 if (this.scroll_scale) { if (scrollTop >

This.scroll_scale [0] & & scrollTop

< this.scroll_scale[1]) { return; } } //起始索引 let start_index = this.getStartIndex(scrollTop); start_index = start_index < 0 ? 0 : start_index; //上屏索引,this.cache_screens默认为1,缓存一个屏幕 let upper_start_index = start_index - this.maxNum * this.cache_screens; upper_start_index = upper_start_index < 0 ? 0 : upper_start_index; // 调整offset this.$refs.container.style.transform = `translate3d(0,${this.list[upper_start_index].top}px,0)`; //中间屏幕的元素 const mid_list = this.list.slice(start_index, start_index + this.maxNum); // 上屏 const upper_list = this.list.slice(upper_start_index, start_index); // 下屏元素 let down_start_index = start_index + this.maxNum; down_start_index = down_start_index >

This.list.length-1? This.list.length: down_start_index; this.scroll_scale = [this.list [Math.floor (upper_start_index + this.maxNum / 2)] .top, this.list [Math.ceil (start_index + this.maxNum / 2)] .top]; const down_list = this.list.slice (down_start_index, down_start_index + this.maxNum * this.cache_screens) This.runList = [... upper_list,... mid_list,... down_list];}

Scrolling events are triggered frequently, so as developers, we should reduce the amount of computation in browsers as much as possible. Therefore, a scrolling range can be cached in the component, that is, the array this.scroll_scale (the data structure is similar to [5000pc5675]), and the sliding distance is within this range, so the browser does not have to update the list data.

Once the scrolling distance scrollTop is within the scrolling range, the getRunData function does nothing and uses the default scrolling behavior to move the .list element up and down with the finger when the finger is slipped.

Assuming the scrolling direction is down, when the scrollTop runs out of the scrolling range, the moment the top edge of the slide viewport .wrapper coincides with the top edge of the next list item, the getRunData function first calculates the initial index start_index, and then uses start_index to get the first element index upper_start_index on the screen.

Since each list item cached its own distance from the top of the long list when the component was mounted, you can get the location information that the .list element should be assigned through this.list [upper _ start_index] .top. Then recalculate the new list data runList render page and cache the scrolling range in the new state.

Thank you for reading, the above is the content of "how to achieve virtual scrolling effect in vue". After the study of this article, I believe you have a deeper understanding of how to achieve virtual scrolling effect in vue, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report