简体   繁体   English

attributeChangedCallback() 总是被调用两次以多个事件监听器结束

[英]attributeChangedCallback() always called twice ending up with multiple event listeners

Playing around with custom elements, I'm trying to get a click event fired depending on custom element attribute's value.玩弄自定义元素,我试图根据自定义元素属性的值触发点击事件。 But using the attributeChangedCallback() method (along with the connectedCallback() method) I'm ending up with multiple event listeners.但是使用attributeChangedCallback()方法(以及connectedCallback()方法)我最终得到了多个事件侦听器。

 class HelloWorld extends HTMLElement { static get observedAttributes() { return ['attribute1', 'attribute2']; } get attribute1() { return this.getAttribute('attribute1'); } set attribute1(val) { if (val) { this.setAttribute('attribute1', val); } else { this.removeAttribute('attribute1'); } } get attribute2() { return this.getAttribute('attribute2'); } set attribute2(val) { if (val) { this.setAttribute('attribute2', val); } else { this.removeAttribute('attribute2'); } } constructor() { super(); } connectedCallback() { this.textContent = 'Hello World'; update(this); } attributeChangedCallback(name, oldValue, newValue) { update(this); } } customElements.define('hello-world', HelloWorld); function update(el) { if (el.attribute1 === 'foo') { el.addEventListener('click', e => { el.textContent = (el.textContent.indexOf(' (') != -1 ? el.textContent.substring(0, el.textContent.indexOf(' (')) : el.textContent) + ' (clicked ' + (el.textContent.match(/\d+/) ? parseInt(el.textContent.match(/-?\d+/)[0]) + 1 : 1) + ' times)'; }); } else if (el.attribute1 === 'bar') { el.addEventListener('click', e => { el.textContent = (el.textContent.indexOf(' (') != -1 ? el.textContent.substring(0, el.textContent.indexOf(' (')) : el.textContent) + ' (clicked ' + (el.textContent.match(/\d+/) ? parseInt(el.textContent.match(/-?\d+/)[0]) - 1 : 1) + ' times)'; }); } }
 hello-world { cursor: pointer; }
 <hello-world attribute1="foo" attribute2=""></hello-world>

Why is the attributeChangedCallback() method always called twice and therefore adds two event listeners?为什么attributeChangedCallback()方法总是被调用两次并因此添加了两个事件监听器? How to avoid this?如何避免这种情况? What would be best practice?什么是最佳实践?

It is called attributeChangedCallback , so fires on every single attribute change, including init when the element is added to the DOM它被称为attributeChangedCallback ,因此会在每个属性更改时触发,包括将元素添加到 DOM 时的 init

Attach listeners in the connectedCallback , but that can run again if you move the element in the DOM, so you have to remove them in the disconnectedCallbackconnectedCallback中附加侦听器,但是如果您在 DOM 中移动元素,它可以再次运行,因此您必须在disconnectedCallback中删除它们

Easier might be to use an inline EventHandler, there can only be one on an element.使用内联EventHandler 可能更简单,元素上只能有一个。

 customElements.define('hello-world', class extends HTMLElement { static get observedAttributes() { return ['attribute1', 'attribute2']; } get attribute1() { return this.getAttribute('attribute1'); } set attribute1(val) { this.toggleAttribute('attribute1', val); } get attribute2() { return this.getAttribute('attribute2'); } set attribute2(val) { this.toggleAttribute('attribute2', val); } connectedCallback() { this.count = 0; this.innerHTML = `Hello World clicked: <span>${this.count}</span> times`; this.onclick = (evt) => { this.count++; this.querySelector("span").innerHTML = this.count; } } attributeChangedCallback(name, oldValue, newValue) { console.log("attributeChangedCallback", name, oldValue, newValue); } });
 hello-world { cursor: pointer; }
 <hello-world attribute1="foo" attribute2=""></hello-world>

constructor() {
  super()
}

is not required, a non existing constructor will execute the constructor from its parent.. which is what super() does.不是必需的,不存在的constructor函数将从其父级执行constructor 。这是super()所做的。

If you want to prevent multiple listeners you could try a method:如果要阻止多个侦听器,可以尝试一种方法:

addListeners(){
  .. add your listeners

  this.addListeners = () => {}; // overload; Don't run its original code again
}

Also note Listeners you add on the Element (or its contents) are automaticall garbage collected / removed when the element is removed from the DOM.另请注意,当从 DOM 中删除元素时,您在元素(或其内容)上添加的侦听器会自动收集/删除所有垃圾。
Any Listeners you add on other DOM elements (eg. document) you have to remove yourself in the disconnectedCallback您在其他 DOM 元素(例如文档)上添加的任何侦听器都必须在disconnectedCallback中删除

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

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