当前位置: 首页 > news >正文

小程序 setData 学问多

为什么不能频繁 setData

先科普下 setData 做的事情:

在数据传输时,逻辑层会执行一次 JSON.stringify 来去除掉 setData 数据中不可传输的部分,之后将数据发送给视图层。同时,逻辑层还会将 setData 所设置的数据字段与 data 合并,使开发者可以用 this.data 读取到变更后的数据。

因此频繁调用,视图会一直更新,阻塞用户交互,引发性能问题。

但频繁调用是常见开发场景,能不能频繁调用的同时,视图延迟更新呢?

参考 Vue,我们能知道,Vue 每次赋值操作并不会直接更新视图,而是缓存到一个数据更新队列中,异步更新,再触发渲染,此时多次赋值,也只会渲染一次。

于是有网友就给出了这套方案的实现方法:

let newState = null
const asyncSetData = ({
    vm,
    newData,
}) => {
    newState = {
        ...newState,
        ...newData,
    }
    Promise.resolve().then(() => {
        if (!newState) return
        vm.setData({
            ...newState,
        })
        newState = null
    })
}

由于异步代码会在同步代码之后执行,因此,当你多次使用 asyncSetData 设置 newState 时,newState 都会被缓存起来,并异步 setData 一次

但同时,这个方案也会带来一个新的问题,同步代码会阻塞页面的渲染

同步代码会阻塞页面的渲染的问题其实在浏览器中也存在,但在小程序中,由于是逻辑、视图双线程架构,因此逻辑并不会阻塞视图渲染,这是小程序的优点,但在这套方案将会丢失这个优点。

鱼与熊掌不可兼得也!

对于信息流页面,数据过多怎么办

单次设置的数据不能超过 1024kB,请尽量避免一次设置过多的数据

通常,我们拉取到分页的数据 newList,添加到数组里,一般是这么写:

this.setData({
    list: this.data.list.concat(newList)
})

随着分页次数的增加,list 会逐渐增大,当超过 1024 kb 时,程序会报 exceed max data size 错误。

为了避免这个问题,我们可以直接修改 list 的某项数据,而不是对整个 list 重新赋值:

let length = this.data.list.length;
let newData = newList.reduce((acc, v, i)=>{
  acc[`list[${length+i}]`] = v;
  return acc;
}, {});
this.setData(newData);

这看着似乎还有点繁琐,为了简化操作,我们可以把 list 的数据结构从一维数组改为二维数组:list = [newList, newList], 每次分页,可以直接将整个 newList 赋值到 list 作为一个子数组,此时赋值方式为:

let length = this.data.list.length;
this.setData({
    [`list[${length}]`]: newList
});

同时,模板也需要相应改成二重循环:

<block wx:for="{{list}}" wx:for-item="{{listItem}}" wx:key="{{listItem}}">
  <child wx:for="{{listItem}}" wx:key="{{item}}"></child>
</block>

下拉加载,让我们一夜回到解放前

信息流产品,总避免不了要做下拉加载。

下拉加载的数据,需要插到 list 的最前面,所以我们应该这样做:

this.setData({
  'list[-1]': newList
})

哦不,对不起,上面是错的,应该是下面这样:

this.setData({
  list: this.data.list.unshift(newList)
});

这下好,又是一次性修改整个数组,一夜回到解放前......

为了解决这个问题,这里需要一点奇淫巧技:

  • 为下拉加载维护一个单独的二维数组 pullDownList
  • 在渲染时,用 wxs 将 pullDownList reverse 一下

此时,当下拉加载时,便可以只修改数组的某个子项:

let length = this.data.pullDownList.length;
this.setData({
    [`pullDownList[${length}]`]: newList
});

关键在于渲染时候的反向渲染

<wxs module="utils">
function reverseArr(arr) {
  console.log
  return arr.reverse()
}
module.exports = {
  reverseArr: reverseArr
}
</wxs>
<block wx:for="{{utils.reverseArr(pullDownList)}}" wx:for-item="{{listItem}}" wx:key="{{listItem}}">
  <child wx:for="{{listItem}}" wx:key="{{item}}"></child>
</block>

<block wx:for="{{list}}" wx:for-item="{{listItem}}" wx:key="{{listItem}}">
  <child wx:for="{{listItem}}" wx:key="{{item}}"></child>
</block>

问题解决!

参考资料

  • 终极蛇皮上帝视角之微信小程序之告别 setData, 佯真愚, 2018年08月12日

相关文章:

  • 洛谷P5163 WD与地图
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 轻松防止服务器被黑
  • spring cloud构建互联网分布式微服务云平台-服务网关zuul
  • 了解语音交互:从“若琪,今天杭州的天气”发生了什么?
  • 阿里云SLB出现502 Bad Gateway 错误排查解决方法
  • bat(DOS)常用命令详解
  • 力扣(LeetCode)357
  • 来,膜拜下android roadmap,强大的执行力
  • JS · \r\n被转义导致出错
  • [译] 每天一段 Spring 5 官方文档(5.1.4.RELEASE)—— Spring Framework Overview 10
  • P3398 仓鼠找sugar (一道LCA的裸题)
  • 创建一个 Django 项目
  • GitHub如何下载clone指定的tag
  • 技术面试感觉什么都会,面试官一问回答不上来怎么办?
  • 「前端早读君006」移动开发必备:那些玩转H5的小技巧
  • bootstrap创建登录注册页面
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • MySQL用户中的%到底包不包括localhost?
  • Netty源码解析1-Buffer
  • Redis学习笔记 - pipline(流水线、管道)
  • Swoft 源码剖析 - 代码自动更新机制
  • 不用申请服务号就可以开发微信支付/支付宝/QQ钱包支付!附:直接可用的代码+demo...
  • 基于 Babel 的 npm 包最小化设置
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 那些被忽略的 JavaScript 数组方法细节
  • 通过npm或yarn自动生成vue组件
  • 新书推荐|Windows黑客编程技术详解
  • 移动端唤起键盘时取消position:fixed定位
  • 云大使推广中的常见热门问题
  • 在Docker Swarm上部署Apache Storm:第1部分
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • ​插件化DPI在商用WIFI中的价值
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • #includecmath
  • #微信小程序(布局、渲染层基础知识)
  • $emit传递多个参数_PPC和MIPS指令集下二进制代码中函数参数个数的识别方法
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (06)金属布线——为半导体注入生命的连接
  • (1)(1.19) TeraRanger One/EVO测距仪
  • (11)MSP430F5529 定时器B
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (八)Flask之app.route装饰器函数的参数
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (六)软件测试分工
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424
  • (转)清华学霸演讲稿:永远不要说你已经尽力了
  • .mysql secret在哪_MySQL如何使用索引
  • .Net 8.0 新的变化
  • .NET CF命令行调试器MDbg入门(三) 进程控制
  • .Net Web窗口页属性
  • .net 简单实现MD5