繁体   English   中英

当页面在 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 中运行没有任何问题。

我还尝试了带有 Mouseleave 事件的 onBlur 事件,但是当页面冻结时,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

加载整个页面时会触发load事件,包括所有相关资源,例如样式表和图像。

因此,我将使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);
    };
  });
}, []);

我用这个( https://stackoverflow.com/a/9502074/9938582 )答案解决了这个问题。 这个答案告诉您可以使用 3 种不同的方法来检测用户从网页上失去焦点。

  1. 页面可见性 API
  2. 焦点/模糊事件
  3. 用户活动

就我而言,我解决了用户鼠标活动和超时的问题。

第一种情况:当用户将屏幕完全从网页更改为另一个页面或其他内容时,它会起作用。 页面可见性 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();
    }
}, []);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM