从 IIFE 内部调用 IIFE 外部的代码

Call code outside of IIFE from within IIFE

我有代码成功调用了 IIFE 中的函数,而该函数又引用了 IIFE 之外的代码,我不知道如何调用。

const msgbox = (function () {
  function showMsgBox(msg) {
    const modal = document.createElement("div");
    modal.classList.add("modal");
    modal.innerHTML = `<div class="modal-content"><p>${msg}</p></div>`;
    document.body.appendChild(modal);
    modal.style.display = "block";
    window.onclick = function (event) {
      if (event.target === modal) {
        modal.style.display = "none";
      }
    };
  }
  return {
    showMsgBox: showMsgBox
  };
})();

  const example = document.getElementById("example");

  function changeClass() {
    if (example.getAttribute("class") === "classTwo") {
      example.classList.remove("classTwo");
      example.classList.add("classOne");
    } else {
      example.classList.add("classTwo");
      example.classList.remove("classOne");
    }
  }

  document.querySelectorAll(".change_class").forEach((item) => {
    item.addEventListener("click", function (e) {
      changeClass();
    });
  });
  
  document.querySelector(".showmsg").addEventListener("click", function (e) {
    msgbox.showMsgBox(
      'Call Function outside of IIFE=> <button class="change_class">Change Class</button> (<= this button should have the same functionality as the other button)'
    );
  });

我尝试将非 IIFE 部分放入其自己的 IIFE 中并为其提供一个单独的命名空间,但这没有用。上面的示例是我的实际问题的简化版本,但这更简洁地封装了我的问题并减少了混淆。是的,我可以使 IIFE 只是一个函数并以这种方式调用它,但我正在努力扩展我的知识。

这是我为此创建的 CodePen 示例的 link: https://codepen.io/NoahBoddy/pen/PoOVMzK 希望我的解释很清楚。如果没有,我可以提供更多细节。谢谢!

模式中的按钮没有 click 处理程序,因此它什么都不做:

msgbox.showMsgBox(
   'Call Function outside of IIFE=> <button class="change_class">Change Class</button> (<= this button should have the same functionality as the other button)'
);

您可以将 click 处理程序设置为内联:

msgbox.showMsgBox(                             
   'Call Function outside of IIFE=> <button onclick="changeClass()" class="change_class">Change Class</button> (<= this button should have the same functionality as the other button)'
);

demo 1

或者您可以更新 showMsgBox() 以添加处理程序:

function showMsgBox(msg) {
  const modal = document.createElement("div");
  ⋮
  modal.querySelectorAll(".change_class").forEach((item) => {
    item.addEventListener("click", function (e) {
      changeClass();
    });
  });
}

demo 2

新按钮没有运行点击事件代码的原因是因为它没有被添加进去

一次

document.querySelectorAll(".change_class").forEach((item) => {
  item.addEventListener("click", function (e) {
    changeClass();
  });
});

运行s,就是这样。任何带有 class 的新元素都不会自动再次生成上述代码 运行

您可以在创建按钮后将相同的事件处理程序添加到新创建的按钮 - 这很乏味,并且重复代码 - 如果您需要进行更改,您可能需要更改多个位置。错误代码的秘诀。

或者...这是一个使用事件委托的解决方案

const msgbox = (function () {
    function showMsgBox(msg) {
        const modal = document.createElement("div");
        modal.classList.add("modal");
        modal.innerHTML = `<div class="modal-content"><p>${msg}</p></div>`;
        document.body.appendChild(modal);
        modal.style.display = "block";
        window.onclick = function (event) {
            if (event.target === modal) {
                modal.style.display = "none";
            }
        };
    }
    return {
        showMsgBox: showMsgBox
    };
})();

const example = document.getElementById("example");
function changeClass() {
    if (example.getAttribute("class") === "classTwo") {
        example.classList.remove("classTwo");
        example.classList.add("classOne");
    } else {
        example.classList.add("classTwo");
        example.classList.remove("classOne");
    }
}
const change_class = document.getElementsByClassName("change_class");
document.body.addEventListener('click', function(e) {
    if ([...change_class].includes(e.target)) {
        changeClass();
    }
});

document.querySelector(".showmsg").addEventListener("click", function (e) {
    msgbox.showMsgBox('<button class="change_class">Change Class</button>');
});
* { font-family: sans-serif; }
/* The Modal (background) */
.modal {
  display: none; /* Hidden by default */
  position: fixed; /* Stay in place */
  z-index: 1; /* Sit on top */
  left: 0;
  top: 0;
  width: 100%; /* Full width */
  height: 100%; /* Full height */
  overflow: auto; /* Enable scroll if needed */
  background-color: rgb(0, 0, 0); /* Fallback color */
  background-color: rgba(0, 0, 0, 0.4); /* Black w/ opacity */
}

/* Modal Content/Box */
.modal-content {
  background-color: #fefefe;
  margin: 15% auto; /* 15% from the top and centered */
  padding: 20px;
  border: 1px solid #888;
  width: 80%; /* Could be more or less, depending on screen size */
}

/* The Close Button */
.close {
  color: #aaa;
  float: right;
  font-size: 28px;
  font-weight: bold;
}

.close:hover,
.close:focus {
  color: black;
  text-decoration: none;
  cursor: pointer;
}
.classOne {
  background: #088;
  color: #fff;
  padding: 0.5rem;
}
.classTwo {
  background: #808;
  color: #fff;
  padding: 0.5rem;
}
<button class="change_class">Change Class</button>
<br><br>
<div id="example" class="classOne">This will alternately use 'classOne' and 'classTwo'</div>
<br>
<button class="showmsg">Show MsgBox</button>

如代码中所述 document.getElementsByClassName returns 一个 live 列表(querySelectorAll 没有)

这意味着使用指定 class 添加的任何新元素都将出现在该列表中,您无需执行任何操作。删除的元素也一样,它们只是从列表中消失

注意:getElementsByClassName也是任何元素的方法,所以你不必获取文档中的所有此类元素,你可以使用它来获取文档中选定元素下的目标元素DOM - 不适用于此代码,但可能有用