是否有一种可靠的跨浏览器方法来检测标签是否有焦点。

这个场景是,我们有一个定期轮询股票价格的应用程序,如果页面没有焦点,我们可以停止轮询并节省所有人的交通噪音,特别是当人们喜欢打开不同投资组合的几个选项卡时。

是窗口。打开模糊和窗口。Onfocus这个选项?


当前回答

我会这样做(参考http://www.w3.org/TR/page-visibility/):

    window.onload = function() {

        // check the visiblility of the page
        var hidden, visibilityState, visibilityChange;

        if (typeof document.hidden !== "undefined") {
            hidden = "hidden", visibilityChange = "visibilitychange", visibilityState = "visibilityState";
        }
        else if (typeof document.mozHidden !== "undefined") {
            hidden = "mozHidden", visibilityChange = "mozvisibilitychange", visibilityState = "mozVisibilityState";
        }
        else if (typeof document.msHidden !== "undefined") {
            hidden = "msHidden", visibilityChange = "msvisibilitychange", visibilityState = "msVisibilityState";
        }
        else if (typeof document.webkitHidden !== "undefined") {
            hidden = "webkitHidden", visibilityChange = "webkitvisibilitychange", visibilityState = "webkitVisibilityState";
        }


        if (typeof document.addEventListener === "undefined" || typeof hidden === "undefined") {
            // not supported
        }
        else {
            document.addEventListener(visibilityChange, function() {
                console.log("hidden: " + document[hidden]);
                console.log(document[visibilityState]);

                switch (document[visibilityState]) {
                case "visible":
                    // visible
                    break;
                case "hidden":
                    // hidden
                    break;
                }
            }, false);
        }

        if (document[visibilityState] === "visible") {
            // visible
        }

    };  

其他回答

重要编辑:这个答案已经过时了。在编写它之后,引入了可见性API (mdn,示例,规范)。这是解决这个问题更好的办法。


var focused = true;

window.onfocus = function() {
    focused = true;
};
window.onblur = function() {
    focused = false;
};

AFAIK,焦点和模糊都支持…所有东西。(见http://www.quirksmode.org/dom/events/index.html)

奇怪的是没有人提到document.hasFocus

if (document.hasFocus()) console.log('Tab is active')

MDN有更多信息。

一个React钩子版本,基于上面所有这些优秀的先生们的回答:

import { useEffect, useState } from 'react';

const EVENT_NAME = 'visibilitychange';

export const useTabFocus = () => {
    const [hasFocus, setHasFocus] = useState(isVisible());

    useEffect(() => {
        const onVisibilityChange = () => {
            setHasFocus(isVisible());
        };

        document.addEventListener(EVENT_NAME, onVisibilityChange);

        return () => {
            document.removeEventListener(EVENT_NAME, onVisibilityChange);
        };
    }, []);

    return hasFocus;
};

const isVisible = () => document.visibilityState === 'visible';

是的,窗户。Onfocus和window。Onblur应该适用于你的场景:

http://www.thefutureoftheweb.com/blog/detect-browser-window-focus

在搜索这个问题时,我发现了一个建议,即应该使用Page Visibility API。根据Can I Use: http://caniuse.com/#feat=pagevisibility,大多数现代浏览器都支持此API。

下面是一个工作示例(从这个代码片段派生出来):

$(document).ready(function() {
  var hidden, visibilityState, visibilityChange;

  if (typeof document.hidden !== "undefined") {
    hidden = "hidden", visibilityChange = "visibilitychange", visibilityState = "visibilityState";
  } else if (typeof document.msHidden !== "undefined") {
    hidden = "msHidden", visibilityChange = "msvisibilitychange", visibilityState = "msVisibilityState";
  }

  var document_hidden = document[hidden];

  document.addEventListener(visibilityChange, function() {
    if(document_hidden != document[hidden]) {
      if(document[hidden]) {
        // Document hidden
      } else {
        // Document shown
      }

      document_hidden = document[hidden];
    }
  });
});

更新:上面的例子曾经为Gecko和WebKit浏览器提供前缀属性,但我删除了这个实现,因为这些浏览器已经提供了一段时间没有前缀的页面可见性API。为了与IE10兼容,我保留了微软特有的前缀。