小程序 scroll-view 性能问题

先说使用场景,一次加载很多数据造成小程序卡顿的问题 ,找了好多都没有好的解决办法,要么太过复杂,然后研究了两天通过简单的办法实现,先根据数量把高度撑开,然后根据滚动位置渲染指定的数据就可以了, 性能简直不要太好。先看效果(实际业务效果要好于测试效果)。

小程序列表性能

DataManage.js 封装

javascript 复制代码
function DataManage() {

  //**********************************************************数据
  let Data = {
    dataSource: [],//数据源
    heatData: [] //热数据(需要渲染的数据)
  }

  //**********************************************************配置
  let BaseConfig = { //基本配置信息(不需要覆盖的配置)
    triggerTime: 0, //滚动时间
    triggerTop: 0, //滚动top位置
    voidViewHeight: 0,//虚拟View高度
    pagingIndex: -1, //切换分页索引
    dataEnd: -1 //数据结束范围
  }
  let PagingConfig = { //分页配置(可改变) 
    pageSize: 50, //分页大小
    cardHeight: 55, //卡片高度
    pagingBoundary: 20,//切换数据边界值(此值需要小于分页大小)
    topBoundary: 20, //数据上移边界
    callback: '',//回调方法
    debug: false //输出日志
  }

  let CallbackFn = null //回调方法

  //**********************************************************内部方法
  const refreshData = (viewData) => {//刷新数据
    Data.heatData = viewData.viewList
    CallbackFn(viewData)
  }
  const virtualPaging = () => {//虚拟分页
    if (Data.dataSource.length <= PagingConfig.pageSize) {//不分页处理
      refreshData({ viewList: Data.dataSource, voidViewHeight: BaseConfig.voidViewHeight, viewListTop: 0 })
      return;
    }
    let currentIndex = Math.floor(BaseConfig.triggerTop / PagingConfig.cardHeight)//根据位置计算当前索引值
    if (BaseConfig.pagingIndex == -1 || (currentIndex != BaseConfig.pagingIndex && Math.abs(currentIndex - BaseConfig.pagingIndex) >= PagingConfig.pagingBoundary)) {
      //数据范围
      let dataS = currentIndex - PagingConfig.topBoundary < 0 ? 0 : currentIndex - PagingConfig.topBoundary//起始位置
      let dataE = dataS + PagingConfig.pageSize//结束位置
      if (Math.abs(Data.dataSource.length - dataE) <= PagingConfig.pagingBoundary)//避免丢失最后的数据
        dataE = Data.dataSource.length
      if (dataE == BaseConfig.dataEnd)//避免总数据量只大于分页数造成的多一次渲染
        return;//返回后,此处会触发多次,因为下面的变量没有更新
      //刷新数据
      refreshData({
        viewList: Data.dataSource.slice(dataS, dataE),
        voidViewHeight: BaseConfig.voidViewHeight,
        viewListTop: dataS * PagingConfig.cardHeight
      })
      //保存此次分页位置 
      BaseConfig.dataEnd = dataE
      BaseConfig.pagingIndex = currentIndex
      //打印日志
      if (PagingConfig.debug)
        console.log("虚拟分页,位置索引->", currentIndex, "上次分页索引->", BaseConfig.pagingIndex, "数据范围[" + dataS + "-" + dataE + "]")
    }
  }

  //**********************************************************对外方法
  /**
   * 初始化
   */
  const Init = (_pagingConfig, _data, _callback) => {
    PagingConfig = { ...PagingConfig, ..._pagingConfig }
    Data.dataSource = _data
    CallbackFn = _callback
    BaseConfig = {
      triggerTime: 0,
      triggerTop: 0,
      voidViewHeight: _data.length * PagingConfig.cardHeight,
      pagingIndex: -1,
      dataEnd: -1
    }
    virtualPaging()
  }

  /**
   * scroll-view 滚动事件
   */
  const RollEvent = (e) => {
    if (Data.dataSource.length <= PagingConfig.pageSize)
      return;
    BaseConfig.triggerTime = new Date().getTime()
    BaseConfig.triggerTop = e.detail.scrollTop
    virtualPaging()
  }
  return {
    Init, RollEvent
  }
}

export {
  DataManage as dm
}

test1.js调用

javascript 复制代码
import { dm } from "../../utils/DataManage"
const DM = dm()
Page({

  /**
   * 页面的初始数据
   */
  data: {
    TestAllData: [],//为了测试位置 对齐

    voidViewHeight: 0,//虚拟列表高度 
    viewListTop: 0, //数据列表Top起始位置   
    viewList: [], //显示的数据
  },

  rollEvent(e) {//滚动事件
    DM.RollEvent(e)
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    let DataSource = []
    for (var i = 0; i < 10000; i++) {
      DataSource.push({ sn: i, text: "第" + i + "个订单" })
    }
    this.setData({ TestAllData: DataSource })
    
    DM.Init({ debug: true }, DataSource, (data) => { this.setData(data)})
  }
})

test1.wxml 布局

XML 复制代码
<view class="container">
  <view style="position: fixed; top: 0; background-color: blueviolet; width: 100%; height: 25px; z-index: 999; ">
    <navigator url="/pages/order/order">订单</navigator>
  </view>
  <view style="margin-top:25px ; ">
    <scroll-view enhanced scroll-y bindscroll="rollEvent" style="height: calc(100vh - 25px);">

      <view class="voidView" style="height:{{voidViewHeight}}px;">
        <view style=" height: 55px; align-content: center; color: greenyellow;" wx:for="{{TestAllData}}" wx:key="sn">
         {{item.sn }}</view>
      </view>

      <view class="dataView" style="top:{{viewListTop<0?0:viewListTop}}px">
        <view class="orderCard" wx:for="{{viewList}}" wx:key="sn">
          {{item.sn }} - {{item.text}}
        </view>
      </view>

    </scroll-view>
  </view>
</view>

test1.wxss 样式

css 复制代码
::-webkit-scrollbar {
  width: 0;
  height: 0;
  color: transparent;
}

/* 占位元素 */
.voidView {
  position: absolute;
  width: 30px;
  background-image: url('http://192.168.1.8:808/images/back.png');
}

/* 列表容器 */
.dataView {
  width: 100vw;
  padding-left: 30px;
  position: absolute;
}

/* 订单卡片 */
.orderCard {
  height: 50px;
  background-color: coral;
  margin: 5px 5px 5px 5px;
  text-align: center;
  font-size: 24px;
}
相关推荐
郭wes代码3 小时前
Cmd命令大全(万字详细版)
python·算法·小程序
.生产的驴8 小时前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven
汤姆yu14 小时前
基于微信小程序的乡村旅游系统
微信小程序·旅游·乡村旅游
计算机徐师兄14 小时前
基于TP5框架的家具购物小程序的设计与实现【附源码、文档】
小程序·php·家具购物小程序·家具购物微信小程序·家具购物
曲辒净14 小时前
微信小程序实现二维码海报保存分享功能
微信小程序·小程序
朽木成才16 小时前
小程序快速实现大模型聊天机器人
小程序·机器人
peachSoda716 小时前
随手记:小程序使用uni.createVideoContext视频无法触发播放
小程序
何极光16 小时前
uniapp小程序样式穿透
前端·小程序·uni-app
小墨&晓末17 小时前
【PythonGui实战】自动摇号小程序
python·算法·小程序·系统安全
oil欧哟1 天前
🤔认真投入一个月做的小程序,能做成什么样子?有人用吗?
前端·vue.js·微信小程序