HTML5迟来的API:Page Visibility | Tencent AlloyTeam

一开始先看个小小demo切换tab对比下!

不得不说,浏览器的多tab(and多窗口)设计确实是满足了用户同时浏览很多个网页的需求,但是,网上有成千上万的页面,这些页面性能又参差不齐,对于某些性能很差的页面,用户停留在这个页面倒还好,但是当用户切换了到了其他tab页时,有可能会出现由于性能差的页面卡死导致整个浏览器卡死甚至机器卡死,其他页面好冤,浏览器好冤,机子好冤[汗]。

多tab固然是好,但是即使用户打开了N个tab窗口,他看的永远只是一个tab,其他不是激活态(按API,应该是叫隐藏)的tab虽然没用被用户关注到,但是它照样再跑,该计算的还得计算,改占的内存并不会少,这明显是造成了很大的资源浪费,作为网页开发者的我们,如果是知道了用户已经不再关注我们的页面,一些耗性能的操作当然可以停掉了(比如canvas的绘图,动态拉取feeds等,这种情况我觉得在网页游戏里面应该较多见),当用户切换回页面时,之前状态就可以恢复,可以说毫不影响用户体验。

这其中,最关键的是一个环节:开发者如何知道所开发的页面被用户关注了?HTML5的Page Visibility API提供了这种可能!但是我觉得在这个时候作为H5的标准提出来明显是迟了,应该在tab设计之初就应该有此API或者相关的方案,如果大家都按照此方式组织代码,我们有理由相信浏览器的内存占用会大幅减少。

支持page visibility的浏览器在document上添加一个hidden属性(不同浏览器可能需要前缀,如webkitHidden),看当前tab页是否激活,激活(focus)时document.hidden属性是false,否则是true,一下这段代码能用来检测浏览器是否支持pagevisivility并读取document的hidden值:

function getHiddenProp() {
	return 'hidden' in document ? 'hidden' : function() {
		var r = null;

		['webkit', 'moz', 'ms', 'o'].forEach(function(prefix) {
			if((prefix + 'Hidden') in document) {
				return r = prefix + 'Hidden';
			}
		});

		return r;
	}();
}

document还会添加一个visibilityState属性,该属性有4个可能值,分别如下:

hidden:当浏览器最小化、切换tab(the page is on a background tab)、电脑锁屏时visibilityState值是hidden

visible:当浏览器顶级context(top level browsing context)的document至少显示在一个屏幕(screen)当中时,返回visible;当浏览器窗口没有最小化,但是浏览器被其他应用遮挡时,visibilityState值也是visible

prerender:文档加载离屏(is loaded off-screen)或者不可见时返回prerender,浏览器可选择性的支持这个属性(not all browsers will necessarily support it)

unloaded:当文档(document)将要被unload时返回unloaded,浏览器可选择性的支持这个属性

此外就是事件支持,document上会添加visibilitychange事件,当UA的顶级document可见性(visibility)改变时触发:

document.addEventListener(bPrefix + 'visibilitychange', function onVisibilityChange(e) {
	//do some thing...
});

bPrefix是浏览器前缀,如webkit。

总体来说,page visibility的内容很少,也很简单,但是窃以为很有用,比如我们在做视频页面时,tab是hidden状态时,我们可以去努力拉取视频内容,播放可以停止,当用户切回来时开始播放;又比如我们可以配合H5的桌面通知(Notifications)API,保证只在使用了Notifications的页面可以收取桌面通知,在此页面visibilityState不是visible时不干扰用户等等。。

最后,enjoy it!

参考:

1.W3C PageVisibility API Spec

2.Using the PageVisibility API