AJax技术

提升HTML5的性能体验系列之一 避免切页白屏

字号+ 作者:H5之家 来源:H5之家 2017-05-08 17:05 我要评论( )

提升HTML5的性能体验系列之一 避免切页白屏 - 提升HTML5的性能体验系列文章目录导航:- [提升HTML5的性能体验系列之一 避免切页白屏]- 提升HTML5的性能体验系列

提升HTML5的性能体验系列文章目录导航:
- [提升HTML5的性能体验系列之一 避免切页白屏]
- 提升HTML5的性能体验系列之二 列表流畅滑动
- 提升HTML5的性能体验系列之三 流畅下拉刷新
- 提升HTML5的性能体验系列之四 使用原生UI(nativeUI)
- 提升HTML5的性能体验系列之五 webview启动速度优化及事件顺序解析

本文于2017年4月10日进行重大更新,之前阅读过本文的开发者请重新阅读。

窗体切换白屏的现实问题\n

HTML5的性能比原生差很多,比如切页时白屏、列表滚动不流畅、下拉刷新和上拉翻页卡顿。
在低端Android手机上,很多原生App常用的功能和体验效果都很难使用HTML5技术模拟。
我们首先来看第一个问题,如何避免切页白屏。

浏览器的页面在切换时,由于其页面加载机制,在跳转到下一个页面时,先要请求联网、载入页面代码、构建dom、渲染,最后才显示出来。
在最终结果渲染完毕前,会出现几十毫秒甚至数秒的白屏。原生App是没有这个问题的。
虽然使用SPA单页应用模型,即ajax+div切换也可以避免白屏,但把所有页面写在一个SPA页面里,简单几个页面还行。但页面多了手机上也跑不起来,初始化非常慢,首页必然白屏,而且工程大了代码那个乱。。。被坑过的人自然知道。

解决窗体切换白屏的4种方案\n

标准HTML5无法解决,我们就使用扩展的手段。
HTML5+是一套增强HTML5的规范,它可以用JS调用几十万原生API。
想要解决切页白屏这个问题,需要使用plus.webview类来做MPA多页应用(不是SPA单页应用)。
plus.webview类是对原生的webview对象的js化封装,使用js可以操作webview。
解决白屏的原理是:把每个页面当作一个webview,但用js来控制它就像控制div一样。动画时通过原生的view动画飘webview进来而不是通过css动画飘div进来
同时webview之间相互独立,不会出现SPA下不同页面js和css冲突的问题。

通过操作webview来避免切页白屏,有几种常见的做法:

- 1、动画先飘不会白屏的原生title进来\n

既然webview加载慢,转场动画会白屏。原生view加载快,不会白屏。那么能不能使用原生view呢,或者至少动画时先飘一个原生view的title进来,也不会整屏白屏。
HBuilder7.2起,提供了plus.nativeObj.View,也就是原生的view对象(以下简称nview),可以使用js向原生的view直接写字、绘图(注意是原生view不是webview)。
从HBuilder8.0起,进一步对title的原生化做了简化了操作,在plus.webview的style里,可以配置navigationbar(以下简称nbar),如下示例:

plus.webview.create('http://m.weibo.cn/u/3196963860', 'testid', {'navigationbar':{'backgroundColor':'#D74B28','titleText':'导航栏标题','titleColor':'#CCCCCC'}})
\n

这样创建webview时,会自带一个原生的title,文字、颜色、是否有返回箭头、分割线这些都可以设置,还可以通过getNavigationbar()方法得到一个nview对象,自由的向上面写字、绘图、处理点击响应。参考nview文档

在mui框架中,进一步简化封装了mui.openWindowWithTitle()方法,参考

上面title有了,中间空白处可以先转个plus.nativeUI.waiting的原生雪花或显示加载中,这样转场时就不会飘白屏了。
一般本地页面加载都很快,转场动画300毫秒结束时,页面也渲染出来了。

另外提供几个让HTML页面渲染快的方法
- 页面渲染尽量不用js做,想要渲染快,就直接写HTML和css渲染,js渲染的界面显示更慢。
- 少用padding、margin,避免错位重绘。比如界面绘制开始是一个样子,然后很快位置移动进行重绘,这样很低效,容易闪屏。
- 减少图片尺寸

延伸:既然有nview,那是不是可以使用nview做完整界面,废除webview?
DCloud一直遵循的是HTML5+的规范和理念,即不推翻HTML,而是在HTML做的不好的地方强化补足。
从技术角度,除了原生title,开发者当然在动画时扩大nview的区域甚至整屏nview,这样动画时可以迅速显示整屏内容。但DCloud认为这也仅限于动画时这一屏幕,完整的页面仍然应该是HTML的。

早些年mui曾推荐使用过head和body分开载入的方案,此方案已废弃,由这里描述的原生title方案替代。

- 2、预加载html\n

既然HTML渲染慢,是否可以后台预加载,需要使用时直接动画进来?
当然是可以的。所谓预载,即后台预载新页面的HTML文件及资源,使用时直接调出这个已经创建好的webview。
Hello mui、36kr等项目源码,都使用了预载思路。
以新闻类app为例,启动首先载入资讯列表list页面,然后后台创建了一个隐藏的webview,加载了一个内容模板content页面。
在点击list页面的一个新闻item时,调用webview的窗体控制动画,把content页面侧滑进屏幕。
但content页面仅仅是一个模板而没有数据,在content页面刚侧滑进屏幕时,在content页面有一个“加载中”的提示。
紧接着content页面开始执行ajax请求,联网加载数据并显示出来。
我们可以在list页面的item点击里,一边移动窗体,一边通知新页面执行ajax。webview间相互传递消息使用webview的evalJS方法。
示例代码如下:

var webviewContent;
document.addEventListener('plusready', function(){ //扩展的js对象在plusready后方可使用
webviewContent = plus.webview.create("content.html");
});
function clicklist (id) { //list点击item后的事件
webviewContent.show("slide-in-right",200);
}
\n

在mui框架里,对这个过程进行了简化封装,使用preload参数来控制。参考:

预加载,由于不显示出来,并不会过多增加资源占用。(同时显示在屏幕上的webview不要超过3个,隐藏在后台的webview不要超过10个)
如果是list转到content,不同的item点击只是一个页面,完全可以使用预载。
但如果页面不同且较多,后台预载太多webview会有点慢。这里的慢不是会造成手机慢,而是预载是耗时间的。
预载这些网页时手机CPU消耗比较高,此时如果滑动列表,会发现滑动不流畅。

-3、等待webview渲染后再做动画(不推荐)\n

如果不使用前2种方案,为了不让转场动画飘白屏,我们也可以先等待webview渲染,渲染完毕在做动画显示。
即点击准备进入新页面时,先在屏幕上显示一个原生雪花(plus.nativeUI.waitting),然后后台创建一个不显示的webview,等待webview渲染后再做动画进来。
但是等待渲染完毕再做动画终究是会造成动画启动慢,体验不好,官方还是推荐使用方案1和2的原生title和预载。

-4、高级技巧:预截图\n

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • php+html5+ajax实现上传图片的方法

    php+html5+ajax实现上传图片的方法

    2017-05-06 18:00

  • ajax技术 ajax方法

    ajax技术 ajax方法

    2017-04-17 14:01

  • ajax技术 load方法

    ajax技术 load方法

    2017-03-20 09:00

  • 基于IE10/HTML5 开发

    基于IE10/HTML5 开发

    2017-02-21 16:00

网友点评
-