Браузерные события элементов Ч. 2



Первая часть: https://studyjavascript.blogspot.com/2019/03/1.html

Создание собственных событий


JavaScript позволяет генерировать события на элементах.
Рассмотрим код:

    <button id="myButton">Нажми</button>
    <div id="myDiv"></div>


В html-коде у нас кнопка и див

  const myButton = document.querySelector("#myButton");
  const myDiv = document.querySelector("#myDiv");
 
  myButton.addEventListener("click", () => {
    const event = new CustomEvent("click");
    myDiv.dispatchEvent(event);
  });

  myDiv.addEventListener("click", () => {   
    console.log("На диве произошло событие click");
  });


Создаём переменные myButton и myDiv для кнопки и блока, на кнопке генерируем новое событие event и передаём это событие диву при помощи метода .dispatchEvent.
Для дива добавляем обработчик событий и прописываем там какой-нибудь код, чтобы отслеживать наступление события. Теперь при клике по кнопке наблюдаем срабатывание обработчика события клик на диве.

Эта возможность используется не так часто, но о её существовании полезно знать.

События мыши


mousedown    нажата кнопка мышиmouseup    отпущена кнопка мышиclick    клик кнопкой мышиdblclick    двойной клик кнопкой мышиmouseover    курсор вошел в рамки элементаmouseenter    курсор вошел в рамки элемента (событие не всплывает)
mousemove    курсор двигается над поверхностью элементаmouseout   курсор вышел за рамки элементаmouseleave    курсор вышел за рамки элемента (событие не всплывает)contextmenu    вызов контекстного меню правой кнопкой мышиwheele    вращение колеса мыши (имеет разные реализаци в браузерах)

Если, например, нужно реализовать метод drag-and-drop. вначале обрабатываем событие  mousedown (нажата кнопка мыши), затем mousemove (передвижение мыши), затем mouseup (отпущена кнопка мыши).

Делегирование

 html-код кнопка и ненумерованый список:

    <button id="myButton">Нажми</button>
    <ul id="myList"></ul>


Скрипт:

  const myButton = document.querySelector("#myButton");
  const myList = document.querySelector("#myList");
 
  let count = 1;
 
  myButton.addEventListener("click", () => {
    const li = document.createElement("li");
    li.textContent = "элемент " + count++;
    myList.appendChild(li);
  });


При клике по кнопке создаётся новый элемент списка li, ему добавляем текст, сам элемент li добавляем в список. Всё работает.

Теперь предположим, что каждому элементу списка мы хотим добавить обработчик событий addEventListener. Собственно, можно сделать так:

  myButton.addEventListener("click", () => {
    const li = document.createElement("li");
    li.textContent = "элемент " + count++;
    li.addEventListener("click", (event) => {
      console.log("кликнули на элемент списка " + event.target.textContent)
    });
    myList.appendChild(li);
  });


И это работает. Но так делать не нужно. для таких случаев предназначено делегирование, когда события на потомках обрабатывает их родитель.
Вот как выглядит нужный нам код:


  myList.addEventListener("click", (event) => {
    console.log("кликнули на элемент списка " + event.target.textContent);
  });
 
  myButton.addEventListener("click", () => {
    const li = document.createElement("li");
    li.textContent = "элемент " + count++;   
    myList.appendChild(li);
  });


Вместо того, чтобы добавлять обработчик событий на каждый дочерний элемент, мы повесили тот же самый обработчик на их родителя. При помощи event.target мы получили ссылку на элемент, на котором произошло событие. И код работает. Только теперь вместо множества обработчиков на дочерних элементах у нас всего один обработчик на родителе.

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

  myList.addEventListener("click", (event) => {
    if(event.target.tagName === "LI") {
      console.log("кликнули на элемент списка " + event.target.textContent);
    }   
  });


Делегирование - процесс, при котором родительский элемент обрабатывает
все или некоторые события, предназначенные для его потомков.


При таком подходе, нет смысла назначать обработчики на
элементы-потомки.

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

Чаще всего используется в целях
оптимизации.