评论

setData动态key的使用以及使用建议

本篇内容主要讲小程序setData的用法、注意事项、使用建议以及动态key的写法。

相信每个小程序开发者用的最多的函数非setData莫属,setData是小程序开发中使用最频繁、也是最容易引发性能问题的接口。
本篇内容主要讲小程序setData的用法、注意事项、使用建议以及动态key的写法

setData介绍

Page.prototype.setData(Object data, Function callback)

setData 函数用于将数据从逻辑层发送到视图层(异步),同时改变对应的 this.data 的值(同步)。
字段 类型 必填 描述 最低版本
data Object 这次要改变的数据
callback Function setData引起的界面更新渲染完毕后的回调函数 1.5.0

Object 以 key: value 的形式表示,将 this.data 中的 key 对应的值改变成 value。

注意事项

  • 直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致。

  • 仅支持设置可 JSON 化的数据。

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

  • 请不要把 data 中任何一项的 value 设为 undefined ,否则这一项将不被设置并可能遗留一些潜在问题。

    示例代码: 在开发者工具中预览效果

使用建议

1. data 应只包括渲染相关的数据

setData 应只用来进行渲染相关的数据更新。用 setData 的方式更新渲染无关的字段,会触发额外的渲染流程,或者增加传输的数据量,影响渲染耗时。

  • ✅ 页面或组件的 d- ata 字段,应用来存放和页面或组件渲染相关的数据(即直接在 wxml 中出现的字段);
  • ✅ 页面或组件渲染间接相关的数据可以设置为「纯数据字段」,可以使用 setData 设置并使用 observers 监听变化;
  • ✅ 页面或组件渲染无关的数据,应挂在非 data 的字段下,如 this.userData = {userId: ‘xxx’};
  • ❌ 避免在 data 中包含渲染无关的业务数据;
  • ❌ 避免使用 data 在页面或组件方法间进行数据共享;
  • ❌ 避免滥用 纯数据字段 来保存可以使用非 data 字段保存的数据。

2. 控制 setData 的频率

每次 setData 都会触发逻辑层虚拟 DOM 树的遍历和更新,也可能会导致触发一次完整的页面渲染流程。过于频繁(毫秒级)的调用 setData,会导致以下后果:

  • 逻辑层 JS 线程持续繁忙,无法正常响应用户操作的事件,也无法正常完成页面切换;
  • 视图层 JS 线程持续处于忙碌状态,逻辑层 -> 视图层通信耗时上升,视图层收到消息的延时较高,渲染出现明显延迟;
  • 视图层无法及时响应用户操作,用户滑动页面时感到明显卡顿,操作反馈延迟,用户操作事件无法及时传递到逻辑层,逻辑层亦无法及时将操作处理结果及时传递到视图层。

因此,开发者在调用 setData 时要注意:

  • ✅ 仅在需要进行页面内容更新时调用 setData;
  • ✅ 对连续的 setData 调用尽可能的进行合并;
  • ❌ 避免不必要的 setData;
  • ❌ 避免以过高的频率持续调用 setData,例如毫秒级的倒计时;
  • ❌ 避免在 onPageScroll 回调中每次都调用 setData。

3.setData 应只传发生变化的数据

setData 的数据量会影响数据拷贝和数据通讯的耗时,增加页面更新的开销,造成页面更新延迟。

  • ✅ setData 应只传入发生变化的字段;
  • 建议以数据路径形式改变数组中的某一项或对象的某个属性,如 This.Setdata({‘Array[2].Message’: ‘Newval’, ‘A.B.C.D’: ‘Newval’}),而不是每次都更新整个对象或数组;
  • ❌ 不要在 setData 中偷懒一次性传所有data:this.setData(this.data)。

修改数组动态key的写法以及修改对象的某个属性

在开发者工具中预览效果

  • 动态修改数组的某个元素
    用一个中括号修饰表达式即可
clickItem(e){
    let item = e.currentTarget.dataset.item
    let index = e.currentTarget.dataset.index
    // 第一种  可以只改某个数组的元素
    // item.selected =!this.data.list[index].selected
    // this.setData({
    //   ['list['+ index + ']']: item
    // })

    //第二种  也可以直接修改某个数组的某个属性
    this.setData({
      ['list['+ index + '].selected']: !this.data.list[index].selected
    })
  },
  • 以数据路径形式改变数组中的某一项或对象的某个属性
clickObject(e){
    this.setData({
      'user.clickNum': this.data.user.clickNum + 1
    })
  },

更多内容可以仔细查看官方文档:

点赞 3
收藏
评论

3 个评论

  • 初晴
    初晴
    2023-08-28

    改变对象的某个属性,key是个变量的话应该怎么写?下面这种写法似乎不行

    const key = 'list[' + type + ']'
      this.setData({
        key: e.detail
      })
    


    2023-08-28
    赞同
    回复 7
    • 启年
      启年
      2023-08-28
      2023-08-28
      1
      回复
    • 初晴
      初晴
      2023-08-29回复启年
      你截的图,要改变的属性是指定的,但如果要改变的属性是传进来的值呢,比如下面这种,应该怎么写呢,在小程序里用user[type]不行诶
      2023-08-29
      回复
    • 启年
      启年
      发表于小程序端
      2023-08-29回复初晴

      中括号写到外边

      2023-08-29
      2
      回复
    • 启年
      启年
      2023-08-31回复初晴
      你怎么写的,你这种写法,要事先在data里边声明这个对象和属性,不是随便追加属性的,你可以做个代码片段帮你看下。
      2023-08-31
      回复
    • 初晴
      初晴
      2023-08-31回复启年
      谢谢,知道咋解决了,里面不能用中括号,要用 .
      2023-08-31
      回复
    查看更多(2)
  • 码奴
    码奴
    2023-07-17

    如果key是 $delegate_produce_task.basic_supplier.id$ 为什么会报错呢

    2023-07-17
    赞同
    回复 2
    • 启年
      启年
      2023-08-31
      不支持这种写法
      2023-08-31
      回复
    • 码奴
      码奴
      2023-09-01回复启年
      好的 谢谢
      2023-09-01
      回复
  • 慢慢。
    慢慢。
    2023-06-01

    如果是数组末尾追加 N 项呢?似乎没有办法。

    2023-06-01
    赞同
    回复 1
    • 启年
      启年
      2023-06-01
      数组末尾追加数据,动态写法不合适呀,动态写法适合修改某个数组的元素。
      2023-06-01
      回复
登录 后发表内容