#javascript #html #reactjs #typescript #interface
#javascript #HTML #reactjs #typescript #интерфейс
Вопрос:
Я получаю эту ошибку при использовании видимости вкладок. В котором ‘msHidden’ и ‘webkitHidden’ не существуют для типа ‘Document’
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;
Я попытался добавить ‘только для чтения msHidden: boolean’ в интерфейс документа в файле ‘lib.dom.d.ts’, потому что hidden работает нормально, и в этом файле он объявлен как логическое значение только для чтения, поэтому попробовал то же самое для msHidden и webkitHidden, но это не работает. Я видел, что этот код используется многими, но не знаю, в чем ошибка с моим. Был бы очень рад, если бы у кого-нибудь нашлось решение для этого!
Ответ №1:
Код взят прямо из документов MDN, так что вы правы в том, что сам код в порядке. Проблемы заключаются в:
lib.dom
Определения действительно включают свойства, зависящие от браузера.
Один из способов обойти это — передать документ в качестве аргумента функции, которая определяет эти свойства как необязательные.
const hiddenPropName = (document: Document amp; {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
}
Но что касается машинописного текста, document.hidden
он всегда существует.
Похоже, что вряд ли есть какая-либо разница между номерами для поддержки с префиксом и без префикса в caniuse. Так что вы могли бы просто отказаться от msHidden
and webkitHidden
.
- Вы игнорируете
hidden
visibilityChange
переменные и, которые вы устанавливаете.
Первый раздел кода в примере — это просто настройка переменных hidden
и visibilityChange
имен свойств, чтобы позже они могли получить доступ к правильным свойствам. В примере используется document[hidden]
where hidden
— переменная, но вы использовали document.hidden
which, которая всегда получает свойство «hidden» и никогда «msHidden» или «webkitHidden».
Они также используют переменную для события в document.addEventListener
.
Если вы хотите поддерживать префиксы, вам нужно использовать имена свойств переменных и событий. Если нет, просто удалите весь этот первый блок кода целиком.
- Вы неправильно адаптируете код к 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>;
};