Яка різниця між addEventListener
і onclick
?
var h = document.getElementById("a");
h.onclick = dothing1;
h.addEventListener("click", dothing2);
Код, що знаходиться вище, знаходиться разом у окремому файлі .js, і вони обидва чудово працюють.
Яка різниця між addEventListener
і onclick
?
var h = document.getElementById("a");
h.onclick = dothing1;
h.addEventListener("click", dothing2);
Код, що знаходиться вище, знаходиться разом у окремому файлі .js, і вони обидва чудово працюють.
Відповіді:
Обидва є правильними, але жоден з них не є "найкращим" сам по собі, і може бути причина, яка розробник вирішив використовувати обидва підходи.
Слухачі подій (addEventListener та IE's 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 ]. Я наводив помилки в прикладах, що є стандартним для 95% випадків використання. Не існує еквівалентного аргументу для attachEvent
або вбудованих подій.
Вбудовані події (HTML onclick = "" властивість та element.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'); };
... натиснувши елемент, ви побачили лише "Зробив номер 2" - ви перезаписали перший присвоєний onclick
ресурс з другим значенням, і ви також перезаписали оригінальну вбудовану onclick
властивість HTML . Перевірте це тут: http://jsfiddle.net/jpgah/ .
Взагалі кажучи, не використовуйте вбудовані події . Для цього можуть бути конкретні випадки використання, але якщо ви не впевнені на 100%, що маєте такий випадок використання, тоді ви не використовуєте і не повинні використовувати вбудовані події.
Сучасний Javascript (кутовий тощо)
Оскільки ця відповідь була опублікована спочатку, рамки javascript на зразок Angular стали набагато популярнішими. Ви побачите такий код у кутовому шаблоні:
<button (click)="doSomething()">Do Something</button>
Це виглядає як вбудована подія, але це не так. Цей тип шаблону буде перетворений у більш складний код, який використовує слухачів подій за кадром. Все, що я писав про події тут, як і раніше, стосується, але ви видаляєтеся з нітроподібної зернистості хоча б на один шар. Ви повинні розуміти гайки та болти, але якщо ваші сучасні найкращі практики JS передбачають написання такого коду в шаблоні, не відчувайте, що ви використовуєте вбудований захід - ви цього не робите.
Що найкраще?
Питання - питання сумісності браузера та необхідності. Чи потрібно приєднувати до елемента кілька подій? Чи будете ви в майбутньому? Шанси є, ти будеш. attachEvent і addEventListener необхідні. Якщо ні, то подібна подія може здатися, що вони би зробили трюк, але вам набагато краще подавати підготовку до майбутнього, яке, хоч і може здатися малоймовірним, принаймні передбачуване. Є ймовірність, що вам доведеться перейти до слухачів подій на базі JS, тож ви можете просто почати там. Не використовуйте вбудовані події.
jQuery та інші рамки javascripsulate різні реалізації браузера подій 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.
Документація та відповідне читання
function addEvent(e,n,f){return e.attachEvent?e.attachEvent('on'+n,f):e.addEventListener(n,f,!!0)}
<< На 98 символів цей на 40% менше!
Різницю, яку ви могли побачити, чи були у вас ще кілька функцій:
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 <9.
У цій відповіді я опишу три методи визначення обробників подій DOM.
element.addEventListener()
Приклад коду:
element.addEventListener()
має ряд переваг:
element.removeEventListener()
.useCapture
параметр, який вказує, чи хочете ви обробляти подію у фазі її захоплення чи барботування . Див.: Неможливо зрозуміти атрибут useCapture в addEventListener ..onevent
властивостей елементів DOM, багато недосвідчених програмістів JavaScript вважає, що назва події є, наприклад, onclick
або onload
. on
це НЕ частина назви події . Правильні імена подій click
і load
, і це, як імена подій передаються .addEventListener()
.element.onevent = function() {}
(наприклад onclick
, onload
)Приклад коду:
Це був спосіб зареєструвати обробників подій у DOM 0. Зараз це не рекомендується, оскільки це:
onevent
властивість до його початкового стану (тобто null
).window.onload
, наприклад:, window.onload = "test";
він не видасть жодних помилок. Ваш код не працює, і було б дуже важко з'ясувати, чому. .addEventListener()
однак, викине помилку (принаймні, у Firefox): TypeError: Аргумент 2 EventTarget.addEventListener не є об'єктом .onevent
атрибут HTML)Приклад коду:
Так само element.onevent
, як і зараз, це не відлякує. Окрім проблем, які element.onevent
є:
Content-Security-Policy
HTTP-заголовок для блокування вбудованих сценаріїв і дозволяти зовнішнім скриптам лише з надійних доменів. Див. Як працює Політика безпеки вмісту?Наскільки мені відомо, подія "завантаження" DOM все ще працює лише дуже обмежено. Це означає , що він буде стріляти тільки для window object
, images
і <script>
елементи , наприклад. Те саме стосується прямого onload
завдання. Технічної різниці між цими двома немає. Можливо .onload =
, є краща доступність крос-браузера.
Однак ви не можете призначити load event
a <div>
або <span>
елемент чи що.
addEventListener
можна додати кілька подій, тоді як з onclick
цим неможливо зробити.onclick
можна додати як HTML
атрибут, тоді як addEventListener
додати можна лише в межах <script>
елементів.addEventListener
можна взяти третій аргумент, який може зупинити поширення події.Обидва можна використовувати для обробки подій. Однак, addEventListener
найкращим вибором має бути, оскільки він може робити все onclick
, і більше. Не використовуйте inline onclick
як атрибути HTML, оскільки це змішує javascript та HTML, що є поганою практикою. Це робить код менш ретельним.
onclick
довідники, боячись не засміяти кімнату - але зазвичай події пов'язані набагато гірше і менш ретельно. Класи подобаються js-link
, js-form-validation
або атрибути даних з data-jspackage="init"
нічим не краще ... А як ofteen ви на самому справі використовувати булькання події? Я особисто хотів би мати можливість написати обробник, не перевіряючи, чи ціль насправді відповідає моєму елементу - або припиняти розповсюдження в декількох місцях через випадкові помилки.
Одна деталь не було помічено ще: сучасні настільні браузери розглядають різні натискання кнопок , щоб бути «клацання» для AddEventListener('click'
і onclick
за замовчуванням.
onclick
та AddEventListener
натискають на ліву та середню клавішу.onclick
спрацьовує лише лівою кнопкою миші, але AddEventListener
натискає пожежі лівою, середньою та правою клацаннями.Крім того, поведінка середнього клацання дуже непослідовна у веб-переглядачах, коли задіяні курсори прокрутки:
Варто також відзначити, що події "клацання" для будь-якого елемента HTML, що вибирається клавіатурою, наприклад, input
стріляти по простору або вводити, коли елемент вибраний.
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))))
Існують варіанти, як це може використовувати getter / setter для onload або HashMap для атрибутів, але в кінцевому підсумку саме так воно буде виглядати. JavaScript усунув цей шар непрямості, очікуючи того, що дізнається, що між іншим. Він об'єднав domElement і атрибути разом.
Для сумісності із забороною вам слід найкращим чином використовувати addEventListener. Оскільки інші відповіді говорять про відмінності в цьому плані, а не про фундаментальні програмні відмінності, я пробую цього. По суті, в ідеальному світі ви дійсно призначені лише для використання * з HTML, але в ще більш ідеальному світі ви не повинні робити нічого подібного з HTML.
Чому вона домінує сьогодні? Швидше писати, легше вчитися і прагне просто працювати.
Вся суть завантаження в 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, оскільки за замовчуванням атрибути - це всі рядки.
За даними MDN , різниця полягає в наступному:
addEventListener:
Метод EventTarget.addEventListener () додає вказаний об'єкт, сумісний з EventListener, до списку слухачів подій для вказаного типу події в EventTarget, на який він викликається. Ціль події може бути Елементом у документі, самому Документі, Вікні чи будь-якому іншому об'єкті, який підтримує події (наприклад, XMLHttpRequest).
onclick:
Властивість onclick повертає код обробника подій кліку на поточному елементі. Під час використання події клацання для запуску дії також врахуйте додавання цієї самої дії до події клавіатури, щоб дозволити використовувати цю саму дію людям, які не використовують мишу чи сенсорний екран. Синтаксичний елемент.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!");
}
Якщо ви не надто переживаєте підтримку веб-переглядача, є спосіб відновити посилання "це" у функції, викликаній подією. Це, як правило, вказує на елемент, який генерував подію при виконанні функції, що не завжди є тим, що потрібно. Складна частина полягає в тому, щоб одночасно мати змогу видалити той самий слухач подій, як показано в цьому прикладі: 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.
Слід також мати можливість або розширити слухача шляхом прототипування його (якщо у нас є посилання на нього, а не на анонімну функцію) - або зробити виклик "onclick" викликом до бібліотеки функцій (функція, що викликає інші функції)
подібно до
elm.onclick = myFunctionList
function myFunctionList(){
myFunc1();
myFunc2();
}
це означає, що нам ніколи не доводиться виконувати виклик onclick, просто змінювати функцію myFunctionList (), щоб робити все, що завгодно, але це залишає нас без контролю фаз барботажу / лову, тому слід уникати нових браузерів.
про всяк випадок, коли хтось знайде цю нитку в майбутньому ...
element.onclick = function () {/ * робити речі * /}
element.addEventListener ('клацання', функція () {/ * робити речі * /}, помилково);
Вони, мабуть, роблять те ж саме: прослуховують подію клацання та виконують функцію зворотного виклику. Тим не менш, вони не рівноцінні. Якщо вам коли-небудь потрібно вибирати між цими двома, це може допомогти вам зрозуміти, який з них найкращий для вас.
Основна відмінність полягає в тому, що onclick - це просто властивість , і, як і всі властивості об'єкта, якщо ви пишете кілька разів, він буде перезаписаний . З addEventListener () замість цього, ми можемо просто прив'язати обробник події до елементу, і ми можемо назвати це кожен раз , коли нам це потрібно , не турбуючись про які - або перезаписані властивості. Тут показаний приклад,
Спробуйте: https://jsfiddle.net/fjets5z4/5/
В першу чергу я спокусився продовжувати користуватися onclick, тому що він коротший і виглядає простіше ... а насправді так. Але я більше не рекомендую його використовувати. Це так само, як використання вбудованого JavaScript. Використання чогось подібного - це вбудований JavaScript - в даний час сильно не рекомендується (вбудований CSS теж не відсторонений, але це вже інша тема).
Однак функція addEventListener (), незважаючи на стандарт, просто не працює у старих браузерах (Internet Explorer нижче версії 9), і це ще одна велика різниця. Якщо вам потрібно підтримати ці старовинні браузери, вам слід слідувати способу onclick. Але ви також можете використовувати jQuery (або одну з його альтернатив): це в основному спрощує вашу роботу і зменшує розбіжності між браузерами, тому може заощадити багато часу.
var clickEvent = document.getElementByID("onclick-eg");
var EventListener = document.getElementByID("addEventListener-eg");
clickEvent.onclick = function(){
window.alert("1 is not called")
}
clickEvent.onclick = function(){
window.alert("2 is not called")
}
EventListener.addEventListener("click",function(){
window.alert("1 is called")
})
EventListener.addEventListener("click",function(){
window.alert("2 is also called")
})
addEventListener
дозволяє встановлювати кілька обробників, але це не підтримується в IE8 або новіших версіях.
IE є attachEvent
, але це не зовсім те саме.
Контекст, на який посилається '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 буде викликано натисканням кнопки, однак кнопка не буде відключена, оскільки немає явного прив'язки між button.onclick та обробником подій onclick. Якщо ви налагодите бачити 'this'
об’єкт, ви можете бачити, що він посилається на 'window'
об'єкт.
По-друге, якщо ви коментуєте btnSubmit.onclick = disable();
та не
коментуєте, //btnSubmit.addEventListener('click', disable, false);
ви можете побачити, що кнопка відключена, оскільки таким чином відбувається явне прив’язання між події button.onclick та обробником події onclick. Якщо ви налагодите функцію відключення, ви можете бачити, що 'this'
стосується, button control
а неwindow
.
Це те, що мені не подобається в JavaScript, що є непослідовністю. Btw, якщо ви використовуєте jQuery ( $('#btnSubmit').on('click', disable);
), він використовує явне прив'язування.
btnSubmit.onclick = disable;
(призначити функцію, а не викликати її). Тоді в обох випадках this
буде посилатися на елемент кнопки.
onclick - це в основному addEventListener, який спеціально виконує функцію при натисканні на елемент. Отже, корисно, коли у вас є кнопка, яка виконує прості операції, як, наприклад, кнопка калькулятора. addEventlistener можна використовувати для безлічі речей, таких як виконання операції, коли DOM або весь вміст завантажений, схожий на window.onload, але з більшим контролем.
Зауважте, ви можете реально використовувати більше однієї події за допомогою вбудованого рядка або принаймні за допомогою onclick, відокремлюючи кожну функцію крапкою з двокрапкою, як це ....
Я б не писав функцію з inline, оскільки у вас потенційно можуть виникнути проблеми пізніше, і це було б безладно imo. Просто використовуйте його для виклику функцій, вже виконаних у вашому файлі сценарію.
Який із них ви використовуєте, я думаю, залежатиме від того, що ви хочете. addEventListener для складних операцій та onclick для простих. Я бачив, як деякі проекти не прикріплюють конкретний елемент до елементів, а натомість реалізують більш глобальний eventlistener, який би визначав, чи натискає кнопка та виконує певні завдання залежно від того, що натиснуто. Я думаю, що це може призвести до проблем, я б подумав, і, мабуть, малий, мабуть, витрата ресурсів, якби цьому eventlistener мав обробляти кожен клік
function addEvent(element, myEvent, fnc) { return ((element.attachEvent) ? element.attachEvent('on' + myEvent, fnc) : element.addEventListener(myEvent, fnc, false)); }