[Pit] Solve the rendering jam problem caused by too much data in vant's list component

Problem scenario

This project is to develop a mobile product, which requires scrolling display of the list, pull-down refresh function, slide up to the bottom to continue loading, and keep sliding to keep loading. I use the vant component library.

Since the list needs to display pictures, when about a hundred pieces of data are loaded, there will be a phenomenon of freezing and not smooth. Because the loading was very smooth at the beginning, and the more you slide down, the more stuck, so I guess it is not a problem of request sending, but a problem of rendering DOM. The more you slide, the more the DOM tree accumulates, causing the page to be unsmooth.

I searched for solutions to similar problems on the Internet, basically to achieve virtual scrolling, only display the content of the device screen range, and not render the data that cannot be seen up and down, which can improve efficiency.

The sad thing is that I did not find a solution supported by the vant component. The list component in the official document only has the function of pushing into the array without any optimization. I have not found anyone using the vant list on the Internet to have similar problems.

I also found a component library called vue-virtual-scroller, which can realize virtual scrolling. Just when I was going to try to use this component in combination with van-list, I found that just referencing the vue-virtual-scroller compiler began to report errors.

insert image description here
I haven't had time to solve this problem so far. I don't know if there is a master who can help me take a look. But I will not introduce it at all, and I will keep doing it and tear it up.

Get the value of scroll

If you want to hide the content outside the display area of ​​the device, you must first obtain the position of the scroll wheel, so that you can judge whether the list is outside the screen display by the length of the scroll.

But where can I get scrollTop... After many attempts, I found that the value of the scroll wheel is not on the van-list at all. If you use van-pull-refresh, the value of scroll is in this component.

Add a ref="refresh" to the component , and you can call this.$refs.refresh.scrollEl.scrollY to get the scroll value.

How to trigger scroll event

It's easy to get the value of scroll, but you can only get this value directly once. How can you monitor the change of the value in real time?

Generally speaking, a component should have a method of triggering when scrolling. The worst thing is that there is nothing written in the official documentation, and I can’t find it on the Internet. In the end, I still rummaged through its internal methods in the van-pull-refresh component. It is $refs.refresh.scrollEl.scroll , just add a function call to this method, the official did not write it! There is no interface to the component function!

Conditions for displaying content

The initial value of the scroll wheel is 0, and scrolling down gradually increases. You can get an approximate range through debugging, so that when the scroll value is within a certain range, a certain item is displayed.

Set the row height of the list to 100px, and each additional item must be within the effective range +100. Here, the index of the v-for loop is used to assist in the calculation.

the code

First write a function to get the value of scroll.

onScroll() {
    
    
  this.showItemDis = this.$refs.refresh.scrollEl.scrollY
}

Then get the component instance in mounted, assign the function to the past, and call onScroll() every time you scroll.

mounted() {
    
    
  this.$refs.refresh.scrollEl.addEventListener('scroll', this.onScroll)
},

According to the value obtained by each scroll, use v-if to judge whether to display a certain item in the list.

<div class="list" id="list">
  <van-pull-refresh v-model="listRefreshing" @refresh="onRefresh" ref="refresh">
    <van-list v-model="listLoading" :finished="listFinished" finished-text="没有更多了" @refresh="onRefresh"
          @load="onLoad">
      <div v-for="(item, index) in listData" :key="index" :class="'cell-item ' + index">
        <van-cell v-if="(showItemDis < 1500 + (index + 1) * 100) && (showItemDis + 1500 > (index + 1) * 100)" clickable :to="'Details?table=2&id=' + item.id">
        <!-- 列表每列内容 -->
        </van-cell>
      </div>
    </van-list>
  </van-pull-refresh>
</div>

The key point is the v-if condition of van-cell. I set 100px for each column here, so it is equivalent to displaying the upper 15 and the lower 15. Just understand it.

Another thing to note is that the div enclosing the van-cell must have a height set, otherwise, once the van-cell inside the div is not rendered, the height will shrink, the value of the scroll wheel will also change, and twitching will occur.

Guess you like

Origin blog.csdn.net/DrLemonPie/article/details/129319043