addEventListener против onclick - PullRequest
622 голосов
/ 14 июня 2011

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

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

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

Ответы [ 14 ]

1 голос
/ 14 марта 2014

Если вы не слишком беспокоитесь о поддержке браузера, есть способ перепривязать ссылку «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, и, возможно, есть некоторая подкладкавокруг обеспечения совместимости «bind» с другими браузерами.

0 голосов
/ 08 марта 2017

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.

Почему это доминирует сегодня?Его легче писать, легче изучать и он просто работает.

Весь смысл загрузки в 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, поскольку по умолчанию все атрибуты являются строками.

0 голосов
/ 13 января 2014

Контекст, на который ссылается ключевое слово '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, который является непоследовательным.Кстати, если вы используете jQuery ($('#btnSubmit').on('click', disable);), он использует явное связывание.

0 голосов
/ 14 июня 2011

addEventListener позволяет вам установить несколько обработчиков, но не поддерживается в IE8 или ниже.

IE имеет attachEvent, но это не совсем то же самое.

...