0
点赞
收藏
分享

微信扫一扫

【长列表优化】

橙子好吃吗 2022-02-13 阅读 96

长列表优化


由于长列表的特殊性,即使前面的列表用户不看了,前面dom也需要一直存在,优化为只要在视图窗口就可以。

js代码:

<template>
    <div id="u" :style="{padding:padding}">
        <slot :sliceitems="sliceitems"></slot>
    </div>
</template>
<script>
export default {
    props:{
     items:{
         require:true
     },
     itemsHeight:{
         require:true
     }
    },
    data() {
        return {
            buffer:2,
            scrollTop:0,
            viewHeight:0,
        }
    },
    computed:{
        over(){
            return  Math.max(this.scrollTop/this.itemsHeight-this.buffer,0)
        },
        down(){
            return  Math.ceil(
                  (this.scrollTop+this.viewHeight)/this.itemsHeight+this.buffer,this.items.length
            )
        },
        sliceitems(){
           return this.items.slice(this.over,this.down)

        },
        padding(){
           return `${this.over*this.itemsHeight}px 0 ${(this.items.length-this.down)*this.itemsHeight}px 0`
        }
    },
    created() {
        document.addEventListener("scroll",this.onScroll,{
             passive:true
        })

         this.scrollTop=window.scrollY
        this.viewHeight=window.innerHeight
    },
    destroyed(){
        document.removeEventListener("scroll",this.onScroll)
    },
    methods: {
        onScroll: function(){
                    this.scrollTop=window.scrollY
                    this.viewHeight=window.innerHeight
                }
             
    },

}
</script>
</script>

其中over是已经滚动过的节点,down表示当前视口滚动到的节点,为了用户体验我们会多出一个buffer值,上下会多5个元素渲染,并且我们需要定义一个最大值和最小值。

passive:true是直接执行浏览器的默认事件,而不会等onScroll。

最重要的就是padding值,让此时视图一直居中,所以要动态的变化。

vue页面如下:

<template>
  <div >
    <u-infinite-list :items="items" :itemsHeight="80" #default="{ sliceitems }">
        <ul>
          <li class="items" v-for="item in sliceitems" :key="item">{{item}}</li>
        </ul>
    </u-infinite-list>
  </div>
</template>

<script>
import UInfiniteList from '../components/UInfiniteList.vue'

export default {
  name: 'Home',
   data() {
        return {
             items:[]
        }
     },
     created() {
       for (let index = 0; index < 200; index++) {
             this.items.push(index)
       }
     },
     components:{
       UInfiniteList
     }
}
</script>
<style >
  .items{
       height: 80px;
       line-height: 80px;
       list-style: none;
  }
</style>

演示如下:
在这里插入图片描述
可以看到dom前面和后面都没有,只有视图窗口才有。

举报

相关推荐

0 条评论