浅谈小程序 setData学问多


Posted in Javascript onFebruary 20, 2019

为什么不能频繁 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>

问题解决!以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 解析后的xml对象的读取方法细解
Jul 25 Javascript
javascript中注册和移除事件的4种方式
Mar 20 Javascript
JavaScript简单实现鼠标移动切换图片的方法
Feb 23 Javascript
Angularjs 实现分页功能及示例代码
Sep 14 Javascript
AngularJS  自定义指令详解及实例代码
Sep 14 Javascript
Vue.js绑定HTML class数组语法错误的原因分析
Oct 19 Javascript
微信小程序 聊天室简单实现
Apr 19 Javascript
vue+ElementUI实现订单页动态添加产品数据效果实例代码
Jul 13 Javascript
js断点调试经验分享
Dec 08 Javascript
解决vue的变量在settimeout内部效果失效的问题
Aug 30 Javascript
vue如何截取字符串
May 06 Javascript
TypeScript 运行时类型检查补充工具
Sep 28 Javascript
9102年webpack4搭建vue项目的方法步骤
Feb 20 #Javascript
微信小程序五子棋游戏AI实现方法【附demo源码下载】
Feb 20 #Javascript
解决element ui select下拉框不回显数据问题的解决
Feb 20 #Javascript
微信小程序五子棋游戏的悔棋实现方法【附demo源码下载】
Feb 20 #Javascript
Vue.js特性Scoped Slots的浅析
Feb 20 #Javascript
微信小程序五子棋游戏的棋盘,重置,对弈实现方法【附demo源码下载】
Feb 20 #Javascript
详解关于element级联选择器数据回显问题
Feb 20 #Javascript
You might like
PHP脚本数据库功能详解(中)
2006/10/09 PHP
php操作sqlserver关于时间日期读取的小小见解
2009/11/29 PHP
实例分析基于PHP微信网页获取用户信息
2017/11/24 PHP
accesskey 提交
2006/06/26 Javascript
jquery中:input和input的区别分析
2011/07/13 Javascript
js解析与序列化json数据(二)序列化探讨
2013/02/01 Javascript
固定网页背景图同时保持图片比例的思路代码
2013/08/15 Javascript
jquery操作select详解(取值,设置选中)
2014/02/07 Javascript
jquery动态更换设置背景图的方法
2014/03/25 Javascript
JavaScript indexOf方法入门实例(计算指定字符在字符串中首次出现的位置)
2014/10/17 Javascript
浅谈JavaScript函数节流
2014/12/09 Javascript
JQuery中模拟image的ajaxPrefilter与ajaxTransport处理
2015/06/19 Javascript
jQuery实现Flash效果上下翻动的中英文导航菜单代码
2015/09/22 Javascript
AngularJS控制器之间的通信方式详解
2016/11/03 Javascript
JavaScript使用indexOf()实现数组去重的方法分析
2018/09/04 Javascript
vue.js基于v-for实现批量渲染 Json数组对象列表数据示例
2019/08/03 Javascript
简单了解前端渐进式框架VUE
2020/07/20 Javascript
[04:40]2016个国际邀请赛中国区预选赛场地——华西村观战指南
2016/06/25 DOTA
简单说明Python中的装饰器的用法
2015/04/24 Python
tensorflow: variable的值与variable.read_value()的值区别详解
2018/07/30 Python
python3+PyQt5 使用三种不同的简便项窗口部件显示数据的方法
2019/06/17 Python
django框架模板语言使用方法详解
2019/07/18 Python
python二元表达式用法
2019/12/04 Python
基于pandas中expand的作用详解
2019/12/17 Python
Python爬虫使用bs4方法实现数据解析
2020/08/25 Python
毕业学生推荐信
2013/12/01 职场文书
年度考核自我鉴定
2014/02/02 职场文书
合作意向协议书范本
2014/03/31 职场文书
助人为乐好少年事迹材料
2014/08/18 职场文书
与美同行演讲稿
2014/09/13 职场文书
基石观后感
2015/06/12 职场文书
公司规章制度范本
2015/08/03 职场文书
小学科学课教学反思
2016/02/23 职场文书
MySQL系列之十二 备份与恢复
2021/07/02 MySQL
mysql主从复制的实现步骤
2021/10/24 MySQL
win10搭建配置ftp服务器的方法
2022/08/05 Servers