微信小程序中 setData 详解

在小程序中各个页面之间是相互独立的,一个页面分为渲染层(视图层 webview),逻辑层(JavaScript),系统层(底层)

在架构上,WebView和 JavascriptCore 都是独立的模块,并不具备数据直接共享的通道

换而言之,若要将逻辑层中的data的数据渲染到页面中,他们之间是无法直接通信的,往往需要系统层作为中间角色

我们都知道视图层的数据来源于逻辑层 data,而视图图层若想要改变逻辑层 data 的数据,需要借助setData这个方法去触发,以达到更新视图层的数据,具体的工作过程是怎么样的?

·  正  ·  文  ·  来  ·  啦  ·

01

setData是什么?

定义: 设置数据,更改数据

作用: setData函数用于将数据从逻辑层发送到视图层(异步),同时改变对应的 this.data的值(同步)

仔细细品这句话,会包含了很多信息

setData它是微信小程序提供的一个内置的接口,是用于改变逻辑层中 data下的数据的

视图层 view的数据挂载在逻辑层的 data下,发送到视图层中是异步的

改变 this.data是同步,换句话说,若直接修改 this.data 而不调用 this.setData方法,是无法改变页面的状态的,还会造成数据不一致

从上面的这张图中就可以看到,当逻辑层data数据渲染到界面的时候,逻辑层的数据需要经过系统层,当系统层接收到这个逻辑层的数据后

系统层在把数据转发给渲染层,然后在渲染层展示出来,在这个过程当中是异步的

视图层和逻辑层的数据传输,实际上通过两边提供的 JavScript Core所实现,即用户传输的数据,需要将其转换为字符串形式传递

同时把转换后的数据内容拼接成一份 JS 脚本,再通过执行 JS 脚本的形式传递到两边独立的环境

02

setData两个重要的参数

从官方文档中看到这句Page.prototype.setData(Object data, Function callback),得知,setData方法是挂载当前页面实例Page原型下一个公用实例方法

也就是说,Page 下面的任何一个方法内,都可以使用 setData 方法,它接收两个参数

一个是Object data,第一个参数Object data是必传的,数据类型是Object,所代表的含义是,这次要改变的数据

而第二个参数Function callback回调函数是非必填的,它所代表的含义是,setData引起的界面更新渲染完毕后的回调函数

为了便于理解,在小程序中创建一个 page 页面,名为setdata,如下是逻辑层 js 文件

// miniprogram/pages/setdata/setdata.js

Page({

/**

* 页面的初始数据

*/

data:{

name:"itclanCoder"

},

/**

* 生命周期函数--监听页面加载

*

/

onLoad:function(options){}

})

而 wxml 文件如下

<!--miniprogram/pages/setdata/setdata.wxml-->

<text>{{name}}</text>

在Web 开发中,开发者使用JavaScript通过Dom接口来完成界面的实时更新。而在小程序中,使用WXML语言所提供的数据绑定功能,来完成此项功能

在小程序中是没有DOM,BOM的那一套东西的,没有document.getElementById等的

小程序是数据驱动视图的,逻辑层中的 data 数据改变了,视图层 view 也会跟着改变,它是单向数据流的,如果想要触发视图中数据的更新,那么就需要借助setData这个方法

上面的WXML通过{{变量名}}来绑定 WXML文件和对应的JavaScript文件中的data对象属性

在上面的示例中,页面会显示itclanCoder,那如何更改逻辑层的数据呢

在下面的示例中,演示了如何更改逻辑层的数据,在 wxml 中新增了一个按钮,用bindtap绑定了一个handleChangeName方法,触发按钮,改变 data 下的数据

<!--miniprogram/pages/setdata/setdata.wxml-->

<text>{{name}}</text>

<buttontype="primary"bindtap="handleChangeName">更改data中数据</button>

而在逻辑层JS// miniprogram/pages/setdata/setdata.js

Page({/**

  * 页面的初始数据

  */

data:{name:"itclanCoder"},

// 改变data的方法

handleChangeName(){

console.log("name开始的数据",this.data.name);

// itclanCoder

this.setData(

    {

        name:"川川"

    }

)

console.log("name经过setData后的数据",this.data.name);// 川川

}})

在上面的示例代码中,更改data下面的name字段值,使用的是setData方法,这个方法接收了一个参数,第一个参数是对象,这个Object 以 key: value 的形式表示,将 this.data中的 key对应的值改变成 value

注意

这个key可以以数据路径的形式给出,支持改变数组中的某一项或对象的某个属性,如 array[2].message,a.b.c.d,并且不需要在 this.data中预先定义,但凡是页面要显示的变量数据,最好先挂载在data下初始化定义,然后在使用

也就是说在更改setData下的变量时,直接写key名就可以了的,不用写this.data.属性,如下所示

this.setData({

this.data.name: "川川" 

// 这样写是会报错的name:"川川"

// 正确的写法

})

而setData接收第二个参数,是一个Function

 callbackhandleChangeName(){

console.log("name开始的数据",this.data.name);// itclanCoder

this.setData({name:"川川"},

()=>{

// 接收第二个回调函数

console.log("执行setData引起的界面更新渲染完毕后的回调函数");})

console.log("name经过setData后的数据",this.data.name);// 川川

}

上面代码的执行顺序是

itclancoder

川川

执行setData引起的界面更新渲染完毕后的回调函数

此结果说明这个setData方法是异步的,等待主线程任务做完了,然后在去执行第二个参数,回调异步函数

03

如何更改某个对象下的属性

有时候,我们的接口数据类型是对象,并非是基本数据类型(number,boolean,string,null),但由于业务需求,我们往往需要改变对象下的某个属性

如下所示,我想改变person下的 age 属性值

// miniprogram/pages/setdata/setdata.js

Page({/**

  * 页面的初始数据

  */

data:{

    person:{

        name:"随笔川迹",

        sex:"男神",

        age:20

                }

},

handleChangeName(){

this.setData(

{

person:{age:24}

})

}})

在上面的代码中,的确可以更改person对象下的age属性,但是随之带来的问题是,person对象下除了age属性,其他属性都消失了

这非常令人郁闷

那如何解决这个问题?

方法 1: 指明具体的修改对象属性

this.setData({"person.age":24// 注意要用双引号或单引号将属性给引起来})

方法 2:使用中扩号['对象.属性']:属性值

this.setData({['person.age']:"川川"// 访问对象下的属性可以用.也可以用中括号,中间代表是一个变量,需要用引号引起来})

如下所示

这个在以后的开发中,很有用,有时候,在需要更改对象下的某个属性值的时候,就可以使用这种方式

04

setData注意事项

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

仅支持设置可JSON化的数据,如果不是 JSON 对象数据格式,需要将数据进行转化成json对象`,key:value形式

单次设置的数据不能超过1024kB(1M),不要一次设置过多的数据(由于小程序运行逻辑线程与渲染线程之上,setData的调用会把数据从逻辑层传到渲染层,数据太大会增加通信时间,会增加脚本的编译执行时间,占用 WebView JS 线程,)

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

页面中需要显示的数据,可以挂载在data下面初始化,虽然这个值不一定要先设置,但是建议先声明然后在使用

避免setData的调用过于频繁(setData接口的调用涉及逻辑层与渲染层间的线程通信,通信过于频繁可能导致处理队列阻塞,界面渲染不及时而导致卡顿,应避免无用的频繁调用)

在Android下用户在滑动时会感觉到卡顿,操作反馈延迟严重,因为JS线程一直在编译执行渲染,未能及时将用户操作事件传递到逻辑层,逻辑层亦无法及时将操作处理结果及时传递到视图层

渲染有出现延时,由于WebView的 JS 线程一直处于忙碌状态,所以,逻辑层到页面层的通信耗时上升,视图层收到的数据消息时距离发出时间已经过去了几百毫秒,渲染的结果并不是实时的

避免 setData 数据冗余(setData操作会引起框架处理一些渲染界面相关的工作,避免将未绑定在 WXML 的变量传入setData,减少不必要的性能消耗)

后台态页面进行setData(比如退出小程序),当页面进入后台态(用户不可见),不应该继续去进行 setData,后台态页面的渲染用户是无法感受到的,另外后台态页面去 setData 也会抢占前台页面的执行

结语

在本文中主要介绍了下setData的使用,它是用于修改挂载在 data 下面的数据的,当想要修改视图 view,那么需要借助 setData 函数,它接收两个参数,第一个参数时必传的,也就是要修改视图 view 层的对象,而第二个参数时非必传的

setData 将数据从逻辑层发送到视图层是异步,同时改变对应的this.data的值是同步,它并不是实时的,这也导致了必须要考虑性能的因素

从而介绍了 setData 的使用注意事项,值得注意的是,如何修改对象下的某个属性,这个在往后的开发中,是使用比较频繁的.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容