当页面在 IE11 中冻结时,如何防止触发 OnBlur 事件
How can I prevent the OnBlur event from triggering when the page freezes in IE11
我有一个使用 React 的考试申请。我需要在 IE11 中 运行 这个应用程序。在此考试应用程序中,我添加了 onblur 事件,当用户离开选项卡时,该事件将 运行 触发,当此事件被触发时,用户会收到弹出窗口提醒,并且用户在 DB 中的 lockCount 会增加。如果 LockCount 超过为考试定义的限制,用户的考试将被阻止。
问题是当页面暂时冻结时会触发 onblur 事件。通常,当重新呈现页面或调用任何 API 服务需要很长时间时,就会出现此冻结问题。它在 Chrome.
中没有任何问题
我还尝试了 onBlur 事件和 Mouseleave 事件,但是当页面冻结时,mouseleave 事件也会触发。
如何防止在IE11中页面冻结时触发onBlur事件?
onBlur 和 onFocus 事件的代码:
const onFocus = () => {
setIsOnblur(false);
};
const onBlur = () => {
increaseCount();
setIsOnblur(true);
};
useEffect(() => {
if (props.location.pathname.includes("/Exam/")) {
window.addEventListener("focus", onFocus);
window.addEventListener("blur", onBlur);
return () => {
window.removeEventListener("focus", onFocus);
window.removeEventListener("blur", onBlur);
};
}
}, []);
问题似乎是 blur
侦听器有时会在页面完全加载之前触发。我们可以通过 load
事件确定页面已完全加载。
来自MDN:
The load
event is fired when the whole page has loaded, including all
dependent resources such as stylesheets and images.
因此,我会让 addEventListener
依赖于 window 是否已满载。这样的事情应该有效:
useEffect(() => {
window.addEventListener("load", () => {
if (props.location.pathname.includes("/Exam/")) {
window.addEventListener("focus", onFocus);
window.addEventListener("blur", onBlur);
}
return () => {
window.removeEventListener("focus", onFocus);
window.removeEventListener("blur", onBlur);
};
});
}, []);
我用这个()答案解决了这个问题。 This answer告诉您可以使用3种不同的方法来检测用户从网页上失去焦点。
- 页面可见度API
- Focus/Blur 事件
- 用户活动
就我而言,我解决了用户鼠标 activity 和超时的问题。
第一种情况:当用户将屏幕从网页完全切换到另一个页面或其他内容时,它会起作用。页面可见性 API 允许我们检测页面何时对用户隐藏。当页面最小化但页面未完全隐藏时,它不会捕获丢失的焦点。不算。
第二种情况:Focus-Blur 事件在正常情况下运行良好。但 Internet Explorer 问题误导了这一点。
第三种情况:由于上述问题,鼠标事件(mouseout、mousein、mouseover)不工作。但是如果我使用所有事件,尤其是鼠标事件超时,onBlur 事件不会在页面冻结时触发。
代码如下:
useEffect(() => {
if (props.location.pathname.includes("/Exam/")) {
var doc = document as any;
// register to the W3C Page Visibility API
var hidden: any = null;
var visibilityChange: any = null;
if (typeof doc.mozHidden !== "undefined") {
hidden = "mozHidden";
visibilityChange = "mozvisibilitychange";
} else if (typeof doc.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof doc.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
// } else if (typeof document.hidden !== "hidden") {
} else if (doc.hidden) {
hidden = "hidden";
visibilityChange = "visibilitychange";
}
if (hidden != null && visibilityChange != null) {
addEvent(doc, visibilityChange, function (event: any) {
if (doc[hidden]) {
onBlur();
}
});
}
// register to the potential page visibility change
addEvent(doc, "potentialvisilitychange", function (event: any) {
if (doc.potentialHidden && !doc[hidden]) {
onBlur();
}
});
var potentialPageVisibility = {
pageVisibilityChangeThreshold: 3 * 3600, // in seconds
init: function () {
var lastActionDate: any = null;
var hasFocusLocal: any = true;
var hasMouseOver: any = true;
doc.potentialHidden = false;
doc.potentiallyHiddenSince = 0;
var timeoutHandler: any = null;
function setAsNotHidden() {
var dispatchEventRequired = doc.potentialHidden;
doc.potentialHidden = false;
doc.potentiallyHiddenSince = 0;
if (dispatchEventRequired) dispatchPageVisibilityChangeEvent();
}
function initPotentiallyHiddenDetection() {
if (!hasFocusLocal) {
// the window does not has the focus => check for user activity in the window
lastActionDate = new Date();
if (timeoutHandler != null) {
clearTimeout(timeoutHandler);
}
timeoutHandler = setTimeout(checkPageVisibility, potentialPageVisibility.pageVisibilityChangeThreshold * 1000 + 100); // +100 ms to avoid rounding issues under Firefox
}
}
function dispatchPageVisibilityChangeEvent() {
var evt = doc.createEvent("Event");
evt.initEvent("potentialvisilitychange", true, true);
doc.dispatchEvent(evt);
}
function checkPageVisibility() {
var potentialHiddenDuration = (hasFocusLocal || lastActionDate == null ? 0 : Math.floor((new Date().getTime() - lastActionDate.getTime()) / 1000));
doc.potentiallyHiddenSince = potentialHiddenDuration;
if (potentialHiddenDuration >= potentialPageVisibility.pageVisibilityChangeThreshold && !doc.potentialHidden) {
// page visibility change threshold raiched => raise the even
doc.potentialHidden = true;
dispatchPageVisibilityChangeEvent();
}
}
addEvent(doc, "mousemove", function (event: any) {
lastActionDate = new Date();
});
addEvent(doc, "mouseover", function (event: any) {
hasMouseOver = true;
setAsNotHidden();
});
addEvent(doc, "mouseout", function (event: any) {
hasMouseOver = false;
initPotentiallyHiddenDetection();
});
addEvent(window, "blur", function (event: any) {
hasFocusLocal = false;
initPotentiallyHiddenDetection();
});
addEvent(window, "focus", function (event: any) {
hasFocusLocal = true;
setAsNotHidden();
});
setAsNotHidden();
}
}
potentialPageVisibility.pageVisibilityChangeThreshold = 1; // 4 seconds for testing
potentialPageVisibility.init();
}
}, []);
我有一个使用 React 的考试申请。我需要在 IE11 中 运行 这个应用程序。在此考试应用程序中,我添加了 onblur 事件,当用户离开选项卡时,该事件将 运行 触发,当此事件被触发时,用户会收到弹出窗口提醒,并且用户在 DB 中的 lockCount 会增加。如果 LockCount 超过为考试定义的限制,用户的考试将被阻止。
问题是当页面暂时冻结时会触发 onblur 事件。通常,当重新呈现页面或调用任何 API 服务需要很长时间时,就会出现此冻结问题。它在 Chrome.
中没有任何问题我还尝试了 onBlur 事件和 Mouseleave 事件,但是当页面冻结时,mouseleave 事件也会触发。
如何防止在IE11中页面冻结时触发onBlur事件?
onBlur 和 onFocus 事件的代码:
const onFocus = () => {
setIsOnblur(false);
};
const onBlur = () => {
increaseCount();
setIsOnblur(true);
};
useEffect(() => {
if (props.location.pathname.includes("/Exam/")) {
window.addEventListener("focus", onFocus);
window.addEventListener("blur", onBlur);
return () => {
window.removeEventListener("focus", onFocus);
window.removeEventListener("blur", onBlur);
};
}
}, []);
问题似乎是 blur
侦听器有时会在页面完全加载之前触发。我们可以通过 load
事件确定页面已完全加载。
来自MDN:
The
load
event is fired when the whole page has loaded, including all dependent resources such as stylesheets and images.
因此,我会让 addEventListener
依赖于 window 是否已满载。这样的事情应该有效:
useEffect(() => {
window.addEventListener("load", () => {
if (props.location.pathname.includes("/Exam/")) {
window.addEventListener("focus", onFocus);
window.addEventListener("blur", onBlur);
}
return () => {
window.removeEventListener("focus", onFocus);
window.removeEventListener("blur", onBlur);
};
});
}, []);
我用这个()答案解决了这个问题。 This answer告诉您可以使用3种不同的方法来检测用户从网页上失去焦点。
- 页面可见度API
- Focus/Blur 事件
- 用户活动
就我而言,我解决了用户鼠标 activity 和超时的问题。
第一种情况:当用户将屏幕从网页完全切换到另一个页面或其他内容时,它会起作用。页面可见性 API 允许我们检测页面何时对用户隐藏。当页面最小化但页面未完全隐藏时,它不会捕获丢失的焦点。不算。
第二种情况:Focus-Blur 事件在正常情况下运行良好。但 Internet Explorer 问题误导了这一点。
第三种情况:由于上述问题,鼠标事件(mouseout、mousein、mouseover)不工作。但是如果我使用所有事件,尤其是鼠标事件超时,onBlur 事件不会在页面冻结时触发。
代码如下:
useEffect(() => {
if (props.location.pathname.includes("/Exam/")) {
var doc = document as any;
// register to the W3C Page Visibility API
var hidden: any = null;
var visibilityChange: any = null;
if (typeof doc.mozHidden !== "undefined") {
hidden = "mozHidden";
visibilityChange = "mozvisibilitychange";
} else if (typeof doc.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof doc.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
// } else if (typeof document.hidden !== "hidden") {
} else if (doc.hidden) {
hidden = "hidden";
visibilityChange = "visibilitychange";
}
if (hidden != null && visibilityChange != null) {
addEvent(doc, visibilityChange, function (event: any) {
if (doc[hidden]) {
onBlur();
}
});
}
// register to the potential page visibility change
addEvent(doc, "potentialvisilitychange", function (event: any) {
if (doc.potentialHidden && !doc[hidden]) {
onBlur();
}
});
var potentialPageVisibility = {
pageVisibilityChangeThreshold: 3 * 3600, // in seconds
init: function () {
var lastActionDate: any = null;
var hasFocusLocal: any = true;
var hasMouseOver: any = true;
doc.potentialHidden = false;
doc.potentiallyHiddenSince = 0;
var timeoutHandler: any = null;
function setAsNotHidden() {
var dispatchEventRequired = doc.potentialHidden;
doc.potentialHidden = false;
doc.potentiallyHiddenSince = 0;
if (dispatchEventRequired) dispatchPageVisibilityChangeEvent();
}
function initPotentiallyHiddenDetection() {
if (!hasFocusLocal) {
// the window does not has the focus => check for user activity in the window
lastActionDate = new Date();
if (timeoutHandler != null) {
clearTimeout(timeoutHandler);
}
timeoutHandler = setTimeout(checkPageVisibility, potentialPageVisibility.pageVisibilityChangeThreshold * 1000 + 100); // +100 ms to avoid rounding issues under Firefox
}
}
function dispatchPageVisibilityChangeEvent() {
var evt = doc.createEvent("Event");
evt.initEvent("potentialvisilitychange", true, true);
doc.dispatchEvent(evt);
}
function checkPageVisibility() {
var potentialHiddenDuration = (hasFocusLocal || lastActionDate == null ? 0 : Math.floor((new Date().getTime() - lastActionDate.getTime()) / 1000));
doc.potentiallyHiddenSince = potentialHiddenDuration;
if (potentialHiddenDuration >= potentialPageVisibility.pageVisibilityChangeThreshold && !doc.potentialHidden) {
// page visibility change threshold raiched => raise the even
doc.potentialHidden = true;
dispatchPageVisibilityChangeEvent();
}
}
addEvent(doc, "mousemove", function (event: any) {
lastActionDate = new Date();
});
addEvent(doc, "mouseover", function (event: any) {
hasMouseOver = true;
setAsNotHidden();
});
addEvent(doc, "mouseout", function (event: any) {
hasMouseOver = false;
initPotentiallyHiddenDetection();
});
addEvent(window, "blur", function (event: any) {
hasFocusLocal = false;
initPotentiallyHiddenDetection();
});
addEvent(window, "focus", function (event: any) {
hasFocusLocal = true;
setAsNotHidden();
});
setAsNotHidden();
}
}
potentialPageVisibility.pageVisibilityChangeThreshold = 1; // 4 seconds for testing
potentialPageVisibility.init();
}
}, []);