метод addEventListener против щелчку
В чем разница между addEventListener
и onclick
?
var h = document.getElementById("a");
h.onclick = dothing1;
h.addEventListener("click", dothing2);
приведенный выше код находится вместе в отдельном .файл JS, и они оба работают отлично.
14 ответов:
оба верны, но ни один из них не является "лучшим" сам по себе, и может быть причина, по которой разработчик решил использовать оба подхода.
прослушиватели событий (addEventListener и IE attachEvent)
более ранние версии Internet Explorer реализуют javascript по-разному от почти всех других браузеров. С версиями менее 9, вы используете
attachEvent
[doc] метод, как это:element.attachEvent('onclick', function() { /* do stuff here*/ });
в большинстве других браузеры (включая IE 9 и выше), вы используете
addEventListener
[doc], как это:element.addEventListener('click', function() { /* do stuff here*/ }, false);
используя этот подход (DOM Уровень 2 события), вы можете прикрепить теоретически неограниченное количество событий к любому отдельному элементу. Единственным практическим ограничением является память на стороне клиента и другие проблемы производительности, которые различны для каждого браузера.
приведенные выше примеры представляют собой использование анонимной функции[doc]. Вы также можете добавить прослушиватель событий, использующий ссылку на функцию[doc] или закрытие[doc]:
var myFunctionReference = function() { /* do stuff here*/ } element.attachEvent('onclick', myFunctionReference); element.addEventListener('click', myFunctionReference , false);
еще одна важная особенность
addEventListener
является последним параметром, который управляет тем, как слушатель реагирует на пузырящиеся события[doc]. Я передавал false в примерах, что является стандартным для, вероятно, 95% случаев использования. Нет эквивалентного аргумента дляattachEvent
, или при использовании встроенных событий.встроенные события (HTML onclick= "" свойство и элемент.onclick)
во всех браузерах, поддерживающих javascript, вы можете поместить прослушиватель событий в строку, что означает прямо в HTML-коде. Вы, наверное, видели это:
<a id="testing" href="#" onclick="alert('did stuff inline');">Click me</a>
большинство опытных разработчиков избегают этого метода, но он выполняет свою работу; это просто и прямо. Вы не можете использовать здесь замыкания или анонимные функции (хотя сам обработчик является анонимной функцией), и Ваш контроль над областью действия ограниченный.
другой метод, который вы упомянули:
element.onclick = function () { /*do stuff here */ };
... является эквивалентом встроенного javascript, за исключением того, что у вас больше контроля над областью (поскольку вы пишете сценарий, а не HTML) и можете использовать анонимные функции, ссылки на функции и/или закрытия.
существенным недостатком встроенных событий является то, что в отличие от описанных выше прослушивателей событий, Вам может быть назначено только одно встроенное событие. Встроенные события хранятся в виде атрибут/свойство элемента[doc], что означает, что он может быть перезаписан.
на примере
<a>
из HTML выше:var element = document.getElementById('testing'); element.onclick = function () { alert('did stuff #1'); }; element.onclick = function () { alert('did stuff #2'); };
... когда вы нажали на элемент, вы бы только см. "Did stuff #2" - вы переписали первый назначенный из
onclick
свойство со вторым значением, и вы переписали исходный встроенный HTMLonclick
тоже собственность. Проверьте это здесь: http://jsfiddle.net/jpgah/.что лучше?
вопрос заключается в совместимости браузера и необходимости. Нужно ли в настоящее время присоединять к элементу более одного события? Будете ли вы в будущем? Скорее всего, так и будет. attachEvent и addEventListener необходимы. Если нет, то встроенное событие будет делать трюк.
jQuery и другие платформы javascript инкапсулируют различные реализации браузера DOM события уровня 2 в общих моделях, чтобы вы могли писать кросс-браузерный совместимый код, не беспокоясь об истории IE как бунтаря. Тот же код с jQuery, все кросс-браузер и готов к рок:
$(element).on('click', function () { /* do stuff */ });
не выбегайте и не получите рамки только для этой одной вещи. Вы можете легко свернуть свою собственную небольшую утилиту, чтобы заботиться о старых браузерах:
function addEvent(element, evnt, funct){ if (element.attachEvent) return element.attachEvent('on'+evnt, funct); else return element.addEventListener(evnt, funct, false); } // example addEvent( document.getElementById('myElement'), 'click', function () { alert('hi!'); } );
попробуйте:http://jsfiddle.net/bmArj/
принимая все это во внимание рассмотрение, если сценарий, на который вы смотрите, не учитывает различия в браузере каким-либо другим способом (в коде, не показанном в вашем вопросе), часть использует
addEventListener
не будет работать в версиях IE ниже 9.документация и связанные с ней чтения
разница, которую вы могли бы увидеть, если бы у вас была еще пара функций:
var h = document.getElementById('a'); h.onclick = doThing_1; h.onclick = doThing_2; h.addEventListener('click', doThing_3); h.addEventListener('click', doThing_4);
функции 2, 3 и 4 работают, но 1 не. Это потому что
addEventListener
не перезаписывает существующие обработчики событий, тогда какonclick
переопределяет любые существующиеonclick = fn
обработчики событий.еще одно существенное различие, конечно, заключается в том, что
onclick
всегда будет работать, тогда какaddEventListener
не работает в Internet Explorer до версии 9. Вы можете использовать аналогичныйattachEvent
(который немного другой синтаксис) в IE
в этом ответе я опишу три метода определения обработчиков событий DOM.
element.addEventListener()
пример кода:
const element = document.querySelector('a'); element.addEventListener('click', event => event.preventDefault(), true);
<a href="//google.com">Try clicking this link.</a>
element.addEventListener()
имеет несколько преимуществ:
- позволяет Вам зарегистрироваться неограниченный обработчики событий и удалить их с
element.removeEventListener()
.- и
useCapture
параметр, который указывает, хотите ли вы обрабатывать событие в своем захват или пузырьковая фаза. Смотрите:невозможно понять атрибут useCapture в addEventListener.- заботится о семантика. В принципе, это делает регистрацию обработчиков событий более явной. Для новичка вызов функции делает очевидным, что что происходит, тогда как присвоение события некоторому свойству элемента DOM, по крайней мере, не интуитивно понятно.
- позволяет отдельная структура документа (HTML) и логика (JavaScript). В крошечной веб-приложений, это может показаться не имеет значения, но это тут дело с любым большим проектом. Гораздо проще поддерживать проект, который разделяет структуру и логику, чем проект, который этого не делает.
- устраняет путаницу с правильными именами событий. Из-за использования встроенных прослушивателей событий или назначения прослушивателей событий
.onevent
свойства элементов DOM, многие неопытные программисты JavaScript считают, что имя события, напримерonclick
илиonload
.on
и не часть имени события. Правильные имена событийclick
иload
, а вот как имена событий передают.addEventListener()
.- работает в почти всех браузеров. Если вам все еще нужно поддерживать IE полифилл от MDN.
element.onevent = function() {}
(например,onclick
,onload
)код пример:
const element = document.querySelector('a'); element.onclick = event => event.preventDefault();
<a href="//google.com">Try clicking this link.</a>
это был способ регистрации обработчиков событий в DOM 0. Теперь он обескуражен, потому что он:
- позволяет Вам зарегистрироваться единственный обработчик событий. Кроме того, удаление назначенного обработчика не является интуитивно понятным, потому что для удаления обработчика событий, назначенного с помощью этого метода, вы должны вернуться
onevent
свойство возвращаться в исходное состояние (т. е.null
).- не ответить ошибки надлежащим образом. Например, если вы по ошибке присвоить строку
window.onload
, например:window.onload = "test";
, он не будет бросать никаких ошибок. Ваш код не будет работать, и было бы очень трудно выяснить, почему..addEventListener()
однако, бросил бы ошибку (по крайней мере, в Firefox): TypeError: Аргумент 2 EventTarget.addEventListener не является объектом.- не предоставляет способ выбрать, хотите ли вы обрабатывать событие в его захвате или пузырении фаза.
встроенные обработчики событий (
onevent
HTML-атрибута)пример кода:
<a href="//google.com" onclick="event.preventDefault();">Try clicking this link.</a>
аналогично
element.onevent
, теперь он обескуражен. Кроме проблем, которыеelement.onevent
он:
- это потенциальная проблема безопасности, потому что это делает XSS гораздо более вредным. В настоящее время веб-сайты должны отправлять правильные
Content-Security-Policy
заголовок HTTP для блокировки встроенных скриптов и разрешения только внешних скриптов из доверенных доменов. Смотрите как работает политика безопасности контента?- не отдельная структура документа и логике.
- если вы создадите свою страницу с помощью сценария на стороне сервера, и, например, вы создадите сто ссылок, каждая с одним и тем же встроенным обработчиком событий, ваш код будет намного длиннее, чем если бы обработчик событий был определен только один раз. Это означает, что клиент должен будет загрузить больше контента, и в результате ваш сайт будет быть медленнее.
см. также
пока
onclick
работает во всех браузерах,addEventListener
не работает в старых версиях Internet Explorer, который используетattachEvent
вместо.недостаток
onclick
Это то, что может быть только один обработчик событий, в то время как другие два будут запускать все зарегистрированные обратные вызовы.
насколько я знаю, событие DOM "load" по-прежнему работает очень ограниченно. Это означает, что он будет стрелять только для
window object
,images
и<script>
элементы, например. То же самое касается прямогоonload
задание. Между ними нет никакой технической разницы. Наверное.onload =
имеет лучшую доступность кросс-браузера.однако, вы не можете назначить
load event
до<div>
или<span>
элемент или еще что-то.
Если вы не слишком беспокоитесь о поддержке браузера, есть способ повторно привязать ссылку "this" в функции, вызываемой событием. Обычно он указывает на элемент, который сгенерировал событие при выполнении функции, что не всегда соответствует вашим требованиям. Хитрая часть состоит в том, чтобы в то же время иметь возможность удалить тот же самый прослушиватель событий, как показано в этом примере:http://jsfiddle.net/roenbaeck/vBYu3/
/* Testing that the function returned from bind is rereferenceable, such that it can be added and removed as an event listener. */ function MyImportantCalloutToYou(message, otherMessage) { // the following is necessary as calling bind again does // not return the same function, so instead we replace the // original function with the one bound to this instance this.swap = this.swap.bind(this); this.element = document.createElement('div'); this.element.addEventListener('click', this.swap, false); document.body.appendChild(this.element); } MyImportantCalloutToYou.prototype = { element: null, swap: function() { // now this function can be properly removed this.element.removeEventListener('click', this.swap, false); } }
приведенный выше код работает хорошо в Chrome, и, вероятно, есть какая-то прокладка вокруг того, чтобы сделать "привязку" совместимой с другими браузерами.
использование встроенных обработчиков несовместимо с Политика Безопасности Контента так
addEventListener
подход является более безопасным с этой точки зрения. Конечно, вы можете включить встроенные обработчики сunsafe-inline
но, как следует из названия, это небезопасно, поскольку он возвращает целые орды эксплойтов JavaScript, которые предотвращает CSP.
одна деталь еще не была отмечена: современные настольные браузеры считают различные нажатия кнопок "щелчками" для
AddEventListener('click'
иonclick
по умолчанию.
- на Chrome 42 и IE11, оба
onclick
иAddEventListener
нажмите огонь на левой и средней кнопки мыши.- На Firefox 38,
onclick
огни только при щелчке левой кнопкой, ноAddEventListener
нажмите пожары слева, посередине и щелчки Правой Кнопкой Мыши.кроме того, поведение среднего щелчка очень несогласованность между браузерами, когда задействованы курсоры прокрутки:
- в Firefox события среднего клика всегда срабатывают.
- в Chrome они не будут срабатывать, если middleclick открывает или закрывает курсор прокрутки.
- в IE они срабатывают при закрытии курсора прокрутки, но не при его открытии.
также стоит отметить, что события "click" для любого выбираемого с клавиатуры HTML-элемента, такого как
input
также огонь на пробел или Enter когда элемент выбран.
также должно быть возможно либо расширить прослушиватель путем его прототипирования (если у нас есть ссылка на него и его не анонимная функция) - или сделать вызов "onclick" вызовом библиотеки функций (функция, вызывающая другие функции)
как
elm.onclick = myFunctionList function myFunctionList(){ myFunc1(); myFunc2(); }
это означает, что мы никогда не должны chenge вызов onclick просто изменить функцию myFunctionList (), чтобы делать то, что мы хотим, но это оставляет нас без контроля пузырящихся / ловить фазы, так что следует избегать для новый браузер.
только в случае, если кто-то найдет эту тему в будущем...
по данным MDN, разница, как показано ниже:
addEventListener:
EventTarget.addEventListener () метод добавляет указанный EventListener-совместимый объект со списком прослушивателей событий для указанный тип события на EventTarget, на котором он вызывается. Этот целью события может быть элемент в документе, сам документ, а Окно или любой другой объект, поддерживающий события (например объект XMLHttpRequest.)
onclick:
свойство onclick возвращает код обработчика событий щелчка на элемент тока. При использовании события click для запуска действия, также рассмотрите возможность добавления этого же действия к событию keydown, чтобы разрешить использование того же действия людьми, которые не используют мышь или прикосновение экран. Элемент синтаксиса.onclick = functionRef; где functionRef - это функция-часто имя объявленной функции в другом месте или функции выражение. Дополнительные сведения см. В разделе "Руководство по JavaScript:функции".
существует также синтаксическая разница в использовании, как вы видите в приведенных ниже кодах:
addEventListener:// Function to change the content of t2 function modifyText() { var t2 = document.getElementById("t2"); if (t2.firstChild.nodeValue == "three") { t2.firstChild.nodeValue = "two"; } else { t2.firstChild.nodeValue = "three"; } } // add event listener to table var el = document.getElementById("outside"); el.addEventListener("click", modifyText, false);
onclick:
function initElement() { var p = document.getElementById("foo"); // NOTE: showAlert(); or showAlert(param); will NOT work here. // Must be a reference to a function name, not a function call. p.onclick = showAlert; }; function showAlert(event) { alert("onclick Event detected!"); }
addEventListener
позволяет установить несколько обработчиков, но не поддерживается в IE8 и ниже.IE имеет
attachEvent
, но это не совсем то же самое.
Javascript имеет тенденцию смешивать все в объекты, и это может привести к путанице. Все в одном-это путь JavaScript.
по существу onclick является атрибутом HTML. И наоборот addEventListener-это метод для объекта DOM, представляющего элемент HTML.
в объектах JavaScript метод-это просто свойство, которое имеет функцию в качестве значения и которое работает против объекта, к которому оно прикреплено (например, используя это).
в JavaScript как HTML-элемент представленный DOM будет иметь его атрибуты, отображенные на его свойства.
здесь люди путаются, потому что JavaScript объединяет все в один контейнер или пространство имен без слоя косвенности.
в обычном макете OO (который, по крайней мере, объединяет пространство имен свойств/методов) вы могли бы иметь что-то вроде:
domElement.addEventListener // Object(Method) domElement.attributes.onload // Object(Property(Object(Property(String))))
есть варианты, как он может использовать геттер / сеттер для onload или HashMap для атрибутов, но в конечном счете, именно так это и будет выглядеть. JavaScript устранил этот слой косвенности, ожидая узнать, что есть что среди прочего. Он объединил domElement и атрибуты вместе.
запрет совместимости вы должны в качестве наилучшей практики использовать addEventListener. Поскольку другие ответы говорят о различиях в этом отношении, а не о фундаментальных программных различиях, я откажусь от этого. По сути, в идеальном мире вы действительно должны использовать только * из HTML, но в еще более идеальный мир вы не должны делать ничего подобного от HTML.
почему он доминирует сегодня? Это быстрее писать, легче учиться и, как правило, просто работать.
весь смысл onload в HTML заключается в том, чтобы предоставить доступ к методу или функциональности addEventListener в первую очередь. Используя его в JS, вы проходите через HTML, когда вы можете применять его напрямую.
гипотетически вы можете сделать свой собственный атрибуты:
$('[myclick]').each(function(i, v) { v.addEventListener('click', function() { eval(v.myclick); // eval($(v).attr('myclick')); }); });
то, что делает JS, немного отличается от этого.
вы можете приравнять его к чему-то вроде (для каждого созданного элемента):
element.addEventListener('click', function() { switch(typeof element.onclick) { case 'string':eval(element.onclick);break; case 'function':element.onclick();break; } });
фактические детали реализации, скорее всего, будут отличаться с диапазоном тонких вариаций, что делает их немного разными в некоторых случаях, но это суть.
это, возможно, Хак совместимости, что вы можете прикрепить функцию к атрибуту on, так как по умолчанию атрибуты все веревка.
резюме:
addEventListener
можно добавить несколько событий, в то время как сonclick
это невозможно сделать.onclick
может быть добавлен в качестве , тогда какaddEventListener
может быть добавлен только в<script>
элементы.addEventListener
может принять третий аргумент, который может остановить распространение событий.оба могут быть использованы для обработки событий. Однако,
addEventListener
должно быть предпочтительным выбором, так как он может сделать всеonclick
делает и многое другое. Не используйте inlineonclick
как атрибуты HTML, так как это смешивает javascript и HTML, что является плохой практикой. Это делает код менее ремонтопригодным.
контекст, на который ссылается
'this'
ключевое слово в JavasSript разные.посмотрите на следующий код:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> </head> <body> <input id="btnSubmit" type="button" value="Submit" /> <script> function disable() { this.disabled = true; } var btnSubmit = document.getElementById('btnSubmit'); btnSubmit.onclick = disable(); //btnSubmit.addEventListener('click', disable, false); </script> </body> </html>
то, что он делает, очень просто. при нажатии на кнопку, Кнопка будет отключена автоматически.
во-первых, когда вы пытаетесь подключить события таким образом
button.onclick = function(),
событие onclick будет вызвано нажатием кнопки, однако кнопка не будет отключена, потому что нет явной привязки между кнопками.onclick и обработчик события onclick. Если вы отлаживаете увидеть'this'
объект, вы можете видеть, что он относится к