优化无限滚动列表内容多导致卡顿的问题

下载vue-intersect

npm install vue-intersect --save

html代码

 <van-pull-refresh v-model="refreshing" success-text="刷新成功" @refresh="onRefresh">
        <van-list
          v-model="loading"
          :finished="!apiData.pageInfo.hasNextPage"
          finished-text="加载完啦"
          @load="getFiles"
          :error="error"
          ref="v_list"
        >
          <div class="file_item" v-for="(item, index) in fileList" :key="index" :ref="'file_item' + index">
            <intersect @enter="intersectFileDay(item, false)" @leave="intersectFileDay(item, true)">
              <div>
                <div v-if="item.isHidden" :style="{height: item.hiddenViewH + 'px'}"></div>
                <div v-else>
                  <van-sticky :offset-top="listBoxOffsetTop">
                    <h1>{{item.createTime}}</h1>
                  </van-sticky>
                  <van-grid :column-num="4" square :border="false" clickable>
                    <van-grid-item v-for="(fileItem, fileIndex) in item.list" :key="fileIndex">
                      <intersect @enter="intersectFileItem(fileItem, false)" @leave="intersectFileItem(fileItem, true)">
                        <div class="wh100" @click="onShowFileItem(fileItem, index)">
                          <file-item :fileItem="fileItem" :fileIndex="fileIndex" v-if="!fileItem.isHidden"></file-item>
                        </div>
                      </intersect>
                    </van-grid-item>
                  </van-grid>
                </div>
              </div>
            </intersect>
          </div>
          <Loading v-if="!loading" :len="fileList.length" :error="error"></Loading>
        </van-list>
      </van-pull-refresh>

script代码

import {searchFileApi} from '../../../http/api'
import FileItem from '../../../components/file-library/FileItem'
import Intersect from 'vue-intersect'
export default {
  name: 'FileLibrary',
  components: {
    FileLibraryStatisticsPie,
    SearchPopup,
    FileItem,
    Intersect,
    FileInfoPopup
  },
  data () {
    return {
      supervene: false,//解决下拉刷新和上拉加载的冲突
      fileList: [],
      loading: true,
      error: false,
      refreshing: false,
      searchParams: {
        isHide: 'visible', //枚举: visible 可见的, hidden 已隐藏
        fileFromList: [],
        fileTypeList: [],
        storeIdList: [],
        filename: '',
        pageNum: 1,
        pageSize: 20,
        timePeriod: {
          beginTime: null,
          endTime: null
        }
      },
      ov: false,//已执行mounted
      ol: false,//完成渲染list
      om: false//完成获取ref高度
    }
  },
  methods: {
    requestOv(error){
      this.refreshing = false;
      this.loading = false;
      this.supervene = false;
      this.error = error;
    },
    getFiles(){
      searchFileApi(this.searchParams).then(res=>{
        this.searchParams.pageNum ++;
        this.fileList = this.fileList.concat(res.data.pageInfo.list);
        this.setH();
        this.requestOv(false);
        this.ol = true;
      }).catch(()=>{
        this.requestOv(true)
      })
    },
    /**
     * 内层每一项
     */
    intersectFileItem(fileItem, type){
      this.$set(fileItem, 'isHidden', type)
    },
    /**
     * 外层每一列
     * @param item
     * @param type
     */
    intersectFileDay(item, type){
      if (this.ov && this.ol && this.om){
        this.$set(item, 'isHidden', type);
      }
    },
    setH(){
      if (this.ov && this.ol){
        setTimeout(()=>{
          this.fileList.map((item,index)=>{
            this.$set(item, 'hiddenViewH', this.$refs['file_item' + index][0].scrollHeight);
          });
          this.om = true
        },100)
      }
    }
  },
  created() {
    this.getFiles();
  },
  mounted(){
    this.ov = true;
    this.setH()
  }
}

思路

使用vue-intersect

请求获取数据list

v-for渲染列表 并把在每一个列表设置一个独立的ref

ref一定要是唯一的(不唯一其实也可以,因为获取的refs是一个数组,但避免出错还是唯一比较好)

保证列表渲染完成后(可以加变量分段判断),通过ref读取每一项列表的高度,存在对应列表每一项中

在触发界面交叉显示函数时设置item显示隐藏属性,

用v-if判断空盒子替代组件,利用ref计算的高度赋值给空盒子,达到高度撑开

intersect下面必须要有一个稳定的div,如果去掉直接是ifelse的组件,会导致一些交叉口方法不执行,或者报错等

这样就可以了,但是划定过快会白屏,然后展现,这个MDN提到过,是html的bug,不过这并不影响什么

intersect支持嵌套,可以尽量的让当前可视页面存在使用的dom,其它均用空div替代

再优化可以将intersect组分大一些

在特殊情况下如几十万条数据量,请考虑使用按钮分页,或者其它解决方法

vue-intersect

vue-intersect是基于 交叉口观察者API开发的,想详细了解请移步官方文档

https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值