“文档”类型上不存在属性“msHidden”

问题描述

我在使用选项卡可见性时收到此错误。其中“文档”类型不存在“msHidden”和“webkitHidden”

const TabVisibilityComponent = () => {
let hidden = null;
let visibilityChange = '';
const [action,setAction] = useState('show');
if (typeof document.hidden !== 'undefined') {
  hidden = 'hidden';
  visibilityChange = 'visibilitychange';
} else if (typeof document.msHidden !== 'undefined') {
  hidden = 'msHidden';
  visibilityChange = 'msvisibilitychange';
} else if (typeof document.webkitHidden !== 'undefined') {
  hidden = 'webkitHidden';
  visibilityChange = 'webkitvisibilitychange';
}

const handleVisibilityChange = () => {
  if (document.hidden) {
    setAction('hide');
  } else {
    setAction('show');
  }
};


useEffect(() => {
  document.addEventListener('visibilitychange',handleVisibilityChange,false);
  window.addEventListener(
    'focus',function() {
      setAction('show');
    },false,);
  window.addEventListener('blur',function() {
    setAction('hide');
  },false);
},[visibilityChange]);
return <p></p>;
};

export default TabVisibilityComponent;

我尝试在 'lib.dom.d.ts' 文件的 Document 界面中添加 'readonly msHidden: boolean',因为 hidden 工作正常,它是在该文件中声明为只读布尔值,因此对 msHidden 和 webkitHidden 尝试了相同的方法,但它不起作用。我已经看到很多人使用这个代码,但不知道我的错误是什么。如果有人对此有解决方案,我会很高兴!

解决方法

代码直接来自 MDN docs,所以代码本身是正确的。问题是:


  1. lib.dom 定义确实包含浏览器特定的属性。

解决此问题的一种方法是将文档作为参数传递给函数,该函数将这些属性定义为可选。

const hiddenPropName = (document: Document & {msHidden?: boolean; webkitHidden?: boolean}) => {
  if (typeof document.hidden !== "undefined" ) {
    return "hidden";
  } else if (typeof document.msHidden !== "undefined") {
    return "msHidden";
  } else if (typeof document.webkitHidden !== "undefined") {
    return "webkitHidden";
  }
  // not sure how to handle when none exist
}

但就 Typescript 而言,document.hidden 始终存在。

看起来 caniuse 上的带前缀和不带前缀的支持数字几乎没有任何区别。所以你可以放弃 msHiddenwebkitHidden


  1. 您忽略了您设置的 hiddenvisibilityChange 变量。

示例中代码的第一部分只是将变量 hiddenvisibilityChange 设置为属性的名称,以便它们稍后可以访问正确的属性。该示例使用 document[hidden],其中 hidden 是一个变量,但您使用了 document.hidden,它始终获取属性“hidden”,而不是“msHidden”或“webkitHidden”。

他们还为 document.addEventListener 中的事件使用了一个变量。

如果你想支持前缀,那么你需要使用变量属性和事件名称。如果没有,只需删除整个第一个代码块。


  1. 您没有根据 React 正确调整代码。

您希望确保您的 useEffect 挂钩具有正确的依赖项,并且理想情况下您应该在您的 useEffect 中使用清理函数来移除卸载时的事件侦听器。

这里最困难的部分是确保您不会创建任何在评估时使用过时的 document 值的陈旧闭包。我实际上不确定不玩它是否正确:

const TabVisibilityComponent = () => {
  const [action,setAction] = useState("show");

  useEffect(() => {
    const hide = () => setAction("hide");

    const show = () => setAction("show");

    const handleVisibilityChange = () => {
      document.hidden ? hide() : show();
    };

    document.addEventListener(
      "visibilitychange",handleVisibilityChange,false
    );
    window.addEventListener("focus",show,false);
    window.addEventListener("blur",hide,false);

    return () => {
      document.removeEventListener("visibilitychange",handleVisibilityChange);
      window.removeEventListener("focus",show);
      window.removeEventListener("blur",hide);
    };
  },[setAction]);

  return <p></p>;
};

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...