列表页无限滚动翻页组件--解决性能问题

解决性能问题

使用demo

  <scroller :data="card_group" @loadmore="next">
        <div class="box" slot-scope="props">
          <question :question='props.item' :qindex="props.index" ></question>
        </div>
      </scroller>

  

源码 scroller.vue

<template>
  <div class="wrapClass" ref="hei" :style="{'padding-top': to_rem(padding_top), 'padding-bottom': to_rem(padding_bottom)}">
    <div v-for="item,k in listData" :qindex="item.qindex" :key="item.qindex">
      <slot :item="item" :index="item.qindex" ></slot>
    </div>
  </div>
</template>
<script type="text/javascript">
  export default {
    name: 'scroller',
    data() {
      return {
        // 当前看到那个
        curindex:0,
        is_scrolling:false,
        padding_top: 0,
        padding_bottom: 0,
        listData: [],
      }
    },
    props: {
      data: {
        type: Array,
        default: () => {
          return []
        }
      },
      //length:默认为40
      option: {
        type: Object,
        default: () => {
          return {
            containLen:10,
            edge:5,
          }
        }
      }
    },
    async created(){
      this.leftedge=Math.floor(this.option.containLen/2)
      this.rightedge=Math.ceil(this.option.containLen/2)

      this.dataLength = this.data.length;
      this.data.forEach(function (item,key) {
        item.qindex=key
      })
      this.init()
    },
    mounted(){

      // console.log(this.$el.offsetTop)
      this.save_height()
      window.addEventListener("scroll",this.scrolling)
      // window.οnscrοll=this.scrolling;
    },
    methods:{

      init:function(){
        const middle=this.getNear(this.curindex,this.option.containLen,this.dataLength)
        this.listData=this.data.slice(middle[0],middle[1])
        this.padding_top=this.getHeight(0,middle[0])
        this.padding_bottom=this.getHeight(middle[1],this.dataLength)
      },
      to_rem: function (hei) {
        return Math.ceil(hei) + 'px';
      },
      scrolling:function (e) {
        if(this.is_scrolling===true){
          return;
        }
        this.is_scrolling=true

        const curScrollTop = document.documentElement.scrollTop || document.body.scrollTop;


        const curindex=this.indexOf(curScrollTop-this.$el.offsetTop);

        if(curindex>this.curindex){
          if(curindex-this.curindex!=1){
            console.log('跨位滚动',curindex,this.curindex)
          }
          this.curindex=curindex;
          this.save_height()
          this.init()
          if(this.dataLength-this.curindex < this.option.edge){
            this.$emit('loadmore')
          }
        }else if(curindex<this.curindex){
          if(curindex-this.curindex!=-1) {
            console.log('跨位滚动',curindex,this.curindex)
          }

          this.curindex = curindex;
          this.save_height()
          this.init()
        }
        this.is_scrolling=false
      },
      getHeight:function(left,right){
        let height=0;
        for(let i=left;i<right;i++){
          if(typeof this.data[i].hei=='undefined'){
            this.data[i].hei=200;
          }
          height+=this.data[i].hei
        }
        return height;
      },
      getNear:function(curindex,edge,len){
        if(edge>=len){
          return [0,len]
        }
        let left=curindex-this.leftedge;
        let right=curindex+this.rightedge;
        if(right>len){
          right=len
          left=right-edge
        }
        if(left<0){
          left=0;
          right=left+edge
        }
        return [left,right]
      },
      save_height:function(){

        const len = this.listData.length;

        const items = this.$refs.hei.children;
        for (let i = 0; i < len; i++) {
          const hei = items[i].offsetHeight;
          const qindex=items[i].getAttribute("qindex")
          Object.assign(this.data[qindex], {hei: hei});
        }


      },
      indexOf:function (top) {
        let has=-1;
        let top2=top;
        for(let i=0;i<this.data.length;i++){
          if(top2<0||!this.data[i].hei){
            has=i
            break;
          }else{
            top2=top2-this.data[i].hei
          }
        }
        return has;
      }
    },
    watch:{
      data: {
        handler: function (val, oldVal) {

          if ((val.length>oldVal.length) && val[0].hei) {
            //追加数据
          }
          else {
            //更新数据
            this.curindex=0;
            document.documentElement.scrollTop=0;
            document.body.scrollTop=0;
          }
          this.$nextTick(()=>{
            this.save_height()
          });
          this.dataLength = val.length;
          val.forEach(function (item,key) {
            item.qindex=key
          });
          this.init()
        },
        deep: false
      }
    }
  }

</script>

  

转载于:https://www.cnblogs.com/caoke/p/9263048.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值