微信扫描登录
或者
请输入您的邮件地址来登录或者创建帐号
提 交取 消
GITBOOK.CN需要您的浏览器打开cookies设置以支持登录功能

mui-最接近原生体验的框架

2016年3月,ITA1024推出的前端技术专题月,邀请业界最顶级的前端技术专家针对前端开发,前端框架,性能调优,复合型前端技术等热门话题展开深入的分享和交流。通过每周的万人课堂和每月的ITA1024互联网技术开放日,精挑细选自国内顶级技术精英团队,分享的干货内容做到只讲经历,不讲道理。

如下是在线万人课堂分享实录。

大家好,我是DCloud公司的前端负责人崔红保,很高兴有机会给大家分享mui框架。首次参加这种文字直播的分享,描述不清楚的地方,大家可以在会后狠狠地提问。

我今天分享的主题,主要包括如下内容:
1、mui框架介绍
2、mui框架如何保证高性能体验
3、利用mui实现多端发布
4、DCloud还为HTML5开发者提供那些产品服务

1. mui简介

1.1 缘起

mui框架在2014.05立项,2014.08在iweb峰会上发布,我们不是闲着没事,重复制造轮子,只是实在没有适合mobile开发的前端框架:
1、基于jq的jqmobile,性能低的无法忍受,且UI难看
2、bootstrap这种响应式设计,性能在低端机不足,而且UI风格一看就是网页,不是App的感觉。
3、framework7当时只能在iPhone上运行也无法被接受。
4、基于angular的ionic,把pc端很重的东西引入到移动App中,且angular学习门槛较高。

看来看去ratchet框架还比较接近我们想要的高性能App框架,但发展理念和我们不同,我们是要求极致化的考虑App的性能。因此,我们撸起袖子,基于ratchet大幅改造实现了第一版的mui。

发展了一年半,目前mui已较完善,基于mui的app数量可统计的有20多万了,在360、大众点评、网易、京东等公司都有App使用了我们的框架。mui在github上的star数看起来不多,是2500+,希望今天过后这个数字能大幅上涨☺

附上mui的地址:https://github.com/dcloudio/mui

1.2 Mui的特点

小巧 mui不依赖任何第三方js库,核心js只有几十K;mui的核心是一个ui框架,并不是一个JS库,因此mui在实现上有所为、有所不为;mui框架中的js代码,均是为了ui组件服务,没有常用DOM操作等封装,这是mui和jQuery的区别。另外jq等框架是因为ie6-11的兼容性问题而壮大起来的,手机上都是webkit,没有引入jq的必要性,原生js很好用;

enter image description here

mui的ui设计理念是:以iOS为基础,补充Android平台特有的控件;因此mui封装的控件,ui上更符合app的体验。

高性能 这是mui的重要特点,后续会单独讲述。

丰富模板 mui在逐步解决性能问题的基础上,开始封装了一系列的ui模板,比如首次启动欢迎页面,这个功能通过mui做的话可能几行代码就出来了;

enter image description here

如下为手机通讯录模板,常用于是通讯录、城市选择等场景,支持右侧滑动字母快速选择。

enter image description here

2. mui框架如何解决性能问题

对于前端性能优化,大多数方法论是基于web的,比如压缩js、css,减少带宽请求;合并文件,减少网络请求次数;我们不谈这些常规的基于web的优化技巧,单独说说针对app,mui是如何实现性能优化的。

2.1 卡头卡尾及快速回弹滚动

在native app中,内容区域和顶部标题栏是不同的组件,内容区域的滚动条不会透穿标题栏;但使用HTML5开发mobileapp时,默认的body滚动条会透穿标题栏,这样的UI不符合app体验;通常的解决方案是使用DIV滚动(区域滚动),但DIV滚动是个大坑,我们简单回顾一下其历史: •最早版本:iOS/Android均不支持非body元素的滚动 •iOS 5.0版本:支持区域滚动,滚动条可见 •Android 4.0:支持区域滚动,滚动条可见 •Android 4.1.x:支持区域滚动,滚动条不可见 •Android 4.4:支持区域滚动,滚动条可见

虽然区域滚动在不同版本上有各种问题,但body的原生滚动却一直很流畅;因此我们的解决思路是: • 将标题栏和内容区分别放到2个webview中 • 内容区使用body原生滚动;

Hello mui的首页其实就是index.html加list.html合并而成的,如下图:

enter image description here

为了方便工程师开发,我们封装了mui.init(subpages:{})方法,可以快捷创建子webview。

这里要引入一个概念,就是mui可以调用原生加速。在App开发中,js代码是和hybrid引擎一起打包成apk、ipa发布的,不是运行在浏览器里,此时引擎的原生操作能力要被充分发挥出来。

mui就是利用对原生的webview的操作能力,实现了在App中更流畅的体验。当然mui在普通浏览器里也可以运行上面的代码,这个是mui如何多端发布,后续会专门讲。

2.2 切页白屏和转场动画

传统的web开发,点击href跳转,会立即显示一个空白页面,然后看到页面的渲染绘制过程,这就是常说的“白屏等待”现象,这个是不符合App体验的;为了解决这个问题,部分框架推出了SPA(Single-pageapplication)方案,在一定程度上缓解了这个问题。

但SPA模式也有其短板:
1、DIV的动画模拟页面切换,在页面复杂时,会出现卡顿现象;
2、通过JS频繁操作DOM,VIEW切换时动态添加、删除事件监听,在低端机上会经常碰到性能问题,甚至出现浏览器崩溃。

MUI针对切页白屏的解决方案:
1、预加载和预渲染新界面,在背景创建webview加载新页面,点击跳转时,直接显示之前创建好的webview,因为已提前加载渲染,因此显示时不会白屏;
2、显示动画使用原生view动画,避免DIV动画的卡顿情况;
3、如果觉得还不够好,mui还提供预截图API,提前对预加载的webview进行截图(预截图),页面切换时直接使用截图代替webview的移动,毕竟图片移动动画的资源消耗要远低于view的移动动画资源消耗。

2.3 下拉刷新

DIV模拟的下拉刷新为什么会卡顿?在这里先带大家复习一下web页面的渲染过程,如下图:

enter image description here

主要流程:
1、JS代码执行:比如设置元素的位置属性;
2、样式计算:根据CSS选择器,对每个DOM元素匹配对应的CSS样式。
3、布局:计算每个DOM元素最终在屏幕上显示的大小和位置。web页面中元素的布局是相对的,因此一个元素的布局发生变化,会联动地引发其他元素的布局发生变化,特别是其子元素和孙子元素。
4、绘制:本质上就是填充像素的过程。包括绘制文字、颜色、图像、边框和阴影等,也就是一个DOM元素所有的可视效果。一般来说,这个绘制过程是在多个层上完成的。
5、渲染层合并:由上一步可知,对页面中DOM元素的绘制是在多个层上进行的。在每个层上完成绘制过程之后,浏览器会将所有层按照合理的顺序合并成一个图层,然后显示在屏幕上。

知道了如上渲染流程,我们就不难理解为何DIV模拟实现的下拉刷新容易发生卡顿现象;随着手指的移动,JS不停更改拖动区域的top属性,然后不停引发后续的布局、重绘、渲染层合并;

mui的解决思路:
1、把一个页面拆分成两个webview,拖动的时候只拖动内容区的webview,拖动过程中webview位置变化,但webview内DOM元素位置不变,因此有效避免页面的布局、重绘操作;
2、拖动及回弹效果均采用原生动画实现,这就保证了原生的流畅体验。

2.4 硬件加速那些坑

很多同学都知道,若想动画流畅,需要启动硬件加速!但硬件加速也不能乱用。

enter image description here

这样相当于将.content下所有元素全部设置了GPU加速,即使是一个没有任何动画的静态元素;我们删除该css定义后,Andriod性能大幅提升。

接着发现在列表数据较多时,iOS平台的侧滑菜单很容易crash,Android终端反而没问题;测试之后在需要执行transform动画的元素父元素之上增加如下定义,就解决了iOS的crash问题:

enter image description here

增加的这两行css定义解决了iOS的crash问题,却引发部分Android终端的transform不渲染,因此该样式还需修改成仅iOS平台生效。

2.5 click延迟及事件透传

300毫秒的由来 2007年初,苹果公司在发布首款iPhone前夕,遇到一个问题:当时的网站都是为大屏幕设备所设计的,不适合手机屏幕的阅读;为了解决这个问题,苹果的工程师们做了一些约定,这当中最出名的,当属双击缩放(double tap to zoom),具体方案:iOS Safari监听用户点击操作,在双击后准确地定位到页面主体文章,并将其缩放至适合比例展现。

那么问题来了,当用户点击屏幕上的一个链接时,浏览器并不能判断用户确实是要打开当前链接,还是要双击放大;因此,iOS Safari就等待300毫秒,以判断用户是否再次点击了屏幕;若有再次点击则触发双击放大;否则,触发单击逻辑,手机浏览器的点击300毫秒延时从此而生。

浏览器厂商的解决方案 优化这个延迟问题,浏览器也在积极采取措施,比如chrome通过meta禁用缩放:

这个方案的最大问题是:完全禁用了页面元素缩放,当你想缩放显示图片时,就无法操作;

然后Chrome团队接着宣布:他们将在包含width=device-width或者置为比viewport 值更小的页面上禁用双击缩放。当然,没有双击缩放就没有300 毫秒点击延迟;这个方案虽妙,但毕竟只有Chrome支持,且有版本限制;iOSsafari除了双击缩放,还有双击滚动功能,双击问题存在,300毫秒就存在。

mui框架的解决方案 监听手机浏览器的touch事件,通过touch持续时间及移动距离来识别单击(tap)事件,当这两个值都小于特定阀值时,则触发单击(tap)事件。 •touch持续时间:touchend/touchcancel触发时间-touchstart时间 •移动距离:tohchmove事件中屏幕位置和touchstart事件中屏幕位置之间的直线距离

事件透传

问题描述:单击(tap)遮罩蒙版时,事件透传到蒙版下层的DOM元素上;比如Action sheet下方有一个链接,当点击Actionsheet控件时,会触发下层a标签的href跳转;

原因:还是300毫秒惹的祸,tap立即触发,很快关闭了遮罩层;但浏览器在300毫秒后才触发click事件,此时根据屏幕位置计算,event.target就刚好是下层的a标签,因此触发了a的默认行为href跳转。

mui解决方案: 关闭遮罩时,仅修改遮罩的透明度,并不真的关闭遮罩;等待350毫秒后,再真实关闭遮罩,这样300毫秒后,click事件触发时目标元素依然是遮罩层,从而避免click事件透传到下层的a标签;

2.6 更多底层API调用

除了webview、截图这些API操作,mui事实上可以调用Android和iOS的40多万原生API,在能力上基本与原生相同。包括拦截短信认证码、调用原生推送、扫描二维码都不在话下。

3. 多端发布

背景:大家刚才看到了mui在打包App时可以调用原生能力提升App体验,但有人会问,那岂不是无法在普通浏览器里运行了?所以mui引入了多端发布理念,通过另一种方式实现跨平台。 概念:一套基于mui的HTML5工程,通过框架的自适应和前端构建工具条件编译双管齐下,实现同时发行到iOSAppStore、安卓各大应用商店、普通手机浏览器、微信App、百度直达号和360流应用,并且并且,在每个平台上都能调用该平台的专有API达到原生体验。

Mui框架本身是支持多端发布的,Hello mui是一个WAP、流应用、Android app、iOS app一套代码多端均可使用的示例,可参考Hello mui的代码,也可以直接访问http://www.dcloud.io/hellomui体验。

实现方案示例—打开新窗口: 使用过mui的同学知道,开发App时,使用mui.openWindow()方法会创建或显示一个新的webview;但在WAP或微信中,没有webview窗口,如何实现页面切换呢?此时mui会自动降级变成href跳转;

实现方案示例—子窗口: 为了流畅的滑动体验,mui不推荐使用DIV区域滚动,若有长列表时,建议使用mui.init(subpages:{})创建子webview,然后在子webview中使用原生滚动;同样的问题,为了兼容WAP和微信,mui在这两个平台,会计算位置并创建iframe,将子页面内容显示到iframe中。

之所以引入构建工具做条件编译,而不是全部在框架里动态判断,是因为把判断放在用户操作之前,能大幅减少用户等待。

总结下与纯SPA框架的对比。 mui不排斥SPA,在mui里我们也适度引入了SPA,但对比其他纯SPA的前端框架,mui的设计思路是与他们不同的。纯SPA也能开发一次到处使用,但无法在App环境下达到原生级的体验。Mui的多端发布,同样也是跨平台,但在执行性能、充分调用引擎能力上都有更强的优势。

4. DCloud还为HTML5开发者提供那些产品服务

4.1 HBuilder

Hbuilder是DCloud提供的极客型HTML5开发IDE,它应该是目前写前端代码最快的编辑器,它的AST语法分析和提示系统也是世界级的。

工具是免费的,没有增值收费项目。

4.2 流应用

流应用是我们做的一个很酷的、有突破性的东西。

一般的App在应用市场下载时是下载按钮,点击后需要一分钟左右、点击数次,app才能启动。但流应用是可以直接秒开的。

流应用,其实是把使用mui开发的、原本打包为apk发行的那些文件,压缩和改造了包格式,使得安装包可以边用边下,一个流应用一般4秒左右就可以安装启动。 见下图,在360手机助手里搜索大众点评外卖,可以看到下载按钮变成秒开按钮:

enter image description here

M站也可以方便的转换为流应用,参考:http://ask.dcloud.net.cn/article/537。

但今天时间有限,这些好玩的东西无法一一分享,这里是一些体验视频。

视频1 应用市场秒开流应用 http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_i0171dyo7cf.html

视频2 快码,扫描立即秒装app http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_w0171ems73j.html

视频3 分享,通过社交网络快速传播app http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_r0171bswy6f.html

视频4 流应用不是web网页,断网时照样使用 http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_k0171y6vfyu.html

视频5 推送流应用 http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_k0171y6vfyu_x01833hx4q3.html

我的分享到此结束,大家有问题,可以稍后提问,我和我的同事会尽力回答。

————Q&A————

1问:多端生成的话,不知道会不会有冗余代码的风险呢?

1答:因为有gulp/grunt构建工具,可以提前编译不同平台版本,不会存在冗余代码

2问:最近使用mui想做关于wap的,在实现子页面a,b之间的切换的时候,无法通过openWindow里面的aniShow实现动画切入,通过您的分享知道wap没有webview,那我想实现子页面之间的动画切换应该如何实现?

2答:mui.openwindow在wap上降级为href页面跳转,无动画;如果想实现动画,可以考虑spa模式,mui也有spa的示例(setting模板)

3问:WAP上窗口切换没有动画吧,也不需要动画吧?

3答:wap上窗体切换走动画只能使用spa方式,但在低端机会有点卡,建议wap上就不用动画了

4问:请问mui相较react native的优势是什么呢?

4答:一种是重订语法重写引擎,一种是把HTML5不流畅的部分使用原生动画补齐。很明显后者的方向更靠谱。一个HTML5移动站,通过5+略加改造就可以变成原生体验的App。但如果是react native,就需要重头学重头写,代价高昂,收益却没有提升多少。 功能:5+远大于react native 性能:两者各有千秋,5+的plus扩展部分>react native>纯HTML5部分 包体积:5+远小于react native OS支持范围:5+大于react native 国内开发者支持:5+优于react native 长期演进生命力:react native像过渡产品,随着手机硬件的提升,该项目存在的意义在下降。更多请参考链接 http://ask.dcloud.net.cn/question/2900

5问:iframe用在WAP里不会有什么兼容问题吧?

5答:iframe在app里坑有点多,但在wap上还是可以商用的

6问:如果一个页面使用了原生的api,多端发布时,在web端是怎么处理的?

6答:通过构建工具创建多个task,发布web端task时,剔除原生API源码文件,仅编译适合web端的代码

7问:android下,调用原生的视频播放器播放视频,想要定时关闭,可惜一致没有找到关闭的方法?

7答:这得看视频播放器的api有没有关闭API

8问:JS和后台Android,iOS的交互,是用的WebViewJavascriptBridge还是都是直接采用源生的API调用?

8答:WebViewJavascriptBridge是我们使用的一种,同时还有其他调用方式

9问:原生做的头和尾部,mui做的内容页面,跳转动画可以控制吗?

9答:中间的webview动画可以控制,原生view的动画也可以控制,但动画同步问题可能存在

10问: 采用构建工具多终端发布,工具什么时候开放出来,还是需要自己去适配其他平台API?

10答:所谓构建工具就是gulp/grunt/webpack等,直接利用就好了。

11问:2.7mui版本还有穿透问题,不知是只针对遮照层还是全部的图层?

11答:目前仅处理了遮罩蒙版。

12问:流应用现在只有360支持吧?

12答:流应用在360可发行,在DCloud自己的平台也可以发行。流应用的用户来源有两块,一块来自于我们给开发者导量,大家可以看最后一个push的视频, http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_k0171y6vfyu_x01833hx4q3.html 导量是非常猛的。流应用第二块用户来源是开发者自己的wap站导量。在开发者的wap站内嵌一个我们的js,可以检测手机上有没有流应用引擎,如果有的话,可以自动把wap站流量转换为流应用app流量。因为我们有一亿多装机量,目前在某一线互联网公司wap站测试,每3个Android访问有一次命中流应用引擎

13问:流应用还不太了解,不过我想知道一下,APP更新的时候是否可以使用咱们的流应用技术呢?

13答:DCloud提供了差量更新技术,可以直接用。http://ask.dcloud.net.cn/article/199

14问:mui还有些什么Todo要去做的?

14答:mui已经发展了1年半,经历了很多app开发考验,目前已稳定。未来方向主要优化文档和强化简化多端发布。

【本文系ITA1024原创首发,转载或节选内容前需获授权(授权后一周以后可以转载),且注明来源:ITA1024在线技术分享实录。欢迎更多互联网研发团队与ITA展开内容合作,欢迎个人技术原创投稿。投稿及授权联系邮箱:openday@ita1024.com,联盟微信:ita1024k,官网:www.ita1024.com】