微信小程序中WebView中原生组件限制问题解析

背景

在微信的文档中有一个章节说明了『 原生组件的使用限制 』有这么一段话html

『因为原生组件脱离在 WebView 渲染流程外,所以在使用时有如下限制:

原生组件的层级是最高的,因此页面中的其余组件不管设置 z-index 为多少,都没法盖在原生组件上。
后插入的原生组件能够覆盖以前的原生组件。
原生组件还没法在 scroll-view、swiper、picker-view、movable-view 中使用。
部分CSS样式没法应用于原生组件,例如:
没法对原生组件设置 CSS 动画
没法定义原生组件为 position: fixed
不能在父级节点使用 overflow: hidden 来裁剪原生组件的显示区域
原生组件的事件监听不能使用 bind:eventname 的写法,只支持 bindeventname。原生组件也不支持 catch 和 capture 的事件绑定方式
在iOS下,原生组件暂时不支持触摸相关事件。
在工具上,原生组件是用web组件模拟的,所以不少状况并不能很好的还原真机的表现,建议开发者在使用到原生组件时尽可能在真机上进行调试。』

解析

所谓的原生组件,即非Web组件系统扩展Native组件。由于小程序在视图渲染层面使用了WebView,而在Video,Map这类组件,使用WebView的WebCore渲染以后体验不佳的诟病一直存在,并且标准不一。小程序上因使用原生的WebView进行渲染,而不是用修改的WebView内核(至少在iOS上没有这么干),而没法对web原生标签扩展。基于用户体验,和坑爹的技术限制,小程序提出了原生组件的概念,也就是在WebView上面使用原生组件填充占位元素的方式修补这类组件用户体验问题。由于WebView和原生组件在应用层自己就不是一个渲染层级,因而出现Web上面的标签没法浮于Video之上(直播应用的恶梦),在不修改技术思路的前提下,position: fixed, overflow: hidden这样的属性是不可能用于原生组件的样式的。不过伪同层渲染也不是说不可能,即在渲染原生组件时候根据层级镂空面积。web

特别在Map上使用WebView做为渲染以后体验不佳的诟病一直存在,特别是地图上marker标记过多的重度场景下,笔者所在的公司的在使用高德地图Web端提供出来的C端具有反人类的体验,地图拖拉龟速,点击响应缓慢,加载loading地图区域等待时间过长。而Video则支持的格式有限,列出部分浏览器的支持的以下:小程序

Firefox:支持 Ogg Vorbis和WAV 
Opera :支持Ogg Vorbis和WAV 
Safari :支持MP3,AAC格式 ,和MP4 
Chrome :支持Ogg Vorbis,MP3,WAV,AAC和MP4 
Internet Explorer 9+ :支持MP3,AAC格式 ,和MP4 
IOS :支持MP3,AAC格式 ,和MP4 
Android :支持AAC和MP3

上述,能够知道视频支持有限(限于版权)。而就咱们关注的移动端iOS和Andoroid,实现一个视频播放,咱们可能都会有如下几点的需求:
一、全屏处理;
二、覆盖层效果;
三、自动播放;
四、播放控制;
五、隐藏播放控件;
在iOS上若是使用WebView,你没法修改全屏下的工具这一点体验已经足够让全部的产品经理抓狂,更不用说Android的这么多的机型。覆盖层效果在微信上不得不使用微信提供原生组件cover-view实现,而限于原生实现限制,cover-view的支持有限。微信小程序

设计方案

一、组件层于WebView层之上

这也应该是微信小程序团队现阶段使用的方案,经过特殊的占位标签,使用getBoundingClientRect获取组件位置,而原生组件跟随Webview滚动。
Talking is cheap. Show me your code,那么用代码实现的效果的以下。
now_lowest_gif.gif
从图中可见,覆盖层确实位于原生组件之下。浏览器

二、组件层于WebView层之下

此方式略微复杂。须要经过与Webview scroll联动的置于Webview之下的Component Layer实现,而Webview背景设置为透明。至于事件,经过Webview的事件透传,传递到Component Layer,须要经过缓存webview中元素再计算是否被点中经过重写hitTest方法实现。经过此技术方案实现的好处也是明显的,由于原生组件层不少时候都是置于最底层,而Web上的组件能够轻松覆盖于Native之上,无需使用cover-view之类的hack方法。
效果以下所示
图片发自简书App缓存

Tips

在iOS上还特别须要注意一点UIWebview的坑。在使用-webkit-overflow-scrolling 使用,你会发现momentum scroll阶段并不会触发scroll事件,并且 scrollTop 属性不会变化,固然getBoundingClientRect也一样失效。若是考虑使用touchmove 这样事件你也仅仅在手指还在屏幕上的时候触发,检测滚动区域内部元素的getBoundingClientRect 一样无效。微信

固然幸运的是,这么大一个坑只是发生在UIWebview,对WKWebview并无影响。ide

相关文章
相关标签/搜索