метод addEventListener против щелчку


В чем разница между addEventListener и onclick?

var h = document.getElementById("a");
h.onclick = dothing1;
h.addEventListener("click", dothing2);

приведенный выше код находится вместе в отдельном .файл JS, и они оба работают отлично.

14 527

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 свойство со вторым значением, и вы переписали исходный встроенный HTML onclick тоже собственность. Проверьте это здесь: 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, так как по умолчанию атрибуты все веревка.

резюме:

  1. addEventListener можно добавить несколько событий, в то время как с onclick это невозможно сделать.
  2. onclick может быть добавлен в качестве , тогда как addEventListener может быть добавлен только в <script> элементы.
  3. addEventListener может принять третий аргумент, который может остановить распространение событий.

оба могут быть использованы для обработки событий. Однако,addEventListener должно быть предпочтительным выбором, так как он может сделать все onclick делает и многое другое. Не используйте inline onclick как атрибуты 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' объект, вы можете видеть, что он относится к