您當前位置>首頁 » 新聞資(zī)訊 » 小程序相關(guān) >
微信小程序中(zhōng) setData 詳解
發表時間:2021-1-5
發布人:葵宇科技
浏覽次數:97
在小程序中(zhōng)各個(gè)頁面之間是相互獨立的,一個(gè)頁面分為渲染層(視圖層 webview),邏輯層(JavaScript),系統層(底層),在架構上,WebView
和(hé) JavascriptCore
都是獨立的模塊,并不具備數據直接共享的通(tōng)道,換而言之,若要将邏輯層中(zhōng)的data
的數據渲染到頁面中(zhōng),他們之間是無法直接通(tōng)信的,往往需要系統層作為中(zhōng)間角色
我們都知道視圖層的數據來源于邏輯層 data,而視圖圖層若想要改變邏輯層 data 的數據,需要借助setData
這個(gè)方法去觸發,以達到更新視圖層的數據,具體的工作過程是怎麼樣的?
定義: 設置數據,更改數據
作用: setData
函數用于将數據從邏輯層發送到視圖層(異步),同時改變對應的this.data
的值(同步)
仔細細品這句話,會包含了很多信息
setData
它是微信小程序提供的一個(gè)内置的接口,是用于改變邏輯層中(zhōng)data
下(xià)的數據的- 視圖層
view
的數據挂載在邏輯層的data
下(xià),發送到視圖層中(zhōng)是異步的 - 改變
this.data
是同步,換句話說,若直接修改this.data
而不調用this.setData
方法,是無法改變頁面的狀态的,還會造成數據不一緻
系統層在把數據轉發給渲染層,然後在渲染層展示出來,在這個(gè)過程當中(zhōng)是異步的
視圖層和(hé)邏輯層的數據傳輸,實際上通(tōng)過兩邊提供的JavScript Core
所實現,即用戶傳輸的數據,需要将其轉換為字符串形式傳遞,同時把轉換後的數據内容拼接成一份 JS 腳本,再通(tōng)過執行 JS 腳本的形式傳遞到兩邊獨立的環境
從官方文(wén)檔中(zhōng)看到這句Page.prototype.setData(Object data, Function callback)
,得知,setData
方法是挂載當前頁面實例Page
原型下(xià)一個(gè)公用實例方法
也就是說,Page 下(xià)面的任何一個(gè)方法内,都可(kě)以使用 setData 方法,它接收兩個(gè)參數
- 一個(gè)是
Object data
,第一個(gè)參數Object data
是必傳的,數據類型是Object
,所代表的含義是,這次要改變的數據 - 而第二個(gè)參數
Function callback
回調函數是非必填的,它所代表的含義是,setData
引起的界面更新渲染完畢後的回調函數
為了便于理解,在小程序中(zhōng)創建一個(gè) page 頁面,名為setdata
,如(rú)下(xià)是邏輯層 js 文(wén)件
點擊即可(kě)查看文(wén)
而 wxml 文(wén)件如(rú)下(xià)
點擊即可(kě)查看
在Web
開發中(zhōng),開發者使用 JavaScript
通(tōng)過Dom
接口來完成界面的實時更新。而在小程序中(zhōng),使用 WXML
語言所提供的數據綁定功能,來完成此項功能,在小程序中(zhōng)是沒有DOM
,BOM
的那一套東西的,沒有document.getElementById
等的
小程序是數據驅動(dòng)視圖的,邏輯層中(zhōng)的 data 數據改變了,視圖層 view 也會跟着改變,它是單向數據流的,如(rú)果想要觸發視圖中(zhōng)數據的更新,那麼就需要借助setData
這個(gè)方法
上面的WXML
通(tōng)過插值表達式來綁定 WXML
文(wén)件和(hé)對應的JavaScript
文(wén)件中(zhōng)的data
對象屬性
在上面的示例中(zhōng),頁面會顯示itclanCoder
,那如(rú)何更改邏輯層的數據呢(ne)
在下(xià)面的示例中(zhōng),演示了如(rú)何更改邏輯層的數據,在 wxml 中(zhōng)新增了一個(gè)按鈕,用bindtap
綁定了一個(gè)handleChangeName
方法,觸發按鈕,改變 data 下(xià)的數據
<!--miniprogram/pages/setdata/setdata.wxml-->
<text>{{name}}</text>
<button type="primary" bindtap="handleChangeName">更改data中(zhōng)數據</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); // 川川
}
})
在上面的示例代碼中(zhōng),更改data
下(xià)面的name
字段值,使用的是setData
方法,這個(gè)方法接收了一個(gè)參數,第一個(gè)參數是對象,這個(gè)Object
以 key: value
的形式表示,将 this.data
中(zhōng)的 key
對應的值改變成 value
注意
這個(gè)key
可(kě)以以數據路(lù)徑的形式給出,支持改變數組中(zhōng)的某一項或對象的某個(gè)屬性,如(rú) array[2].message,a.b.c.d,并且不需要在 this.data
中(zhōng)預先定義,但凡是頁面要顯示的變量數據,最好先挂載在data
下(xià)初始化定義,然後在使用
也就是說在更改setData
下(xià)的變量時,直接寫key
名就可(kě)以了的,不用寫this.data.屬性
,如(rú)下(xià)所示
this.setData({
// this.data.name: "川川" // 這樣寫是會報錯的
name: "川川" // 正确的寫法
})
而setData
接收第二個(gè)參數,是一個(gè)Function callback
handleChangeName() {
console.log("name開始的數據", this.data.name); // itclanCoder
this.setData({
name: "川川"
}, () => { // 接收第二個(gè)回調函數
console.log("執行setData引起的界面更新渲染完畢後的回調函數");
})
console.log("name經過setData後的數據", this.data.name); // 川川
}
上面代碼的執行順序是
itclancoder
川川
執行setData引起的界面更新渲染完畢後的回調函數
此結果說明這個(gè)setData
方法是異步的,等待主線程任務做完了,然後在去執行第二個(gè)參數,回調異步函數
有時候,我們的接口數據類型是對象,并非是基本數據類型(number,boolean,string,null),但由于業(yè)務需求,我們往往需要改變對象下(xià)的某個(gè)屬性
如(rú)下(xià)所示,我想改變person
下(xià)的 age 屬性值
// miniprogram/pages/setdata/setdata.js
Page({
/**
* 頁面的初始數據
*/
data: {
person: {
name: "随筆川迹",
sex: "男(nán)神",
age: 20
}
},
handleChangeName() {
this.setData({
person: {
age: 24
}
})
}
})
在上面的代碼中(zhōng),的确可(kě)以更改person
對象下(xià)的age
屬性,但是随之帶來的問(wèn)題是,person
對象下(xià)除了age
屬性,其他屬性都消失了
這非常令人郁悶
那如(rú)何解決這個(gè)問(wèn)題?
原因:
對象是一個(gè)引用數據類型,上面那種方式,是把我們當前的值指向了一個(gè)新的對象
這樣,就相當于現在的對象把之前的對象的值給覆蓋掉了的,所以隻看到age
屬性值,其他屬性值給覆蓋掉了的,這是一個(gè)非常蛋疼的問(wèn)題,
解決方式如(rú)下(xià)
- 方法 1: 指明具體的修改對象屬性
this.setData({
"person.age": 24 // 注意要用雙引号或單引号将屬性給引起來
})
- 方法 2:使用中(zhōng)擴号
['對象.屬性']:屬性值
this.setData({
['person.age']: "川川" // 訪問(wèn)對象下(xià)的屬性可(kě)以用.也可(kě)以用中(zhōng)括号,中(zhōng)間代表是一個(gè)變量,需要用引号引起來
})
如(rú)下(xià)所示
- 直接修改
this.data
而不調用this.setData
是無法改變頁面的狀态的,還會造成數據不一緻 - 僅支持設置可(kě)
JSON
化的數據,如(rú)果不是 JSON 對象數據格式,需要将數據進行轉化成json對象
,key:value
形式 - 單次設置的數據不能超過
1024kB
(1M),不要一次設置過多的數據(由于小程序運行邏輯線程與渲染線程之上,setData
的調用會把數據從邏輯層傳到渲染層,數據太大會增加通(tōng)信時間,會增加腳本的編譯執行時間,占用WebView JS
線程,) - 不要把
data
中(zhōng)任何一項的value
設為undefined
,否則這一項将不被設置并可(kě)能遺留一些潛在問(wèn)題 - 頁面中(zhōng)需要顯示的數據,可(kě)以挂載在
data
下(xià)面初始化,雖然這個(gè)值不一定要先設置,但是建議先聲明然後在使用 - 避免
setData
的調用過于頻繁(setData接口
的調用涉及邏輯層與渲染層間的線程通(tōng)信,通(tōng)信過于頻繁可(kě)能導緻處理隊列阻塞,界面渲染不及時而導緻卡頓,應避免無用的頻繁調用)- 在
Android
下(xià)用戶在滑動(dòng)時會感覺到卡頓,操作反饋延遲嚴重,因為JS
線程一直在編譯執行渲染,未能及時将用戶操作事件傳遞到邏輯層,邏輯層亦無法及時将操作處理結果及時傳遞到視圖層 - 渲染有出現延時,由于
WebView
的 JS 線程一直處于忙碌狀态,所以,邏輯層到頁面層的通(tōng)信耗時上升,視圖層收到的數據消息時距離(lí)發出時間已經過去了幾百毫秒,渲染的結果并不是實時的
- 在
- 避免 setData 數據冗餘(
setData
操作會引起框架處理一些渲染界面相關(guān)的工作,避免将未綁定在 WXML 的變量傳入setData
,減少(shǎo)不必要的性能消耗) - 後台态頁面進行
setData
(比如(rú)退出小程序),當頁面進入後台态(用戶不可(kě)見),不應該繼續去進行setData
,後台态頁面的渲染用戶是無法感受到的,另外後台态頁面去setData
也會搶占前台頁面的執行
在本文(wén)中(zhōng)主要介紹了下(xià)setData
的使用,它是用于修改挂載在 data 下(xià)面的數據的,當想要修改視圖 view,那麼需要借助 setData 函數,它接收兩個(gè)參數,第一個(gè)參數時必傳的,也就是要修改視圖 view 層的對象,而第二個(gè)參數時非必傳的
setData 将數據從邏輯層發送到視圖層是異步,同時改變對應的this.data
的值是同步,它并不是實時的,這也導緻了必須要考慮性能的因素。從而介紹了 setData 的使用注意事項,值得注意的是,如(rú)何修改對象下(xià)的某個(gè)屬性,這個(gè)在往後的開發中(zhōng),是使用比較頻繁的.