【走进小程序原理】揭秘组件同层渲染

阅读本文的收获:为何个人小程序组件不能随着页面滚动?为何组件层级不对?我该如何解决?

在平常开发中,咱们总能在小程序的开发文档里看到种种组件:css

基础组件:小程序框架层开发前端

自定义组件:开发者or小程序官方,基于基础组件进行二次开发ios

动态库组件:小程序官方开发的、以动态库形式发布的组件,其本质依然是自定义、基础组件web

......canvas

综上:就像是盖楼,框架开发的基础组件,是小程序全部组件建筑的地基,咱们今天要聊的正是它。小程序

基础组件实现

前置名词解释

NANative App的缩写,是基于智能手机本地操做系统如 iOS、Android、WP并使用原生程式编写运行的第三方应用程序,通常开发语言为 JAVA、C++、Objective-C、Swift
NA 组件:也称原生组件,是 Android、iosNA客户端开发的控件
H5组件:是指 HTML5语言编写的 web组件
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组件功能全、速度快、开销少;然而,命运赠送的礼物,早已在暗中标好了价格——原生组件并非十全十美,它付出了其余代价。ide

图1.1

图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 节点之间的层级关系。 图片 经过上述流程,小程序的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 起

2)未支持同层渲染的NA组件或者较低版本,须要注意上文提到的原生组件的使用限制:

  • 原生组件的层级是最高的,因此页面中的其余组件不管设置 z-index 为多少,都没法盖在原生组件上。后插入的原生组件能够覆盖以前的原生组件;
  • 原生组件没法在 scroll-view、swiper、picker-view、movable-view 中使用;
  • 没法对原生组件设置 CSS 动画;
  • 不能在父级节点使用 overflow: hidden 来裁剪原生组件的显示区域

3)如需在NA组件中增长更高层级的组件,可考虑使用cover-image、cover-view

- END -

相关文章
相关标签/搜索