Добавьте прослушиватели событий onclick к нескольким кнопкам с помощью шаблонов Handlebar. js, эффективна только последняя - PullRequest
0 голосов
/ 16 апреля 2020

Я пишу веб-приложение как домашнее задание, которое использует websocket для получения сообщений от сервера и отображения их на html с помощью руля. js.

Я пытаюсь реализовать Функция удаления сообщения с использованием следующего кода:

document.addEventListener('DOMContentLoaded', () => {
    ...
    let message_container = document.querySelector("#message_container");
    const message_template = Handlebars.compile(document.querySelector("#message_template").innerHTML);
    const delete_button_template = Handlebars.compile(document.querySelector("#delete_button_template").innerHTML);

    function addDeleteButton(id) {
        let con = delete_button_template({"message_id": id}); //line #1
        document.querySelector("#content_" + id).innerHTML += con;
        document.querySelector("#delete_button_" + id).onclick = function () {
            const msg_id = event.target.dataset.message_id;
            const msg = document.querySelector("#message_" + msg_id);
            const blank = document.querySelector("#message_" + msg_id + "_newline");
            msg.parentElement.removeChild(msg);
            blank.parentElement.removeChild(blank);
        }
    }

Функция добавления сообщения в DOM проста:

function newMessage(i) {
            let msg = message_template({
                "message_id": i.message_id,
                "username": ...,
                "timestamp": ...,
                "content": ...
            });
            message_container.innerHTML += msg;
            addDeleteButton(i.message_id);
    }

Рули. js Шаблон для удаления кнопка подключена к HTML следующим образом:

<button id="delete_button_{{ message_id }}" data-message_id="{{ message_id }}" class="btn btn-primary">
                Delete
</button>

Однако каждый раз, когда я добавляю новое сообщение (включая кнопку удаления) в DOM, все предыдущие кнопки теряют свои прослушиватели событий onclick (). Инспектор chrome ясно показывает это, и это происходит в строке № 1:
Для 4-й кнопки зарегистрирован прослушиватель событий.

Добавление 5-й кнопки

Событие onclick 4-й кнопки исчезло.

Обходное решение - встроить вызов onclick в атрибут html. Но почему я не могу зарегистрировать слушателей событий, как в указанном коде?

1 Ответ

0 голосов
/ 17 апреля 2020

Проблема в следующей строке:

message_container.innerHTML += msg;

Мы используем Handlebars для создания новой строки HTML, которую мы храним в переменной msg. Затем мы хотим добавить этот новый HTML к элементу #message_container DOM.

Однако message_container.innerHTML += msg не не просто добавляет наш новый HTML вместо #message_container вместо этого заменяются все нисходящие DOM-узлы #message_container!

. Что происходит:

  • Мы получить узлы-потомки #message_container в DOM, преобразованные в строку HTML.
  • msg объединяется в конце этой новой строки HTML.
  • новая HTML строка заменяет innerHTML из #message_container.

Важной частью здесь является замена . Когда innerHTML из #message_container заменяется, заменяются все его дочерние узлы . Таким образом, все <button>, которые вы ранее подключили onclick слушателей, были удалены из DOM.

Один из способов предотвратить замену всех дочерних элементов #message_container каждый раз, когда мы хотим добавить <button> будет использовать Node.appendChild() API . Результирующий код будет выглядеть следующим образом:

// message_container.innerHTML += msg; // TODO: Replace this line with the below.

const node = document.createElement('div');
node.innerHTML = msg;
message_container.appendChild(node);

Я создал скрипку для справки.

...