【问题标题】:Remove event listener from custom-elements从自定义元素中移除事件监听器
【发布时间】:2021-05-24 14:14:56
【问题描述】:

考虑一个简单的自定义元素simple-element 我无法移除事件监听器:

const myElement = document.getElementById('myElement');

function removeListener(){
  // works
  this.style.backgroundColor = ''; 
  this.style.color = 'red';
  // NOT WORKING
  this.removeEventListener('click', handleEvent.bind(this));
  this.span.innerText = 'Event Listener "handleEvent" not removed, you can still click this "simple-element"'
}

function handleEvent(){
  this.style.backgroundColor = '#069';
  this.style.color = '#ffffff'
}

// sample custom element
(() => {
  class SimpleElement extends HTMLElement {
    constructor() {
      super();

      this.template = document.createElement('template');
      this.template.innerHTML = 
`<style>span {color: inherit}</style>
<span>Simple element content<br>Click ME</span>`;

      // Patch shadow DOM
      if (window.ShadyCSS) {
        window.ShadyCSS.prepareTemplate(this.template, 'simple-element');
      }

      this.attachShadow({ mode: 'open' });
      this.shadowRoot.appendChild(this.template.content.cloneNode(true));

      // Patch shadow DOM
      if (window.ShadyCSS) {
        window.ShadyCSS.styleElement(this)
      }
    }

    connectedCallback(){
      this.span = this.shadowRoot.querySelector('span');
      this.addEventListener('click', handleEvent.bind(this))
    }
  }

  customElements.define('simple-element', SimpleElement);
})();
simple-element {padding: 1rem 0.25rem; width: 100%; display: block}
<simple-element id="myElement"></simple-element>
<br>
<button onclick="removeListener.call(myElement)">Remove Listener</button>

无论我选择在哪里/如何定义和执行事件侦听器移除,它都不起作用。

感谢任何回复,并提前致谢。

【问题讨论】:

  • .bind() 每次调用时都会返回一个新函数,这就是我认为事件监听器没有被删除的原因。
  • .apply有同样的效果吗?
  • 不,callapply 不返回新函数,bind 返回新函数。
  • 你有什么建议? this.addEventListener('click', handleEvent.apply(this)) 不起作用。
  • handleEvent.apply(this) - 这不起作用,因为它会立即调用函数

标签: javascript html custom-element


【解决方案1】:

您正在创建依赖关系。

如果自定义元素添加一个 EventListener,那么同一个自定义元素应该处理它的行为

<my-element id=ELEMENT>
  <button id=BUTTON>Remove Listener</button>
</my-element>

<script>
  BUTTON.onclick = (evt) => ELEMENT.removeListener();
  
  customElements.define('my-element', class extends HTMLElement {
    constructor() {
      super() // sets and return this-Scope
        .attachShadow({mode: 'open'}) // sets and returns this.shadowRoot
        .innerHTML = `<style>:host{display:inline-block}</style>
                      <div>Simple element content<br>
                        Click ME <slot></slot>
                      </div>`;
      this.addEventListener('click', this.handleClick )
    }
    handleClick(evt) {
      this.style.background = 'teal';
      this.style.color = 'white';
    }
    removeListener() {
      this.style.background = 'none';
      this.style.color = 'red';
      this.removeEventListener('click', this.handleClick);
      this.shadowRoot.querySelector("div").innerText = `Event Listener "handleClick" removed`;
    }

  });
</script>

内联事件

而不是addEventListener(可以添加多个事件)
你也可以使用 inline 事件(只能使用一种功能)

不仅符号更短,它还让您的组件用户更容易覆盖行为。

// assign
this.onclick = this.handleClick;
// remove
this.onclick = null;

另请注意,当元素从 DOM 中删除时,JavaScript 垃圾收集过程会删除您分配给元素的事件。因此,您不必自己删除这些侦听器。

如果您的元素将侦听器添加到其他元素,例如document,您确实必须删除这些,
disconnectedCallback

【讨论】:

  • 感谢您的解释,我一直在努力确保不会让听众污染全球,这就是我首先提出这个问题的原因:)。干杯!
猜你喜欢
  • 1970-01-01
  • 2021-11-21
  • 1970-01-01
  • 2022-08-16
  • 2017-01-28
  • 1970-01-01
  • 1970-01-01
  • 2017-02-18
相关资源
最近更新 更多