Onclick = "" против обработчика событий

Если я хочу, чтобы функция была выполнена, я предпочитаю делать inline js:

<p id="element" onclick="doSomething();">Click me</p>

потому что его легче отлаживать.

Однако я слышал, как люди говорили, что не используют встроенные js, и делают:

document.getElementById('element').onclick = doSomething;

Почему рекомендуется прослушиватель событий js?

Ответ 1

В основном это связано с тем, что все держит все отдельно, я верю. Поэтому держите HTML/CSS/JS в отдельности. Это делает ваш HTML более аккуратным и, я думаю, легче ориентироваться без него.

Затем, когда/если вам нужно внести большие изменения, у вас есть достаточно места, чтобы в любом случае переместить встроенный JS во внешний файл или если вы хотите применить одну и ту же функцию к нескольким кнопкам, то это меньше кода. И меньше кода - более счастливое место.

Если у вас есть файлы JS правильно и тщательно задокументированы, а затем переадресовать их внешним человеком, сделайте eaiser

Ответ 2

Один большой аргумент против встроенных обработчиков событий и аргумент, который решается другими ответами, - это разделение представления и логики.

Однако на самом деле существует большая проблема IMO: как-то неуловимый способ оценки обработчиков inline-событий.

Как вы можете теперь, содержимое атрибутов on* будет использоваться как тело функции обработчика событий. Но каковы характеристики этой функции?

Одним из удивительных является то, что свойства некоторых элементов-предков и самого элемента находятся в области обработчика inline-событий,

Вот пример:

<form>
    <input name="foo" />
    <button type="button" onclick="console.log(foo); console.log(window.foo);">
        Click me
    </button>
    <div onclick="console.log(foo);">Click me as well!</div>
</form>

Нажатие button журналов

[object HTMLInputElement]
undefined

в консоли. Тот факт, что window.foo равен undefined, указывает, что глобальная переменная foo отсутствует. Итак, откуда взялась переменная foo? Почему console.log(foo) регистрирует входной элемент, а не вызывает опорную ошибку?
Поскольку свойства элемента form находятся в области действия обработчика события, а элемент form имеет свойство для каждого элемента управления указанной формы. Вы можете легко проверить это с помощью console.log(document.querySelector('form').foo).

Теперь щелчок по элементу div действительно вызывает ошибку ссылки:

ReferenceError: foo is not defined

Таким образом, видимо, элемент form находится только в области элементов управления формой, а не для потомков. Насколько запутанно это?

Аналогично, свойства объекта document также входят в объем встроенных обработчиков событий, которые могут привести к к некоторым неожиданным ошибкам (знаете ли вы, что document имеет свойство plugins?).

Как точно оцениваются обработчики inline-событий, формализованы в спецификации HTML5. На этапе 10, в частности, там, где описывается создание цепочки видимости.


Заключение

Из-за этого неявного соединения между элементами и встроенных обработчиков событий ошибки могут быть очень трудными для отслеживания. Конечно, отлично использовать обработчики событий inline, если вы просто хотите что-то проверить. Но использование их в производственном коде требует более высоких затрат на обслуживание.

Статьи на quirksmode.org объясняют разные способы привязки обработчиков событий и их (dis) преимуществ.

Ответ 3

Есть много причин, чтобы избежать встроенного JavaScript, и одним из наиболее важных из них является поддержка кода.

Быстрый пример (я использую jQuery только для демонстрационных целей).

<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>

Что делать, если вдруг вы получите запрос на изменение всех своих абзацев, чтобы выполнить другую функцию? В вашем примере вам придется изменить все вручную в своем HTML-коде. Однако, если вы решите отделить HTML от JavaScript, вы можете просто сделать это следующим образом.

<p class="element">Click me</p>
<p class="element">Click me</p>
<p class="element">Click me</p>
<p class="element">Click me</p>
<p class="element">Click me</p>
<p class="element">Click me</p>

$('.element').bind('click', doSomethingElse);

HTML-код также является более чистым, что позволяет дизайнерам сосредоточиться исключительно на дизайне, не опасаясь, что они могут что-то сломать во время работы над проектом, который также включает других людей.

РЕДАКТИРОВАТЬ: Предоставление примера для комментариев ниже.

Project = {
    // All the variables/constants/objects that need to be globally accessible inside the Project object.

    init : function(){
        // Main entry point...
        this.MainMenu.init();

        // Rest of the code which should execute the moment Project is initiated.
    }
}

Project.MainMenu = {
    // All the variables/constants/objects that need to be accessible only to MainMenu.

    init : function(){ // Is run immediatelly by Project.init()
        // Event handlers relevant to the main menu are bound here

        // Rest of the initialization code
    }
}

Project.SlideShow = {
    // All the variables/constants/objects that need to be accessible only to SlideShow.

    init : function(){ // Is run only on pages that really require it.
        // Event handlers for the slideshow.
    }
}

Ответ 4

Несмотря на то, что могут подумать другие люди, я думаю, что есть возможность искупать слушателей в разметке. В частности, это дает вам гораздо больше возможностей для изменения узлов DOM. Если вы добавляете слушателей, хотя JavaScript, слушатели теряются при замене innerHTML любых родительских узлов. Если вы вставляете слушателей в разметку, вы можете клонировать node, вносить в нее изменения, а затем заменить исходный node на node, который вы только что клонировали и модифицировали.

Возможно, лучше описать его в конкретном прецеденте. Я хочу внести изменения в несколько частей документа, не вызывая многократную перезагрузку. Таким образом, в этом случае я могу клонировать node, вносить в него какие-либо изменения (без reflow с его отсоединения), а затем заменить предыдущий node на модифицированный (запуск одного пересчета). Благодаря встроенным слушателям это предотвращает потерю любого слушателя во время замены.

Ответ 5

Я вижу, что некоторые говорят, что необходимо разделять озабоченность по поводу представления и бизнес-логики.

OP в своем примере действительно показывает это разделение! В обработчике событий inline нет никакой логики, а просто ссылка на функцию/вызов, которая будет выполнена в событии "click"... сама логика может быть отдельно сохранена в другом месте.

Я лично предпочитаю этот подход из-за возможности обнаружения логического потока. Если я никогда не видел приложение раньше... первое, что я собираюсь начать, обход кода в DOM, и там будет ясно, какие обработчики событий находятся в игре и какие функции предоставляют логику для обработчики. С использованием, скажем, подхода JQuery.On, просто просматривая html, вы не представляете, какие обработчики фактически подключены и предоставляют функциональность.

Обработчики событий Inline, которые просто предоставляют указатели на функции, просто соединяют события и не пропускают логику в презентацию.

Ответ 6

Вы можете сказать то же самое о CSS и включая встроенные стили. Было бы легко не пропустить через файл css, чтобы найти текущий класс /id или родительские/дочерние элементы, с которыми вы работаете.

Действительно ли лучше привязать клик, чтобы сказать 10 разных элементов? Или только один обработчик событий, предназначенный для класса? Даже если вам не нужны 10 обработчиков кликов, всегда есть лучшая идея, чтобы настроить код на ремонтопригодность и обновить дорогу.

Ответ 7

Я не знаю о преимуществах использования встроенного обработчика и не добавляю обработчика позже. По моему опыту, я предпочитаю использовать встроенный метод, когда мне приходится иметь дело с динамическим элементом, например, я хочу добавить обработчик к каждому изображению, а число изображений изменяется в соответствии с другими данными (ex images in db). В этом случае, используя inline, я могу добавить обработчик для каждого изображения, иначе мне придется пересчитать количество изображений в файле javascript для прикрепления и обработки каждого изображения.

Конечно, когда вы можете использовать библиотеки, такие как jQuery, где вы можете легко получить список встроенных элементов, не полезны

Ответ 8

Помимо перспективы стандартов кодирования

Использование атрибутов:

<p id="element" onclick="doSomething();">Click me</p>

если вы снова добавите тот же атрибут (см. ниже) -the рассмотрен последний.

<p id="element" onclick="doSomethingMore();">Click me</p>

Использование обработчика событий:

document.getElementById('element').onclick = doSomething;

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

document.getElementById('element').onclick = doSomethingMore; Вызывается оба обработчика.