【走進小程序原理】揭祕組件同層渲染

閱讀本文的收穫:爲何個人小程序組件不能隨着頁面滾動?爲何組件層級不對?我該如何解決?css

在平常開發中,咱們總能在小程序的開發文檔裏看到種種組件:前端

基礎組件:小程序框架層開發ios

自定義組件:開發者or小程序官方,基於基礎組件進行二次開發web

動態庫組件:小程序官方開發的、以動態庫形式發佈的組件,其本質依然是自定義、基礎組件canvas

......小程序

綜上:就像是蓋樓,框架開發的基礎組件,是小程序全部組件建築的地基,咱們今天要聊的正是它。瀏覽器

基礎組件實現

前置名詞解釋

NANative App的縮寫,是基於智能手機本地操做系統如iOS、Android、WP並使用原生程式編寫運行的第三方應用程序,通常開發語言爲JAVA、C++、Objective-C、Swift前端框架

NA 組件:也稱原生組件,是Android、iosNA客戶端開發的控件框架

H5組件:是指HTML5語言編寫的web組件ide

webview:用來在NA代碼中展現web頁面,有點相似web中的iframeios、Android中分別採起WKWebViewWebView控件實現。

前置特性解釋

  1. 小程序前端框架,會將開發者實現的小程序佈局轉換成標準 HTML 佈局;

  2. NA 組件與webview在兩個層級(以下圖1.1)

  3. 在客戶端代碼中,後插入的NA組件,層級高於以前的NA組件

框架層的基礎組件,是基於H5組件和NA組件實現的。 

好比小程序中的 canvas、map、animation-view、textarea、cover-view、cover-image、camera、video、live-player、input 這些都是原生組件

相比於H5組件,NA組件不只能夠提供H5組件沒法實現的一些功能,還能提高用戶體驗上的流暢度,又由於減小了客戶端代碼與webview通訊的流程,下降了通訊開銷。

簡單來講,NA組件功能全、速度快、開銷少;然而,命運贈送的禮物,早已在暗中標好了價格——原生組件並非十全十美,它付出了其餘代價。

圖1.1

因爲原生組件脫離在 webview 渲染流程外,所以在使用時有如下限制:

  1. 原生組件的層級是最高的:頁面中的其餘組件不管設置 z-index 爲多少,都沒法蓋在原生組件上;

  2. 部分 CSS 樣式沒法應用於原生組件;

  3. 原生組件沒法在 scroll-viewswiperpicker-viewmovable-view 中使用:由於若是開發者在可滾動的DOM區域,插入原生組件做爲其子節點,因爲原生組件是直接插入到webview外部的層級,與DOM之間沒有關聯,因此不會跟隨移動也不會被裁減

這也就解釋了,爲何你在使用一些原生組件時,會出現組件不隨着頁面滾動或是層級永遠最高的bug。

.......是否是有點難搞?

解決NA的限制

解決這個問題不是一蹴而就的,它也有本身的歷史進程:

cover-imagecover-view,是局部解決方案:因爲在客戶端中,後插入的原生組件層級高於前面的原生組件,因此把想覆蓋原生組件的內容,用一個原生組件包裹後插入,從而hack解決。

但這樣作,就像是寫css的時候,寫了一堆!important,並非一個優雅的解決方案,後面提到的同層渲染纔是終極大殺器。

同層渲染

爲了解決原生組件的層級問題,同時儘量保留 NA 組件的優點,小程序客戶端、前端及瀏覽內核團隊一塊兒制定了一套解決方案:因爲此方案的控件並不是繪製在 NA 貼片層,而是繪製在 WebView 所渲染的頁面中,與其餘 HTML 控件在同一層級,所以稱爲「同層渲染」;在支持同層渲染後,原生組件與其它H5組件能夠隨意疊加,層級的限制將不復存在。

Android 同層渲染原理

前置特性解釋

T7:T7內核是百度手機瀏覽器基於Blink研發的瀏覽內核

ZeusPlugin:T7瀏覽器內核的一個插件機制,可用來解析或發送前端、客戶端指令,做爲二者通訊的中樞

swanCore:小程序前端框架

小程序在 Android 端採用 T7 瀏覽內核做爲渲染層,內核提供了 ZeusPlugin 指令系統。

  1. SwanCore 將開發者實現的小程序佈局轉換成標準 HTML 佈局,並對同層渲染的組件增長標識;

  2. T7 瀏覽內核渲染頁面時,識別到標識,則認爲此組件爲同層組件;

  3. T7 瀏覽內核根據需求爲同層組件擴展方法和屬性,供前端 SwanCore 調用;

  4. 擴展的能力部分由瀏覽內核實現,也可經過小程序客戶端的能力實現,根據能力具體內容而定。

ios 同層渲染原理

前置名詞

WKWebViewNA組件,用來在NA代碼中展現web頁面,它在內部採用的是分層方式進行渲染

Compositing Layer:NA合成層,內核通常會將多個webview內的 DOM 節點渲染到一個 Compositing Layer 上,所以合成層與 DOM 節點之間不存在一對一的映射關係

WKChildScrollView:也是NA組件,但 WebKit 內核已經處理了它與其餘 DOM 節點之間的層級關係,與 webview內的DOM 節點存在映射關係

前置特性

當把一個webview內的 DOM 節點的 CSS 屬性設置爲 overflow: scroll (低版本需同時設置 -webkit-overflow-scrolling: touch)以後,NAWKWebView 會爲其生成一個對應的 WKChildScrollView

iOS 端同層渲染,也正是基於 WKChildScrollView 實現的,大體流程以下:

  1. 小程序前端,在webview內建立一個 DOM 節點並設置其 CSS 屬性爲 overflow: hidden-webkit-overflow-scrolling: touch

  2. 前端通知客戶端查找到該 DOM 節點對應的原生 WKChildScrollView 組件;

  3. 將原生組件掛載到該 WKChildScrollView 節點上做爲其子 View

  4. WebKit 內核已經處理了WKChildScrollView與對應DOM 節點之間的層級關係。  

  5. 經過上述流程,小程序的NA組件就被插入到 WKChildScrollView 了,也便是在 步驟1 建立的那個 DOM 節點映射的原生 WKChildScrollView 節點。此時,修改這個 DOM 節點的樣式屬性一樣也會應用到原生組件上。所以,同層渲染的原生組件與普通的H5組件表現並沒有二致。

使用組件的注意事項

  1. NA組件中支持同層渲染的狀況(同時須要注意的是,同層渲染會存在失敗的狀況,若是嘗試5次以後依舊失敗,依舊會採用NA組件的方式)

組件名 支持版本
video v3.70.0 起
input v3.105.0 起
textarea v3.140.1起
live-player v3.140.1 起
  1. 未支持同層渲染的NA組件或者較低版本,須要注意上文提到的原生組件的使用限制:

  • 原生組件的層級是最高的,因此頁面中的其餘組件不管設置 z-index 爲多少,都沒法蓋在原生組件上。後插入的原生組件能夠覆蓋以前的原生組件;

  • 原生組件沒法在 scroll-view、swiper、picker-view、movable-view 中使用;

  • 沒法對原生組件設置 CSS 動畫;

  • 不能在父級節點使用 overflow: hidden 來裁剪原生組件的顯示區域

3.如需在NA組件中增長更高層級的組件,可考慮使用cover-image、cover-view

- END -

相關文章
相關標籤/搜索