欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

微信小程序渲染性能調優(yōu)小結

 更新時間:2019年07月30日 10:34:29   作者:andypliang  
這篇文章主要介紹了微信小程序渲染性能調優(yōu),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

網(wǎng)頁的性能優(yōu)化是前端開發(fā)老生常談的熱門話題,其中微信小程序因其頁面雙線程架構設計,所以性能優(yōu)化的手段跟傳統(tǒng)的 H5 應用不太一樣。今天主要介紹一下微信小程序頁面雙線程架構的特性給頁面渲染帶來的一些影響,以及應對的一些渲染性能調優(yōu)策略。為了敘述方便,下文會把微信小程序簡稱為小程序。

小程序的雙線程架構

與傳統(tǒng)的瀏覽器Web頁面最大區(qū)別在于,小程序的是基于 雙線程 模型的,在這種架構中,小程序的渲染層使用 WebView 作為渲染載體,而邏輯層則由獨立的 JsCore 線程運行 JS 腳本,雙方并不具備數(shù)據(jù)直接共享的通道,因此渲染層和邏輯層的通信要由 NativeJSBrigde 做中轉。

 

小程序更新視圖數(shù)據(jù)的通信流程

每當小程序視圖數(shù)據(jù)需要更新時,邏輯層會調用小程序宿主環(huán)境提供的 setData 方法將數(shù)據(jù)從邏輯層傳遞到視圖層,經(jīng)過一系列渲染步驟之后完成UI視圖更新。完整的通信流程如下:

  1. 小程序邏輯層調用宿主環(huán)境的 setData 方法。
  2. 邏輯層執(zhí)行 JSON.stringify 將待傳輸數(shù)據(jù)轉換成字符串并拼接到特定的JS腳本,并通過evaluateJavascript 執(zhí)行腳本將數(shù)據(jù)傳輸?shù)戒秩緦印?/li>
  3. 渲染層接收到后, WebView JS 線程會對腳本進行編譯,得到待更新數(shù)據(jù)后進入渲染隊列等待 WebView 線程空閑時進行頁面渲染。
  4. WebView 線程開始執(zhí)行渲染時,待更新數(shù)據(jù)會合并到視圖層保留的原始 data 數(shù)據(jù),并將新數(shù)據(jù)套用在WXML片段中得到新的虛擬節(jié)點樹。經(jīng)過新虛擬節(jié)點樹與當前節(jié)點樹的 diff 對比,將差異部分更新到UI視圖。同時,將新的節(jié)點樹替換舊節(jié)點樹,用于下一次重渲染。

引發(fā)渲染性能問題的一些原因

在上述通信流程中,一些不恰當?shù)牟僮骺赡軙绊懙巾撁驿秩镜男阅埽?/p>

setData傳遞大量的新數(shù)據(jù)

數(shù)據(jù)的傳輸會經(jīng)歷跨線程傳輸和腳本編譯的過程,當數(shù)據(jù)量過大,會增加腳本編譯的執(zhí)行時間,占用 WebView JS 線程。

下圖是我們做的一組測試統(tǒng)計:在相同網(wǎng)絡環(huán)境下,各個機型分別對大小為 1KB 、 2KB 、 3KB 的數(shù)據(jù)執(zhí)行 setData 操作所消耗的時間。

從圖中可以看出, setData 數(shù)據(jù)傳輸量越大,數(shù)據(jù)傳輸所消耗的時間越大。

頻繁的執(zhí)行setData操作

頻繁的執(zhí)行 setData 會讓 WebView JS 線程一直忙碌于腳本的編譯、節(jié)點樹的對比計算和頁面渲染。導致的結果是:

  1. 頁面渲染結果有一定的延時。
  2. 用戶觸發(fā)頁面事件時,因 WebView JS 線程忙碌,用戶事件未能及時的傳輸?shù)竭壿媽佣鴮е路答佈舆t。

過多的頁面節(jié)點數(shù)

  • 頁面初始渲染時,渲染樹的構建、計算節(jié)點幾何信息以及繪制節(jié)點到屏幕的時間開銷都跟頁面節(jié)點數(shù)量成正相關關系,頁面節(jié)點數(shù)量越多,渲染耗時越長。
  • 每次執(zhí)行 setData 更新視圖, WebView JS 線程都要遍歷節(jié)點樹計算新舊節(jié)點數(shù)差異部分。當頁面節(jié)點數(shù)量越多,計算的時間開銷越大,減少節(jié)點樹節(jié)點數(shù)量可以有效降低重渲染的時間開銷。

渲染性能優(yōu)化

基于引發(fā)渲染性能問題的原因,我們可以制定一些優(yōu)化策略來避免性能問題的發(fā)生。

setData優(yōu)化

setData 作為邏輯層與視圖層通信的媒介,是最容易造成渲染性能瓶頸的 API 。我們在使用 setData 時應該遵循一些規(guī)則來盡可能避免性能問題的發(fā)生:

減少 setData 數(shù)據(jù)傳輸量

  • 僅傳輸視圖層使用到的數(shù)據(jù),其他 JS 環(huán)境用到的數(shù)據(jù)存放到 data 對象外。
  • 合理利用局部更新。 setData 是支持使用 數(shù)據(jù)路徑 的方式對對象的局部字段進行更新,我們可能會遇到這樣的場景: list 列表是從后臺獲取的數(shù)據(jù),并展示在頁面上,當 list 列表的第一項數(shù)據(jù)的 src 字段需要更新時,一般情況下我們會從后臺獲取新的 list 列表,執(zhí)行 setData 更新整個 list 列表。
 // 后臺獲取列表數(shù)據(jù)
 const list = requestSync(); 

 // 更新整個列表
 this.setData({ list }); 

實際上,只有個別字段需要更新時,我們可以這么寫來避免整個 list 列表更新:

// 后臺獲取列表數(shù)據(jù)
 const list = requestSync(); 

 // 局部更新列表
 this.setData({ 
   'list[0].src': list[0].src
 }); 

降低 setData 執(zhí)行頻率

  1. 在不影響業(yè)務流程的前提下,將多個 setData 調用合并執(zhí)行,減少線程間通信頻次。
  2. 當需要在頻繁觸發(fā)的用戶事件(如 PageScroll 、 Resize 事件)中調用 setData ,合理的利用 函數(shù)防抖(debounce)函數(shù)節(jié)流(throttle) 可以減少 setData 執(zhí)行次數(shù)。

函數(shù)防抖(debounce) :函數(shù)在觸發(fā)n秒后才執(zhí)行一次,如果在n秒內重復觸發(fā)函數(shù),則重新計算時間。

函數(shù)節(jié)流(throttle) :單位時間內,只會觸發(fā)一次函數(shù),如果同一個單位時間內觸發(fā)多次函數(shù),只會有一次生效。

除了讓開發(fā)者自覺遵循規(guī)則來減少 setData 數(shù)據(jù)傳輸量和執(zhí)行頻率之外,我們還可以自己設計一個 diff 算法,重新對 setData 進行封裝,使得在 setData 執(zhí)行之前,讓待更新的數(shù)據(jù)與原 data 數(shù)據(jù)做 diff 對比,計算出數(shù)據(jù)差異 patch 對象,判斷 patch 對象是否為空,如果為空則跳過執(zhí)行更新,否則再將 patch 對象執(zhí)行 setData 操作,從而達到減少數(shù)據(jù)傳輸量和降低執(zhí)行 setData 頻率的目的。

// setData重新封裝成新的方法,使得數(shù)據(jù)更新前先對新舊數(shù)據(jù)做diff對比,再執(zhí)行setData方法
this.update = (data) => {
  return new Promise((resolve, reject) => {
    const result = diff(data, this.data);
    if (!Object.keys(result).length) {
      resolve(null);
      return;
    } 
    this.setData(result, () => {
      resolve(result);
    });
  });
}

當然,可以直接引用這里 的現(xiàn)成 高性能小程序 setData diff算法

具體流程如下圖:

 

善用自定義組件

小程序自定義組件的實現(xiàn)是由小程序官方設計的 Exparser 框架所支持,框架實現(xiàn)的自定義組件的組件模型與 Web Components 標準的 Shadow DOM 相似:

在頁面引用自定義組件后,當初始化頁面時, Exparser 會在創(chuàng)建頁面實例的同時,也會根據(jù)自定義組件的注冊信息進行組件實例化,然后根據(jù)組件自帶的 data 數(shù)據(jù)和組件WXML,構造出獨立的 Shadow Tree ,并追加到頁面 Composed Tree 。創(chuàng)建出來的 Shadow Tree 擁有著自己獨立的邏輯空間、數(shù)據(jù)、樣式環(huán)境及setData調用:

基于自定義組件的 Shadow DOM 模型設計,我們可以將頁面中一些需要高頻執(zhí)行 setData 更新的功能模塊(如倒計時、進度條等)封裝成自定義組件嵌入到頁面中。當這些自定義組件視圖需要更新時,執(zhí)行的是組件自己的 setData ,新舊節(jié)點樹的對比計算和渲染樹的更新都只限于組件內有限的節(jié)點數(shù)量,有效降低渲染時間開銷。

下圖是我們在微保小程序WeDrive首頁中,將倒計時模塊抽取自定義組件前后的setData更新耗時對比:

從圖中可以看出,使用自定義組件后,倒計時模塊 setData 平均渲染耗時有了非常明顯的下降,實際在低端安卓機中體驗會感覺明顯的更流暢。

當然,并不是使用自定義組件越多會越好,頁面每新增一個自定義組件, Exparser 需要多管理一個組件實例,內存消耗會更大,當內存占用上升到一定程度,有可能導致 iOS 將部分 WKWebView 回收,安卓機體驗會變得更加卡頓。因此要合理的使用自定義組件,同時頁面設計也要注意不濫用標簽。

總結

小程序雙線程架構決定了數(shù)據(jù)通信優(yōu)化會是性能優(yōu)化中一個比較重要的點。而上述提到的幾個優(yōu)化建議只是優(yōu)化渲染性能中的一部分,要想讓你的頁面體驗變得更加絲滑,就要熟悉小程序框架的底層原理,根據(jù)小程序框架的特點,編寫出“合身”的前端代碼。

參考資料

微信小程序官方開發(fā)指南

小程序高性能setData diff算法

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Javascript中函數(shù)名.length屬性用法分析(對比arguments.length)

    Javascript中函數(shù)名.length屬性用法分析(對比arguments.length)

    這篇文章主要介紹了Javascript中函數(shù)名.length屬性用法,結合實例形式簡單對比分析了與arguments.length屬性的用法區(qū)別,需要的朋友可以參考下
    2016-09-09
  • JS重載實現(xiàn)方法分析

    JS重載實現(xiàn)方法分析

    這篇文章主要介紹了JS重載實現(xiàn)方法,結合實例形式分析了javascript重載的實現(xiàn)與使用方法,需要的朋友可以參考下
    2016-12-12
  • 分享我對JS插件開發(fā)的一些感想和心得

    分享我對JS插件開發(fā)的一些感想和心得

    這篇文章主要給大家分享我對JS插件開發(fā)的一些感想和心得的相關資料,需要的朋友可以參考下
    2016-02-02
  • ES6新特征數(shù)字、數(shù)組、字符串

    ES6新特征數(shù)字、數(shù)組、字符串

    這篇文章主要介紹了es6新特征之數(shù)字數(shù)組和字符串的相關資料,需要的朋友可以參考下
    2016-10-10
  • 一文讓你快速了解JavaScript棧

    一文讓你快速了解JavaScript棧

    這篇文章主要介紹了一文讓你快速了解JavaScript棧,棧全稱為堆棧,是一種先進后出的的數(shù)據(jù)結構,棧中只有兩種基本操作,也就是插入和刪除,也就是入棧和出棧操作,棧只有一端可以進行入棧和出棧操作,我們將其稱為棧頂,另一端稱其為棧底
    2022-07-07
  • 自用js開發(fā)框架小成 學習js的朋友可以看看

    自用js開發(fā)框架小成 學習js的朋友可以看看

    前段時間項目需要用到js樹,找了好多都不符合項目需求,后來發(fā)現(xiàn)了梅花雪樹和js框架,類似C#名稱空間的用法讓我眼前一亮,遂拿來主義,讀了幾遍代碼后就開工了(我是個急性子呵呵),完成了大部分,最近才找出來測試了下。
    2010-11-11
  • 真正好用的js驗證上傳文件大小的簡單方法

    真正好用的js驗證上傳文件大小的簡單方法

    下面小編就為大家?guī)硪黄嬲糜玫膉s驗證上傳文件大小的簡單方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-10-10
  • 原生js實現(xiàn)查詢天氣小應用

    原生js實現(xiàn)查詢天氣小應用

    這篇文章主要為大家詳細介紹了原生js實現(xiàn)查詢天氣的小應用,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • 純JS半透明Tip效果代碼

    純JS半透明Tip效果代碼

    自己根據(jù)網(wǎng)上提供的一個透明功能類庫寫的純JS半透明Tip效果
    2008-10-10
  • 如何用js控制css中的float的代碼

    如何用js控制css中的float的代碼

    這里向大家描述一下JS操作css的float屬性的特殊寫法,使用js操作css屬性的寫法是有一定的規(guī)律的,對于沒有中劃線的css屬性一般直接使用style.屬性名即可
    2007-08-08

最新評論