网友真实露脸自拍10p,成人国产精品秘?久久久按摩,国产精品久久久久久无码不卡,成人免费区一区二区三区

小程序模板網

從小程序不支持DOM操作開始深入分析小程序運行機制

發布時間:2020-05-13 09:49 所屬欄目:小程序開發教程

小程序現在如日中天,各大公司都推出了自己的小程序平臺,目前看來運行機制都差不多,數據形成視圖,渲染和邏輯分成兩個線程,交互通過線程通信實現。

剛開始接觸小程序開發的時候,看到小程序的語法覺得很奇怪。看著像react和vue的結合體,疑惑為什么要這么費力的實現這么一套機制。難道是為了體現技術nb? 用了一會就發現問題了,照搬pc開發的那套思想,特么小程序里不支持dom相關的api,很不方便。翻了很多遍微信和支付寶小程序的官方文檔,終于有了一點理解。

本文大部分是官方文檔引用加上自己一點總結。

web開發渲染線程和腳本線程是互斥的,這也是為什么長時間的腳本運行可能會導致頁面失去響應。開發者可以使用到各種瀏覽器暴露出來的 DOM API,進行 DOM 選中和操作。 而在小程序中,二者是分開的,分別運行在不同的線程中,邏輯層運行在 JSCore 中,并沒有一個完整瀏覽器對象,因而缺少相關的DOM API和BOM API。

由于支付寶官方文檔說明過于簡略,本文結合了微信和支付寶小程序的特點總結,結合如有差異,歡迎指正。

這部分在 微信 和支付寶小程序官方文檔都有說明

瀏覽器環境中渲染線程和js線程是互斥的

由于JavaScript是可操縱DOM的,如果在修改這些元素屬性同時渲染界面(即JS線程和GUI線程同時運行),那么渲染線程前后獲得的元素數據就可能不一致了。

小程序頁面文件結構

小程序分為 app 和 page 兩層。app 用來描述整個應用,page 用來描述各個頁面。

app 由三個文件組成,必須放在項目的根目錄。

文件 必需 作用
app.js 小程序邏輯
app.json 小程序全局設置
app.acss 小程序全局樣式表

page 由四個文件組成,分別是:

文件 必需 作用
app.js 頁面邏輯
app.axml 頁面結構
app.json 頁面配置
app.acss 頁面樣式

為了方便開發者減少配置項,描述頁面的四個文件必須具有相同的路徑與文件名。

單邏輯線程與多webview渲染線程

小程序的邏輯層和渲染層是分開的兩個線程,小程序的運行環境分成渲染層和邏輯層,其中 WXML 模板和 WXSS 樣式工作在渲染層,JS腳本工作在邏輯層。在渲染層,宿主環境會把WXML轉化成對應的JS對象,在邏輯層發生數據變更的時候,我們需要通過宿主環境提供的setData方法把數據從邏輯層傳遞到渲染層,再經過對比前后差異,把差異應用在原來的Dom樹上,渲染出正確的UI界面。

小程序的渲染層和邏輯層分別由2個線程管理:渲染層的界面使用了WebView 進行渲染;邏輯層采用JsCore線程運行JS腳本。一個小程序存在多個界面,所以渲染層存在多個WebView線程,這兩個線程的通信會經由客戶端做中轉,邏輯層發送網絡請求也經由Native轉發,小程序的通信模型下圖所示。

從邏輯組成來說,一個小程序是由多個“頁面”組成的“程序”。宿主環境提供了 App() 構造器用來注冊一個程序App,需要留意的是App() 構造器必須寫在項目根目錄的app.js里,App實例是單例對象,在其他JS腳本中可以使用宿主環境提供的 getApp() 來獲取程序實例。

小程序開發框架的邏輯層使用 JavaScript 引擎為小程序提供開發者 JavaScript 代碼的運行環境以及微信小程序的特有功能。 邏輯層將數據進行處理后發送給視圖層,同時接受視圖層的事件反饋。 開發者寫的所有代碼最終將會打包成一份 JavaScript 文件,并在小程序啟動的時候運行,直到小程序銷毀。這一行為類似 ServiceWorker,所以邏輯層也稱之為 App Service。

const app = getApp(); 
復制代碼

參考資料: 微信1 、 微信2 、 微信3

小程序的運行環境

js運行引擎

小程序的 JavaScript 代碼分為邏輯層腳本和 sjs/wxs 腳本

支付寶文檔 說sjs和邏輯層運行在相同的 JavaScript 引擎的不同線程中。

微信文檔 又表示wxs是運行在webview中的,并且提供了更為強大的功能:如果在 iOS 設備上小程序內的 WXS 會比 JavaScript 代碼快 2 ~ 20 倍,在 android 設備上二者運行效率無差異;減少通信的次數,讓事件在視圖層(Webview)響應;用來響應小程序事件,目前只能響應內置組件的事件,不支持自定義組件事件;還能調用邏輯層的事件;

對兩者sjs/wxs差別表示吃瓜狀態,支付寶的sjs明顯功能弱了很多,畢竟雞肋,一般用來模擬vue里的compued功能使用,無法作為事件回調。微信的wxs提供了更強大的支持。

試了下sjs不帶類似computed緩存功能

兩個平臺都會對新預發的代碼進行 babel 轉換,使 JavaScript 引擎支持絕大多數 ES6 的新特性,但是對于內置對象未提供完全的Polyfill,具體支持情況可以查閱 支付寶 、 微信

  • 在 iOS 上,小程序邏輯層的 javascript 代碼運行在 JavaScriptCore 中;
  • 在 Android 上,小程序邏輯層的 javascript 代碼運行在 V8 中;

視圖層渲染

  • 在 iOS 上,視圖層是由 WKWebView 來渲染的
  • 在 Android 上,微信是由自研 XWeb 引擎基于 Mobile Chrome 內核來渲染的,支付寶未找到說明,猜測是UC

小程序渲染native組件原理

小程序中,有一些組件其實是調用原生組件的,如map、video等,這些復雜交互的控件,原生能帶來更好的性能與原生體驗。

簡單說就是在期望插入原生控件的位置渲染一個HTML元素,拿到此DOM的位置,客戶端在相同的位置上,根據寬高插入一塊原生區域,位置或寬高發生變化時,組件會通知客戶端做相應的調整。 可以直接看 官方文檔

為什么這么設計

微信小程序的官方介紹 很全面了

回到標題的問題。因為邏輯層Service中的代碼與WebView中的代碼完全隔離,JavaScriptCore中并沒有document,window等對象(ECMAScript標準沒有規定DOM,這其實是瀏覽器提供的)。js和視圖(dom所在)沒有運行在同一容器中。

小程序開發可做的優化

減少包的大小

很好理解,小程序初次啟動時,客戶端需要從 CDN 下載小程序資源包,此后,如果小程序代碼包未更新且還被保留在緩存中,則下載小程序代碼包的步驟會被跳過。可以做的:

  • 減少在代碼包中直接嵌入的資源文件,建議從 CDN 渠道上傳
  • 清理無用代碼和結構
  • 提升首屏,可以使用分包

減少setData次數,合并setData

每一次setData都是線程通信

支付寶小程序提供了$batchedUpdates

this.$batchedUpdates(() => {
    this.setData({
      counter: this.data.counter + 1,
    });
    this.setData({
      counter: this.data.counter + 1,
    });
  });
復制代碼

優化setData

setData是線程通信傳遞數據,傳輸時數據需要序列化,框架提供了指定路徑設置數據的方便,避免一次傳輸完整數據。

this.setData({
  'array[0]': 1,
  'obj.x':2,
});
復制代碼

針對長列表, 支付寶小程序 提供了優化方法$spliceData,使用方式對應js數組的splice

this.$spliceData({ 'a.b': [1, 0, 5, 6] })
復制代碼

針對長列表做優化,避免每次傳遞整個列表,只會從對應組件節點開始做差異比較

使用 wxs /sjs

小程序中事件響應也需要通過線程通信,如果頻繁的觸發可能會造成卡頓。例如頁面有 2 個元素 A 和 B,用戶在 A 上做 touchmove 手勢,要求 B 也跟隨移動。一次 touchmove 事件的響應過程為:

a、touchmove 事件從視圖層(Webview)拋到邏輯層(App Service)

b、邏輯層(App Service)處理 touchmove 事件,再通過 setData 來改變 B 的位置

微信小程序里可以使用wxs響應事件優化,wxs是運行在webview中的,不需要跨線程通信。WXS 函數的除了純邏輯的運算,還可以通過封裝好的ComponentDescriptor 實例來訪問以及設置組件的 class 和樣式,對于交互動畫,設置 style 和 class 足夠了:

const wxsFunction = function(event, ownerInstance) {
    const instance = ownerInstance.selectComponent('.classSelector') // 返回組件的實例
    instance.setStyle({
        "font-size": "14px" // 支持rpx
    })
    instance.getDataset()
    instance.setClass(className)
    // ...
    return false // 不往上冒泡,相當于調用了同時調用了stopPropagation和preventDefault
}
復制代碼

一次 touchmove 的響應需要經過 2 次的邏輯層和渲染層的通信以及一次渲染,通信的耗時比較大。此外 setData 渲染也會阻塞其它腳本執行,導致了整個用戶交互的動畫過程會有延遲。 官方性能優化文檔: 微信 、 支付寶 ;


易優小程序(企業版)+靈活api+前后代碼開源 碼云倉庫:starfork
本文地址:http://www.xiuhaier.com/wxmini/doc/course/25125.html 復制鏈接 如需定制請聯系易優客服咨詢:800182392 點擊咨詢
QQ在線咨詢
AI智能客服 ×