微信小程序 setData数据量过大的解决与分页加载的实现

我们经常使用setData方法来修改数据,从而达到更新页面的目的。但是当我们通过setData方法设置的数据过大时就会报如下错误。

复制代码
vdSyncBatch 数据传输长度为 2260792 已经超过最大长度 1048576

这是因为setData设置的数据量是有限制的,单次设置的数据大小不得超过1024kb,否则就会出现如上错误。

而我们在一些列表页面中,每次上拉加载更多后,会习惯性的把之前存在的数据和新加载的数据合并后,一起通过setData提交来重新渲染页面。这样会留下隐患,当用户浏览的数据量达到一定程度时,就会出现如上错误。

解决方法

  • 常规做法:分页加载后,每次都将全部的数据通过setData提交

    data:{
    // 数据源
    list:[]
    },

    getListData:function(){
    // 本次加载的数据
    let _list = [];
    ...
    setData({
    // 将之前的数据与本次加载的数据合并后,一起提交
    list: this.data.list.concat(_list)
    });
    }

  • 改进后的做法:分页加载后,通过设置 list 指定位置的元素值,实现只提交新加载的数据,

    data:{
    // 当前页数
    pageNo:0,
    // 数据源
    list:[]
    },

    getListData:function(){
    // 本次加载的数据
    let _list = [];
    ...
    setData({
    ['list[' + pageNo + ']']: _list,
    });
    }

注意:改进后方案中的 list 与常规方案中的 list 已经不是同种数组。

常规方案中的 list,是一维数组,直接存放 item,结构为:[{...},{...},{...},...]

而改进方案中的 list 是二维数组,每个子元素为一页 item 数据的集合,而子元素数组中的每个元素才是 item 数据,结构为:[[{..},{...},{...}],[{..},{...},{...}],[{..},{...},{...}],...]所以需要注意对wxml中的列表结构进行修改

复制代码
      // TODO: 记录一下总条数
      this.loadedCount = this.loadedCount + data.list.length || 0;
      console.log(this.loadedCount, "总数组长度");
      // 分页条件
      if (this.loadedCount < data.total) {
        // 页码累加
        pageNo++;
      } else {
        // 分页已结束
        isFinish = true;
        // 拼接还原截取的天数并清空
        orderList = orderList.concat(this._slicedArr);
        this._slicedArr = [];
      }

      // 更新数据
      this.setData({
        ["OrderConfig.isFinish"]: isFinish,
        ["OrderConfig.pageNo"]: pageNo,
        ["OrderConfig.isLoading"]: false,
        orderList,
        //如果数据加载完毕 -1 否则为pageNo-2(因为是先++,并且页数从1开始,索引应该为0)
        [`dayList[${isFinish ? pageNo - 1 : pageNo - 2}]`]: data.list,
        daytotal: data.total,
      });
      console.log(dayList);

此处作者使用total作为判断条件的 拆分之后获取不到总条数需要单独记录

因为pageNo为1开始所以做了个判断 可参考

优化实践

纸上得来终觉浅,理论还得去实践~

1. 删掉渲染层用不到的数据,全都改到 this 或下其他方式 --- 难度系数 ⭐️

**2. 将频繁更新的页面元素封装为组件,大多数场景我们都是在组件化开发,这点几乎没有难度,只不过需要额外留意"频繁更新"这个关键词,看有没有漏掉的 ** --- 难度系数 ⭐️

3. 检查后台运行的 setData,包括不在可视窗口内的,改成进入后台后暂停 setData,比如轮播,倒计时等场景可能为高发地段 --- 难度系数 ⭐️⭐️

鉴于人工检查、分析较为耗费精力,加一颗星

4. 减少调用 setData ,合并 setData --- 难度系数 ⭐️⭐️⭐️⭐️⭐️

看着不难做到,为啥五颗星?

由于函数式编程和函数单一职责原则,为了更好的可读性和可维护性,我们的代码往往要实现低耦合,这意味着某些场景我们不得不把 setData 分散到各个函数,而不能把它们糅杂到一起,造成的问题显而易见,每个 setData 都会产生通信消耗,那将浪费不少性能,能够完美的在性能和可维护性之间做好平衡是不容易的,大多数情况我们都是取可维护性而舍性能。

5. setData 只传入数据发生变化的字段,使用数据路径形式替换直接更新某个对象或数组 --- 难度系数 ⭐️⭐️⭐️⭐️⭐️

分页列表使用二维数组实现; 避免使用 this.setData(...obj)...本身就是遍历迭代器的操作,比 forEach 性能还要差一些,如果仅仅是 obj里的属性变化,使用数据路径形式替代,只更新必要字段,而且...也不直观;

除此之外,还有很多不易发现或者不易判断是否发生变化的属性,在开发过程中不可避免地会被遗漏掉,全都考虑的面面俱到的话整个开发过程会极为复杂,在setData一个属性时需要留意该属性目前可能是处于一个什么样的状态,做出判断,甚至得为了只更新变化的数据而多写很多逻辑,这样虽然可能性能有所提升,但是对于开发者来说极不友好,写个 setData 都得思前顾后。。。

还有些是我们为了更好的可读性、代码的简洁性主动忽略掉这点的。

因此,这样被重复渲染的数据在大多数项目中都绝不在少数,只是由于无法量化,且在当今的一些高性能手机上表现也过得去,所以大家也就没太在意,但是优化的空间肯定是存在的,且非常大,只不过优化成本较高,费心费力,所以此题也给 5 颗星。

相关推荐
无己心1 天前
面向多平台 AI 搜索引擎的适配层架构设计
前端·人工智能·搜索引擎·ai·1024程序员节
u0103055277 天前
AI驱动的安卓UI自动生成功能实现
人工智能·1024程序员节
u0103055278 天前
长株潭智能体赋能腾讯元器链接共享
1024程序员节
云贝贝贝9 天前
OceanBase认证体系介绍与备考指南
运维·服务器·oceanbase·1024程序员节
u0103055279 天前
Java图像处理实战指南
人工智能·1024程序员节
u01030552710 天前
Java AWT鼠标事件全解析
人工智能·1024程序员节
u01030552712 天前
Java实用类应用精讲
人工智能·1024程序员节
u01030552712 天前
Java I/O核心操作实战
人工智能·1024程序员节
u01030552713 天前
ArrayList操作详解与实战应用
人工智能·1024程序员节
u01030552714 天前
Java模块化编程实战指南
人工智能·笔记·1024程序员节