在我们开发的任何类型的 javascript 应用程序中都可能存在
功能或应用程序中的任何更改根据
当前用户可见性状态,这可能是暂停正在播放的视频
当用户 ALT+TAB 切换到不同窗口时,跟踪有关如何进行的统计信息
用户与我们的应用程序交互,他多久切换到
不同的标签,他需要多长时间才能返回以及很多
可以从这种 API 中受益的性能改进。
页面可见性 API 为我们提供了两个顶级属性:
document.hidden (布尔值) 和 document.visibilityState (可以是
这些字符串中的任何一个:“隐藏”、“可见”、“预渲染”、“已卸载”)。
如果没有我们可以听到的活动,这还不够好
不过,这就是为什么 API 还提供了有用的visibilitychange
事件。
因此,这是一个关于我们如何对可见性采取行动的基本示例
改变:
function handleVisibilityChange() {
if(document.hidden) {
// the page is hidden
} else {
// the page is visible
}
}
document.addEventListener("visibilitychange", handleVisibilityChange, false);
我们还可以检查 document.visibilityState 值。
处理供应商问题 George Berkeley 作者:John Smibert
某些浏览器上的某些实现仍然需要
属性甚至事件名称都是供应商前缀的,这意味着我们
可能需要监听 msvisibilitychange 事件或检查
document.webkitHidden 或 document.mozHidden 属性。为了
为此,我们应该检查是否设置了任何供应商前缀属性,并且
一旦我们知道当前浏览器中使用的是哪一个(仅当
需要前缀),我们可以命名事件和属性
适当地。
以下是如何处理这些前缀的示例方法:
var browserPrefixes = ['moz', 'ms', 'o', 'webkit'];
// get the correct attribute name
function getHiddenPropertyName(prefix) {
return (prefix ? prefix + 'Hidden' : 'hidden');
}
// get the correct event name
function getVisibilityEvent(prefix) {
return (prefix ? prefix : '') + 'visibilitychange';
}
// get current browser vendor prefix
function getBrowserPrefix() {
for (var i = 0; i < browserPrefixes.length; i++) {
if(getHiddenPropertyName(browserPrefixes[i]) in document) {
// return vendor prefix
return browserPrefixes[i];
}
}
// no vendor prefix needed
return null;
}
// bind and handle events
var browserPrefix = getBrowserPrefix();
function handleVisibilityChange() {
if(document[getHiddenPropertyName(browserPrefix )]) {
// the page is hidden
console.log('hidden');
} else {
// the page is visible
console.log('visible');
}
}
document.addEventListener(getVisibilityEvent(browserPrefix), handleVisibilityChange, false);
其他问题“页面可见性”存在一个具有挑战性的问题
定义:如何确定应用程序是否可见
另一个窗口的窗口焦点丢失,但实际的窗口焦点没有丢失
屏幕上的可见性?不同类型的可见性怎么样
丢失,如 ALT+TAB、WIN/MAC 键(开始菜单/破折号)、任务栏/dock
操作、WIN+L(锁定屏幕)、窗口最小化、窗口关闭、选项卡
交换。移动设备上的行为怎么样?
我们可能会通过很多方式失去或获得知名度,而且很多
浏览器和操作系统之间可能的交互,因此我
不认为有一个正确且完整的“可见页面”定义
W3C 规范。这是我们得到的 document.hidden 的定义
属性:
隐藏属性 获取时,隐藏属性必须返回 true,如果
顶级浏览上下文(根窗口
在浏览器的视口中)[HTML5]根本不可见。这
如果顶层包含 Document,则属性必须返回 false
浏览上下文在至少一个屏幕上至少部分可见。
如果 Document 的 defaultView 为 null,则在获取时隐藏
属性必须返回 true。
为了适应通常是全屏但
仍然显示页面视图,如果适用,此属性可以
当用户代理未最小化但已完全最小化时返回 false
被其他应用程序遮挡。
我发现活动实际时间存在一些不一致之处
例如(Chrome 41.0.2272.101 m,在 Windows 8.1 上)触发该事件
当我 ALT+TAB 切换到不同的窗口/程序时,也不会触发
再次按 ALT+TAB 返回,但如果我按 CTRL+TAB 然后它会被触发
CTRL+SHIFT+TAB 在浏览器选项卡之间切换。当我的时候它也被解雇了
单击最小化按钮,但如果窗口未打开,则不会触发该按钮
最大化,然后单击浏览器后面的编辑器窗口
窗户。所以这个API的行为和它不同
实施仍然模糊。
解决这个问题的方法是利用更好的优势进行补偿
实现了焦点和模糊事件,并制定了自定义方法
使用内部标志来防止整个“页面可见性”问题
多次执行,这就是我想出的:
var browserPrefixes = ['moz', 'ms', 'o', 'webkit'],
isVisible = true; // internal flag, defaults to true
// get the correct attribute name
function getHiddenPropertyName(prefix) {
return (prefix ? prefix + 'Hidden' : 'hidden');
}
// get the correct event name
function getVisibilityEvent(prefix) {
return (prefix ? prefix : '') + 'visibilitychange';
}
// get current browser vendor prefix
function getBrowserPrefix() {
for (var i = 0; i < browserPrefixes.length; i++) {
if(getHiddenPropertyName(browserPrefixes[i]) in document) {
// return vendor prefix
return browserPrefixes[i];
}
}
// no vendor prefix needed
return null;
}
// bind and handle events
var browserPrefix = getBrowserPrefix(),
hiddenPropertyName = getHiddenPropertyName(browserPrefix),
visibilityEventName = getVisibilityEvent(browserPrefix);
function onVisible() {
// prevent double execution
if(isVisible) {
return;
}
// change flag value
isVisible = true;
console.log('visible');
}
function onHidden() {
// prevent double execution
if(!isVisible) {
return;
}
// change flag value
isVisible = false;
console.log('hidden');
}
function handleVisibilityChange(forcedFlag) {
// forcedFlag is a boolean when this event handler is triggered by a
// focus or blur eventotherwise it's an Event object
if(typeof forcedFlag === "boolean") {
if(forcedFlag) {
return onVisible();
}
return onHidden();
}
if(document[hiddenPropertyName]) {
return onHidden();
}
return onVisible();
}
document.addEventListener(visibilityEventName, handleVisibilityChange, false);
// extra event listeners for better behaviour
document.addEventListener('focus', function() {
handleVisibilityChange(true);
}, false);
document.addEventListener('blur', function() {
handleVisibilityChange(false);
}, false);
window.addEventListener('focus', function() {
handleVisibilityChange(true);
}, false);
window.addEventListener('blur', function() {
handleVisibilityChange(false);
}, false);
我欢迎有关此解决方法的任何反馈。其他一些很棒的来源
有关此主题的想法:
使用页面可见性 API 更有效地使用 PC 硬件
HTML5:新的 Web 性能 API,第 2 部分页面简介
Visibility API 结论 Web 技术不断发展
不断发展,我们仍在从黑暗的过去中恢复过来,那里的桌子
标记之王,语义并不重要,而且它们也不是任何
关于浏览器如何呈现页面的标准。
我们推动这些新标准很重要,但有时我们的
发展的要求使我们还需要适应这些
转换,通过处理供应商前缀,在不同的环境中进行测试
浏览器和不同的操作系统或依赖第三方工具来正确
识别这种差异。
我们只能希望 W3C 规范的未来
浏览器开发团队严格修改、严格执行,
也许有一天我们会有一个共同的工作标准
和。
至于页面可见性 API,我们稍微引用一下乔治·伯克利 (George Berkeley)
并说:
“可见”是被感知。