在微信小程序中渲染数据时通常会使用setData方法,但是setData对数据是有影响的,单次设置的数据不能超过1024kB,否则就会出现卡顿甚至有时会导致小程序闪退等现象。而我们平时在实现业务时,一般会采取数据分页而防止大量数据渲染导致小程序白屏/卡顿,例如在一些商城平台需要滚动时切换菜单,也需要回显购物车数据的情况下,无法进行分页处理,我的方法是把从接口获取到的数据进行格式化处理后,进行递归调用(递归一次进行一次setDate从而不进行一次性渲染大量数据),代码如下:
<template> <scroll-box> <!-- 菜单 --> <view> <view v-for="(item,index) in truthfulData" :key="item.id"> {{item.title}} </view> </view> <!-- 子列表 --> <view> <!-- 菜单 --> <view v-for="(item,index) in truthfulData" :key="item.id"> {{item.title}} </view> <view> <!-- 子列表 --> <view v-for="(childItem,childIndex) in itme.childList" :key="childItem.id"> {{childItem.name}} </view> </view> </view> </scroll-box></template><script setup lang="ts">// 获取数据列表const truthfulData = ref(null) // 真实渲染数据// 处理数据模型 [{id,title,childList:[]},{id,title,childList:[]}...]async function getDate() { try { // 1. 通过接口调用获取需要渲染的数据列表 const dateList= await getDateList() // 2. 调用setDate优化函数 truthfulData.value = [] injectDate(dateList.data,0,0) // 3. 进行渲染完成后的容器数据获取 - 小程序 uni.createSelectorQuery().select("#id").boundingClientRect(data=>{...}).exec() 是异步方法需要在数据渲染后执行 nextTick(() => { // ... }) } catch (e) { console.log(e); }}// 优化渲染数据 function injectDate(virtuallyDate : [any], pIndex : number, index : number) { if (virtuallyDate.length === pIndex) return // 当菜单数据为空时 if (!truthfulData.value[pIndex]) { // 数据最外层菜单赋值 truthfulData.value[pIndex] = { id: virtuallyDate[pIndex].id, title: virtuallyDate[pIndex].title, childList: [] // 需要渲染的子集数据 } } // 添加数据 truthfulData.value[pIndex].childList.push(...virtuallyDate[pIndex].childList.slice(index, index + 20)) // 20 根据自己的数据大小拟定 let i = index + 20 if (i >= virtuallyDate[pIndex].childList.length) i = 0 initCommodityList(virtuallyDate , i === 0 ? pIndex + 1 : pIndex, i) // 递归调用}</script>
递归setDate 渲染之后可用正常获取容器的宽高进行进一步业务扩展
大致效果如下:
建议搭配图片懒加载使用,防止大量图片同时请求导致服务器承受不住