微信小程序 虚拟列表+动态高度+动态数据

2,073 阅读2分钟

虚拟列表——无限滚动

在做项目的过程中有一个列表页会产生非常多的数据,列表会变得卡顿 于是问了度娘一遍说了两种情况

  1. 等高列表
  2. 不等高列表

我这里要讲的是第二种不等高列表,而且是动态加载数据 以下是实现大致的显示效果

虚拟列表.png

如果实现呢?上代码 wxml代码

<scroll-view class="lsmap" id="screenSee" scroll-y bindscrolltolower="bindscrolltolower" bindscroll="bindscroll">
    <view style="height: {{ headerHeight }}px;"></view>
    <view wx:for="{{pageList}}" wx:if="{{item.visible}}" wx:key="index" id="listPageId{{index}}">
      <faqsItem canCtl="{{false}}"  wx:for="{{item.data}}" wx:key="id" wx:for-item="qItem"
        wx:for-index="qIndex" bind:ctlClick="showCtlModal" bind:getPhoneNumber="itemGetPhoneNumber" phone="{{phone}}"
        accessToken="{{accessToken}}" itemData="{{qItem}}" data-item="{{qItem}}" data-index="{{index}}"
        data-qindex="{{qIndex}}">
      </faqsItem>
    </view>
    <view style=" height: {{bottomHeight}}px;"></view>
    <empty isEmpty="{{isEmpty}}" noMore="{{noMore}}"></empty>
  </scroll-view>

js代码

Page({

  /**
   * 页面的初始数据
   */
  data: {
    current: 1,
    size: 10,
    content: '',
    newsLs: [],//文章列表
    isLoading: false,//加载中
    isEmpty: false,//空
    noMore: false,//没有更多

    headerHeight: 0,
    bottomHeight: 0,
    pageList: [// 每一页数据
      // {
      //   data: [],//数据
      //   visible: false,// 当前是否显示
      // }
    ],
    pageHeight: [// 每一页高度
      // {
      //   top: 0, // 顶部在scroll里的高度
      //   height: 0, // 高度
      //   bottom:0, // 底部在scroll里的高度
      // }
    ],
    scrollH: 0,// 滚动框高度
  },


  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
    this.getListData();
    const query = wx.createSelectorQuery();
    query.select('#screenSee').boundingClientRect().exec((res) => {
      this.setData({
        scrollH: res[0].height
      })
    })
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  // 滚动触底
  bindscrolltolower() {
    if (!this.data.noMore) {
      this.getListData()
    }
  },

  // 滚动
  bindscroll(e) {
    // 实现虚拟列表
    let pageList = this.data.pageList, headerHeight = this.data.headerHeight, bottomHeight = this.data.bottomHeight;
    this.data.pageHeight.forEach((item, index) => {
      // 手指上滑
      if (e.detail.deltaY < 0 && item.bottom < floatObj.subtract(e.detail.scrollTop, 10) && pageList[index].visible && pageList[index + 2]) {
        // 隐藏头部
        pageList[index].visible = false;
        headerHeight += item.height;
        // 显示底部
        if (!pageList[index + 2].visible) {
          pageList[index + 2].visible = true;
          bottomHeight -= this.data.pageHeight[index + 2].height
        }
        this.setData({
          pageList: pageList,
          headerHeight: headerHeight,
          bottomHeight: bottomHeight
        })
      }

      // 手指下滑
      if (e.detail.deltaY > 0 && item.top > floatObj.add(e.detail.scrollTop, floatObj.add(this.data.scrollH, 10)) && pageList[index].visible == true && pageList[index - 2]) {

        // 隐藏头部
        pageList[index].visible = false;
        bottomHeight += item.height;

        if (!pageList[index - 2].visible) {
          // 显示底部
          pageList[index - 2].visible = true;
          headerHeight -= this.data.pageHeight[index - 2].height
        }

        this.setData({
          pageList: pageList,
          headerHeight: headerHeight,
          bottomHeight: bottomHeight
        })
      }
    })
  },

  // 搜索输入
  searchInput(e) {
    this.setData({
      content: e.detail.value,
    })
  },

  // 搜索
  getListData() {
    if (this.data.isLoading) return
    // 获取列表数据
    getqList().then(res => {
      if (res.code == 200) {
        let tampParam = {}
        let tempLs = res.data.records.map(el => {
          if (el.content) {
            el.content = JSON.parse(el.content)
          } else {
            el.content = []
          }
          return el
        });
        if (res.data.records.length < this.data.size) {
          tampParam = {
            current: this.data.current + 1,
            isEmpty: this.data.current == 1 && res.data.records.length == 0 ? true : false,
            noMore: true,
            newsLs: this.data.newsLs.concat(res.data.records)
          }
        } else {
          tampParam = {
            current: this.data.current + 1,
            newsLs: this.data.newsLs.concat(res.data.records)
          }
        }

        if (res.data.records.length > 0) {
          let pageList = this.data.pageList, pageHeight = this.data.pageHeight;

          pageList.push({
            data: res.data.records,//数据
            visible: true,// 当前是否显示
          })

          pageHeight.push({
            top: 0, // 顶部在scroll里的高度
            height: this.data.virtualHeight, // 高度
            bottom: this.data.virtualHeight, // 底部在scroll里的高度
          })
          tampParam.pageList = pageList
          tampParam.pageHeight = pageHeight
        }
        this.setData(tampParam)
        if (res.data.records.length > 0) {
          setTimeout(() => {
            this.initPageHeight(this.data.current - 2)
          }, 0);
        }
      }
    })
  },
  // 初始化首页高度
  initPageHeight(index) {
    const query = wx.createSelectorQuery();
    query.select(`#listPageId${index}`).boundingClientRect().exec((res) => {
      let pageHeight = this.data.pageHeight;
      pageHeight[index] = {
        top: index > 0 ? pageHeight[index - 1].bottom + 1 : 0, // 顶部在scroll里的高度
        height: res[0].height,
        bottom: index > 0 ?
          floatObj.add(pageHeight[index - 1].bottom + 1, res[0].height)
          : res[0].height, // 底部在scroll里的高度
      }
      this.setData({
        pageHeight: pageHeight
      })
    })
  },

})

这里是部分代码。需要源代码请关注公众号 ”BWeb“或者扫下方二维码,然后回复 ”微信小程序虚拟列表“

qrcode_for_gh_608fa23a438c_344.jpg