Олег
20 апр. 2021 г., 21:59

Написать обработчик по клику на кнопку

Нужно написать обработчик, который будет выводить сообщение в консоль о том, что товар добавлен в корзину при клике на кнопку «Купить»

Написал такой код :
var $btn = document.querySelector('elem-btn elem-btn--red to-basket ng-scope') document.addEventListener('click', function(e) { console.log($btn) })
Но он почему-то цепляет все клики на странице и выводит результаты кликов по кнопке несколько раз. Не пойму почему так происходит.
Занятная задачка и занятные ошибки :)

В первую очередь лучше, конечно, документацию сразу искать в том же MDN. Вот: https://developer.mozilla.org/ru/docs/Web/API/EventTarget/addEventListener (заодно прочитай и про removeEventListener(), его очень рекомендуется использовать).

1. document.addEventListener()
Ты вызываешь метод addEventListener у элемента document. Таким образом слушателя ты добавляешь именно документу. В итоге, где бы ты ни кликнул в документ (который суть враппер для всего содержимого страницы), ты получишь вызов обработчика.

2. document.addEventListener() можно вызывать несколько раз (как и на любом другом элементе). Если ты искал все кнопки и в цикле попытался навесить на каждую из них обработчик (а навесил каждый раз на документ), то столько раз и вызов произошел по клику. Еще раз уточню, что вызывая document.addEventListener(), ты добавляешь новый обработчик в массив обработчиков, а не перетираешь существующий. Выполни в консоли getEventListeners(document), увидишь там все обработчики, в том числе и на click.

3. Это уже чуть другой момент, но тоже важный. document.querySelector('elem-btn elem-btn--red to-basket ng-scope') - это поиск первого попавшегося элемента, не всех. Чтобы все найти и перечислить, надо юзать
1. document.addEventListener()
Ты вызываешь метож addEventListener у элемента document. Таким образом слушателя ты добавляешь именно документу. В итоге, где бы ты ни кликнул в документ (который суть враппер для всего содержимого страницы), ты получишь вызов обработчика.

Я же из документа выбираю конкретный селектор, при чем здесь весь документ?

2. document.addEventListener() можно вызывать несколько раз (как и на любом другом элементе). Если ты искал все кнопки и в цикле попытался навесить на каждую из них обработчик (а навесил каждый раз на документ), то столько раз и вызов произошел по клику. Еще раз уточню, что вызывая document.addEventListener(), ты добавляешь новый обработчик в массив обработчиков, а не перетираешь существующий. Выполни в консоли getEventListeners(document), увидишь там все обработчики, в том числе и на click.

В данном случае не нужны все кнопки, нужна конкретно одна кнопка.

3. Это уже чуть другой момент, но тоже важный. document.querySelector('elem-btn elem-btn--red to-basket ng-scope') - это поиск первого попавшегося элемента, не всех. Чтобы все найти и перечислить, надо юзать

Мне и нужен первый попавшийся элемент кнопка по которому я кликаю.


Олег, вот опять ты пытаешься получить магию и считаешь, что компьютер тебя неправильно понимает. Я тебе уже говорил об этом: компьютер тебя понимает ровно на столько, на сколько ты изъяснился с ним. А изъясниться с ним ты пока что можешь только кодом. Вот и надо код смотреть, а не твои желания. Точнее при написании кода ты, конечно же, должен учитывать свои желания, но конечный результат надо смотреть по написанному коду, и если что-то работает не так, как ты хотел, то скорее всего ты код неправильно написал, а не компьютер тебя не так понял.

> Я же из документа выбираю конкретный селектор, при чем здесь весь документ?

Это две, совершенно не связанные друг с другом операции.
// Здесь ты выполняешь поиск ноды в документе и присваиваешь ее переменной $btn // (точнее в переменную записывается ссылка на найденный в DOM элемент) var $btn = document.querySelector('elem-btn elem-btn--red to-basket ng-scope') // Здесь ты навешиваешь на документ обработчик, срабатывающий на клик по документу document.addEventListener('click', function(e) { // Этот обработчик срабатывает по клику и выводит ранее созданную переменную console.log($btn) })
Этот код можно написать вот так, чтобы было понятней.
// Здесь ты выполняешь поиск ноды в документе и присваиваешь ее переменной $btn // (точнее в переменную записывается ссылка на найденный в DOM элемент) var $btn = document.querySelector('elem-btn elem-btn--red to-basket ng-scope') // Создаем функцию-обработчик var handler = function(e) { // Этот обработчик срабатывает по клику и выводит ранее созданную переменную console.log($btn) } // Здесь ты навешиваешь на документ обработчик, срабатывающий на клик по документу document.addEventListener('click', handler)
Как видишь, handler как бы и не имеет отношения к document. Просто документу прописывается "При клике вызови handler".

Соответственно, если ты хочешь, чтобы обработчик срабатывал именно по кнопке, то и событие надо навешивать на кнопку.
// Создаем функцию-обработчик var handler = function(e) { // Выводим ноду из объекта события console.log(e.target) } // Здесь ты навешиваешь на документ обработчик, срабатывающий на клик по документу document.querySelector('elem-btn elem-btn--red to-basket ng-scope').addEventListener('click', handler)

>> В данном случае не нужны все кнопки, нужна конкретно одна кнопка.

Вот в данном случае и будет одна кнопка. Но только одна и самая первая. Не думаю, что ты хотел именно этого. Скорее всего ты хотел обрабатывать клики по любой кнопке, просто знать на какой именно клик сработал. И именно поэтому я и говорил использовать цикл, а в нем навесить по ивенту на каждую кнопку. Пример
// Создаем функцию-обработчик var handler = function(e) { // Выводим ноду из объекта события console.log(e.target) } // Здесь ты навешиваешь на документ обработчик, срабатывающий на клик по документу document.querySelectorAll('elem-btn elem-btn--red to-basket ng-scope').forEach(node => { node.addEventListener('click', handler) })
Вот здесь на каждую кнопку будет навешен один и тот же хендлер и срабатывать он будет на каждой кнопке в отдельности. А в самом хендлере из объекта события ты вытащишь инстанс конкретной ноды (e.target), и из нее уже можешь получить все нужные тебе данные.



Добавить комментарий