乐趣区

关于前端:走进小程序原理揭秘组件同层渲染

浏览本文的播种:为什么我的小程序组件不能随着页面滚动?为什么组件层级不对?我该如何解决?

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

根底组件:小程序框架层开发

自定义组件:开发者 or 小程序官网,基于 根底组件 进行二次开发

动静库组件:小程序官网开发的、以动静库模式公布的组件,其本质仍然是自定义、根底组件

……

综上:就像是盖楼,框架开发的 根底组件,是小程序所有组件修建的地基,咱们明天要聊的正是它。

根底组件实现

前置名词解释

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组件性能全、速度快、开销少;然而,命运赠送的礼物,早已在暗中标好了价格——原生组件并不是美中不足,它付出了其余代价。

图 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 –

退出移动版