小程序 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;
}
相关推荐
2401_845937535 小时前
PHP一键约课高效健身智能健身管理系统小程序源码
微信·微信小程序·小程序·微信公众平台·微信开放平台
程序员入门进阶7 小时前
基于微信小程序的科创微应用平台设计与实现+ssm(lw+演示+源码+运行)
微信小程序·小程序
计算机源码社15 小时前
分享一个基于微信小程序的居家养老服务小程序 养老服务预约安卓app uniapp(源码、调试、LW、开题、PPT)
android·微信小程序·uni-app·毕业设计项目·毕业设计源码·计算机课程设计·计算机毕业设计开题
DreamByte16 小时前
Python Tkinter小程序
开发语言·python·小程序
说私域17 小时前
开源 AI 智能名片小程序:开启内容营销新境界
人工智能·小程序
汇匠源17 小时前
零工市场小程序:保障灵活就业
java·小程序·零工市场
哈尔滨财富通科技17 小时前
家居小程序有什么用?
小程序
双普拉斯17 小时前
微信小程序点赞动画特效实现
nginx·微信小程序·notepad++
程序员阿龙18 小时前
【2025】基于微信小程序的网上点餐系统设计与实现、基于微信小程序的智能网上点餐系统、微信小程序点餐系统设计、智能点餐系统开发、微信小程序网上点餐平台设计
微信小程序·小程序·毕业设计·订单管理·在线点餐·订单跟踪·在线支付
Angus-zoe18 小时前
uniapp+vue+微信小程序实现侧边导航
vue.js·微信小程序·uni-app