浏览器功能(1) - JS判定当前页面是否显示在最前面


问题起因

前段时间遇到个奇葩需求,需要窗口每次显示在浏览器最前面时,都调用接口重新获取服务器时间,以确保定时器时间的准确性(相对的准确性)。

既然有需求,那么就要想办法去实现。

1、使用 visibilitychange

浏览器标签页在 被隐藏或显示 时都会触发 visibilitychange 事件。这里的隐藏包括:1、浏览器最小化(包括手动最小化浏览器;清屏操作);2、当前标签页被其他内容遮挡(要全部遮挡,部分遮挡不算);3、浏览器切换标签页

既然标签页在 被隐藏或显示 时都会触发事件,那么我们就监听 visibilitychange 事件即可。

document.addEventListener('visibilitychange', function() {
  console.log(document.visibilityState)
  if (document.visibilityState == 'hidden') {
    console.log('隐藏')
    alert('隐藏页面')
  } else if (document.visibilityState == 'visible') {
    console.log('显示')
    alert('显示页面')
  }
})

2、使用onblur 和 onfocus

通过获取、失去焦点来判断页面是否在最前面。但这种方法有功能缺陷,详见下文。

 let count = 1
 window.addEventListener('focus', function() {
   // window获得焦点
   console.log('window获得焦点')
   console.log('window获得焦点计数:', ++count)
 })
 window.addEventListener('blur', function() {
   // window失去焦点
   console.log('window失去焦点')
   console.log('window失去焦点计数:', --count)
 })

1、浏览器对象(即window对象) 是有 onfocus 和 onblur事件可以监听,但触发这两个事件的前提是页面之前是focus过的。也就是说如果页面刚刚渲染完(如刷新或新加载等)且鼠标一直停留在页面内的,此时不管用户在页面上有没有操作,页面都不会正常监听这两个事件。

2、如果页面在打开状态下,但是触发了 onblur 之后并无页面操作的情况下也不会正常监听这两个事件。直到,用户操作页面触发focus,之后离开页面才会触发blur,再次点击到当前页面时才会触发focus,如此反复都会触发相应的事件。

触发onblur事件的情况:

1、在chrome浏览器下,点击console面板也会触发blur事件,同样的,前提是之前是focus的状态。

2、页面最小化。

3、浏览器切换tab页面。

4、页面中的任何弹窗。

5、focus状态下切换到其他应用。

3、使用mouseover和mouseout事件监听

但是这种方法也有问题,下文叙述。

4、可以通过document.hidden属性判断当前页面是否是激活状态。

兼容性:IE10+,Firefox10+,Chrome14+,Opera12.1+,Safari7.1+

兼容性写法示例:

var hiddenProperty = 'hidden' in document ? 'hidden' :    
    'webkitHidden' in document ? 'webkitHidden' :    
    'mozHidden' in document ? 'mozHidden' :    
    null;
var visibilityChangeEvent = hiddenProperty.replace(/hidden/i, 'visibilitychange');
var onVisibilityChange = function(){
    if (!document[hiddenProperty]) {    
        console.log('页面非激活');
    }else{
        console.log('页面激活')
    }
}
document.addEventListener(visibilityChangeEvent, onVisibilityChange);