如何以普通方式复制事件侦听器 Javascript

How to copy an event listener in plain Javascript

所以我正在对 Wordpress 插件进行一些覆盖。我需要在一个元素上复制事件侦听器,然后替换该元素并将其添加回去。事件侦听器由插件生成。

我认为 getEventListeners() 会起作用,但我读到它只能在控制台中起作用。如果是这种情况,我真的很震惊。我们正处于可怕的 2020 年,我没有找到一个明显的解决方案。

这里的解决方案是什么?

下面是我在假设 getEventListeners 不仅仅是一个控制台函数的情况下尝试实现的代码。

  // Edit Affirm
  (function replaceAffirm() {
    if (document.querySelector(".affirm-modal-trigger")) {
      const learnMore = document.querySelector("#learn-more");
      const modalTrigger = document.querySelector(".affirm-modal-trigger");
      const clickHandler = getEventListeners(modalTrigger).click[0].listener;
      const substr = learnMore.innerHTML
        .toString()
        .substring(
          learnMore.innerHTML.indexOf("h") + 2,
          learnMore.innerHTML.length
        );
      learnMore.innerHTML = "Easy Financing with " + substr;
      modalTrigger.addEventListener("click", clickHandler);
    } else {
      setTimeout(function () {
        replaceAffirm();
      }, 250);
    }
  })();

HTML

<p id="learn-more" class="affirm-as-low-as" data-amount="20000" data-affirm-color="white" data-learnmore-show="true" data-page-type="product">
   Starting at 
   <span class="affirm-ala-price"></span>
   /mo with 
   <span class="__affirm-logo __affirm-logo-white __ligature__affirm_full_logo__ __processed">Affirm</span>. 
   <a class="affirm-modal-trigger" aria-label="Prequalify Now (opens in modal)" href="javascript:void(0)">Prequalify now</a>
</p>

是的,等待 Html 元素加载并检查直到它加载是可以的,这是等待它的正确方法之一。

根据我对你的问题的理解,你只需要更改 learn-more 元素的文本即可。 为此,没有必要复制事件侦听器然后再次绑定它。

无需替换整个元素,只需更改保留相同元素的文本即可。 所以它默认与事件监听器绑定。

您无法复制事件侦听器,但似乎由于您 HTML 的结构,您更有可能不需要重新添加它。与其编辑 HTML 并通过这样做删除事件侦听器,最好的办法是围绕它进行编辑。

如果您想删除文本节点,您可以遍历 childNodes 并分离出应该删除的内容。

然后要在需要的位置重建适当的文本,您可以使用 insertAdjacentText

if (document.querySelector(".affirm-modal-trigger")) {
  const learnMore = document.querySelector("#learn-more");
  const modalTrigger = document.querySelector(".affirm-modal-trigger");
  const children = Array.from(learnMore.childNodes);

  children.forEach(child => {
    if (child.nodeType === Node.TEXT_NODE || child.matches(".affirm-ala-price")) {
      if (learnMore.contains(child)) {
        learnMore.removeChild(child);
      }
    }
  });

  learnMore.insertAdjacentText("afterBegin", "Easy Financing With ");
  modalTrigger.insertAdjacentText("beforeBegin", " ");
} else {
  setTimeout(function() {
    replaceAffirm();
  }, 250);
}
<p id="learn-more" class="affirm-as-low-as" data-amount="20000" data-affirm-color="white" data-learnmore-show="true" data-page-type="product">
  Starting at
  <span class="affirm-ala-price"></span> /mo with
  <span class="__affirm-logo __affirm-logo-white __ligature__affirm_full_logo__ __processed">Affirm</span>.
  <a class="affirm-modal-trigger" aria-label="Prequalify Now (opens in modal)" href="javascript:void(0)">Prequalify now</a>
</p>