【问题标题】:Close modal when clicking outside of it单击外部时关闭模式
【发布时间】:2020-08-18 23:20:23
【问题描述】:

单击 x 图标和按下退出按钮时,我能够关闭我的模式。在模式外部(即页面的正文?)单击时,如何使其关闭?谢谢

document.querySelectorAll(".modal-trigger").forEach((trigger) => {
    const modal = document.querySelector(trigger.dataset.modal);
    const closeBtn = modal.querySelector(".modal-close");
    function open() {
        modal.classList.add("show-modal");
        trigger.blur();
        document.body.style.overflow = "hidden";
        document.body.addEventListener("keydown", escapeClose);
    }
    function close() {
        modal.classList.remove("show-modal");
        document.body.style.overflow = "auto";
        document.body.removeEventListener("keydown", escapeClose);
    }
    function escapeClose(event) {
        if (event.keyCode === 27) {
            close();
        }
    }
    trigger.addEventListener("click", open);
    closeBtn.addEventListener("click", close);
});

【问题讨论】:

    标签: javascript simplemodal


    【解决方案1】:

    您可以执行以下操作

    document.addEventListener('click', function(e) {
      if (e.target.closest(trigger.dataset.modal) == null) {
        close();
      }
    })
    

    这将查询最近单击的任何项目的方法。 Closest() 从它开始的地方向上遍历 dom。因此,如果您在模式之外单击,它将返回一个空值。如果您单击模态框内的某个项目,它将返回模态框本身。您应该能够假设如果返回值为 null,则点击来自模态框之外。

    关于最接近()的附加信息

    https://developer.mozilla.org/en-US/docs/Web/API/Element/closest

    【讨论】:

      【解决方案2】:

      尝试直接使用事件监听器更改样式。

      window.onclick = (e) => {
          if (e.target == modal) {
              modal.style.display = "none";
          }        
      }
      

      【讨论】:

        【解决方案3】:

        这就是我最终要做的。谢谢!

        document.querySelectorAll(".modal-trigger").forEach((trigger) => {
            const modal = document.querySelector(trigger.dataset.modal);
            const closeBtn = modal.querySelector(".modal-close");
            function open(event) {
                modal.classList.add("show-modal");
                trigger.blur();
                document.body.style.overflow = "hidden";
                document.body.addEventListener("keydown", escapeClose);
                modal.addEventListener("click", outsideClose);
                event.stopPropagation();
            }
            function close() {
                modal.classList.remove("show-modal");
                document.body.style.overflow = "auto";
                document.body.removeEventListener("keydown", escapeClose);
                modal.removeEventListener("click", outsideClose);
            }
            function escapeClose(event) {
                if (event.keyCode === 27) {
                    close();
                }
            }
        
            function outsideClose(event) {
                if (
                    event.target === modal ||
                    event.target.classList.contains("close-modal")
                ) {
                    close();
                }
            }
        
            trigger.addEventListener("click", open);
            closeBtn.addEventListener("click", close);
        });
        

        【讨论】:

        • 如果用户在模态元素内单击,这不会关闭模态吗?不应该是event.target != modal吗?
        • 这对我来说确实是个问题,我花了一段时间才弄清楚,所以在模态变量中我有一个 div 作为背景。所以如果模态得到点击,如果目标是它本身,这意味着我没有点击模态内容,而是点击了背景,所以我关闭了模态。因此,如果我这样做 event.target != modal 它会相反:当我点击模式时关闭,而不是当我点击背景时这有效,但可能有更简单的方法来做到这一点。
        • 我将发布我的非常简单和通用的解决方案,它使用逻辑 (!not) 运算符来检查点击是在模式内部还是外部。
        【解决方案4】:

        我喜欢这个解决方案,我可能在 Stackoverflow 上找到了它:

        // Close modal on outside click
        
        const modal = document.querySelector('.modal')
        
        document.addEventListener('click', (e) => {
          let clickInside = modal.contains(e.target)
        
          if (!clickInside) {
             modal.classList.remove('show')
          }
        })
        

        【讨论】:

          猜你喜欢
          • 2019-07-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-24
          • 1970-01-01
          相关资源
          最近更新 更多