微信小程序中(zhōng) setData 詳解 - 新聞資(zī)訊 - 雲南小程序開發|雲南軟件開發|雲南網站(zhàn)建設-西山區知普網絡科技工作室

159-8711-8523

雲南網建設/小程序開發/軟件開發

知識

不管是網站(zhàn),軟件還是小程序,都要直接或間接能為您産生價值,我們在追求其視覺表現的同時,更側重于功能的便捷,營銷的便利,運營的高效,讓網站(zhàn)成為營銷工具,讓軟件能切實提升企業(yè)内部管理水平和(hé)效率。優秀的程序為後期升級提供便捷的支持!

微信小程序中(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 是什麼

定義: 設置數據,更改數據

作用: setData函數用于将數據從邏輯層發送到視圖層(異步),同時改變對應的this.data的值(同步)

仔細細品這句話,會包含了很多信息

  • setData它是微信小程序提供的一個(gè)内置的接口,是用于改變邏輯層中(zhōng)data下(xià)的數據的
  • 視圖層 view的數據挂載在邏輯層的data下(xià),發送到視圖層中(zhōng)是異步的
  • 改變this.data是同步,換句話說,若直接修改 this.data 而不調用 this.setData方法,是無法改變頁面的狀态的,還會造成數據不一緻

從上面的這張圖中(zhōng)就可(kě)以看到,當邏輯層data數據渲染到界面的時候,邏輯層的數據需要經過系統層,當系統層接收到這個(gè)邏輯層的數據後

系統層在把數據轉發給渲染層,然後在渲染層展示出來,在這個(gè)過程當中(zhōng)是異步的

視圖層和(hé)邏輯層的數據傳輸,實際上通(tōng)過兩邊提供的JavScript Core所實現,即用戶傳輸的數據,需要将其轉換為字符串形式傳遞,同時把轉換後的數據内容拼接成一份 JS 腳本,再通(tōng)過執行 JS 腳本的形式傳遞到兩邊獨立的環境

setData 接收兩重要參數

從官方文(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è)Objectkey: 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è)參數,回調異步函數

如(rú)何更改當前對象某個(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à)所示

成功改屬性
這個(gè)在以後的開發中(zhōng),很有用,有時候,在需要更改對象下(xià)的某個(gè)屬性值的時候,就可(kě)以使用這種方式

setData 注意事項
  • 直接修改 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),是使用比較頻繁的.

相關(guān)案例查看更多