2016-10-04 3 views
0

Этому ответили. Не проблема с ES6 или прослушивателями событий, а скорее как работает innerHTML. Он удаляет весь html (прерывает прослушиватели), а затем добавляет html обратно только при подключении только последнего слушателя. Спасибо.У меня проблемы с классами es6 и прослушивателями событий?

В основном у меня возникают проблемы с ES6 классами и слушателями событий. Или это вполне может быть просто моим пониманием всего этого.

Я динамически создаю 5 экземпляров того же класса под названием «Вещь». Каждая «Вещь» записывает фрагмент HTML в DOM, содержащий кнопку, и добавляет прослушиватель событий для обработки кликов. Элементы выбираются с помощью document.querySelector и основываются на атрибуте data, называемом «indexNumber», чтобы однозначно идентифицировать каждую кнопку.

Поскольку каждая вещь является ее собственным примером, я представил себе, что каждая кнопка будет работать, но только последняя кнопка. Почему один экземпляр класса перезаписывает другой?

Может ли кто-нибудь объяснить, что здесь происходит?

HTML

<h1>Things</h1> 
<span class="output"></span> 
<div class="thingHolder"></div> 

JS (Babel)

class Thing { 
    constructor(index) { 
    this.Index = index; 
    this.html = '<div class="thing" data-index-number="'+ index +'">Thing ' + index + '<button type="button">Click Me!</button></div>'; 
    this.renderDom(); 
    } 
    renderDom(){ 
    const thingHolder = document.querySelector(".thingHolder"); 
    thingHolder.innerHTML += this.html; 

    this.addEventListeners(); 
    } 

    addEventListeners(){ 
    const button = document.querySelector('.thingHolder .thing[data-index-number="' + this.Index + '"] button'); 

    button.addEventListener("click",() => { 
     this.doSomething() 
    }, false); 
    } 

    doSomething(){ 
    const output = document.querySelector(".output"); 
    output.innerHTML = 'You clicked thing #' + this.Index; 
    console.log('You clicked thing #' + this.Index) 
    } 
} 

for(var i = 0; i < 5; i++) { 
var thing = new Thing(i); 
} 

ответ

1

При использовании thingHolder.innerHTML += html старые объекты в контейнере удаляются и воссозданы, но без их слушателей событий. Таким образом, вы воссоздаете их все каждый раз, когда вы вставляете новый узел таким образом.

Тот факт, что первая кнопка работает только потому, что вы присоединяете событие только к первому элементу, с которым вы сталкиваетесь внутри родителя (с помощью querySelector), сразу после удаления всех других событий.

Таким образом, решение будет состоять из create your elements with JS (или любого другого, что используется в Babel) вместо использования innerHTML.

+2

* "или что-то используется в Вавилоне" * JavaScript;) –

+0

@FelixKling я не знаю. В настоящее время в веб-браузере используются очень неясные вещи. XP – germanfr

2

Проблема не имеет ничего общего с ES6 или JavaScript.

thingHolder.innerHTML += this.html; 

будет уничтожить и воссоздать всех существующих детей thingHolder. В этом процессе существующие обработчики событий уничтожаются.

Вместо создания HTML и использования innerHTML вы должны использовать DOM API для создания и добавления нового элемента.

Пример:

var div = document.createElement('div'); 
div.addEventListener('click',() => { ... }); 

// ... 
thingHolder.appendChild(div); 
+0

Это может быть проще понять, если вы считаете, что 'thingHolder.innerHTML + = this.html;' такое же, как 'thingHolder.innerHTML = thingHolder.innerHTML + this.html;' , – Nit

+0

Разве у нас нет канонического обмана? – Bergi

+0

@Bergi: Не удалось найти ничего, но для этого, безусловно, есть дубликат. –

Смежные вопросы