H5 具有开发成本较低、跨平台、快速迭代等优点,但 WebView 在性能上相比 Native 会有一定的劣势,如在资源加载比较多的场景下会导致内存占用过高、滚动卡顿、部分格式图片格式不支持等问题。针对这些问题,客户端可对图片和视频等资源进行原生渲染,即实现 WebView 同层渲染。
iOS
实现原理
WKWebView 在进行 HTML 解析时,会根据页面 DOM 元素在 WKWebView 控件下生成对应的 iOS 原生控件。但通常情况下,生成的原生控件与 HTML 节点无对应关系,但在某些特殊情况下,一些特殊 DOM 元素会在 WebView 的对应位置生成位置、大小完全一致的原生控件:
- CSS 属性满足:
overflow: scroll; -webkit-overflow-scrolling: touch;
- 子元素高度或宽度超出该 DOM 的高度或宽度形成弹性滚动
iOS 13 之前,上面两个条件都需要满足;iOS 13 只需满足上面任一条件即可。
详细步骤
- 前端预先在需要插入原生控件的位置插入一个具有 overflow 属性的 div 标签,通知客户端该滚动条的位置、大小;
- 客户端根据前端传入的位置和大小,在 WKWebView 下遍历找到这个 div 标签对应的 UIScrollView (大小位置均一致),保存其对象指针,并分配一个 id 返回给前端;
- 客户端根据前端传入的位置和大小,在 WKWebView 下遍历找到这个 div 标签对应的 UIScrollView (大小位置均一致),保存其对象指针,并分配一个 id 返回给前端;
手势问题
由于 WKWebView 会接管用户的所有操作事件,因此按照上述方案插入后,原生控件是无法响应用户事件的。需要对事件做特殊处理:通过重载 WKWebView 的 hitTest
方法,在该方法的处理逻辑中优先处理网页上的事件,如果网页未处理,再传递给原生控件。
Android
实现原理
Chromium 内核支持 WebPlugin 机制,WebPlugin 是浏览器内核的一个插件机制,主要用来解析和描述 embed
标签。Android 端的同层渲染就是基于 embed
标签结合 Chromium 内核扩展来实现的。
详细步骤
- WebView 侧创建一个
embed
DOM 节点并指定组件类型; - Chromium 内核会创建一个
WebPlugin
实例,并生成一个RenderLayer
; - Android 客户端初始化一个对应的原生组件;
- Android 客户端将原生组件的画面绘制到步骤 2 创建的
RenderLayer
所绑定的SurfaceTexture
上; - 通知 Chromium 内核渲染该
RenderLayer
; - Chromium 渲染该
embed
节点并上屏。
参考资料
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END