Почему использование onClick() в HTML плохой практики?

Я слышал много раз, что использование JavaScript-событий, таких как onClick(), в HTML является плохой практикой, потому что это не хорошо для семантики. Я хотел бы знать, что это за недостатки и как исправить следующий код?

<a href="#" onclick="popup('/map/', 300, 300, 'map'); return false;">link</a>

Ответ 1

Вероятно, вы говорите ненавязчивый Javascript, который будет выглядеть следующим образом:

<a href="#" id="someLink">link</a>

с логикой в ​​центральном файле javascript, выглядящим примерно так:

$('#someLink').click(function(){
    popup('/map/', 300, 300, 'map'); 
    return false;
});

Преимущества

  • поведение (Javascript) отделено от представления (HTML)
  • Отсутствие смешивания языков
  • вы используете фреймворк javascript, такой как jQuery, который может обрабатывать большинство проблем с несколькими браузерами для вас.
  • Вы можете добавить поведение к множеству HTML-элементов сразу без дублирования кода.

Ответ 2

Если вы используете jQuery, тогда:

HTML:

 <a id="openMap" href="/map/">link</a>

JS:

$(document).ready(function() {
    $("#openMap").click(function(){
        popup('/map/', 300, 300, 'map');
        return false;
    });
});

Это полезно для работы без JS, или если пользователь посещает среднюю ссылку.

Это также означает, что я мог обрабатывать общие всплывающие окна, переписывая снова:

HTML:

 <a class="popup" href="/map/">link</a>

JS:

$(document).ready(function() {
    $(".popup").click(function(){
        popup($(this).attr("href"), 300, 300, 'map');
        return false;
    });
});

Это позволит вам добавить всплывающее окно к любой ссылке, просто предоставив ему всплывающий класс.

Эта идея может быть продолжена еще дальше:

HTML:

 <a class="popup" data-width="300" data-height="300" href="/map/">link</a>

JS:

$(document).ready(function() {
    $(".popup").click(function(){
        popup($(this).attr("href"), $(this).data('width'), $(this).data('height'), 'map');
        return false;
    });
});

Теперь я могу использовать один и тот же бит кода для большого количества всплывающих окон на моем сайте, не загружая лишние вещи onclick! Yay для повторного использования!

Это также означает, что если позже я решаю, что всплывающие окна - это плохая практика (они есть!) и что я хочу заменить их модальным окном в стиле лайтбокса, я могу изменить:

popup($(this).attr("href"), $(this).data('width'), $(this).data('height'), 'map');

к

myAmazingModalWindow($(this).attr("href"), $(this).data('width'), $(this).data('height'), 'map');

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

Ответ 3

Это не очень полезно по нескольким причинам:

  • он смешивает код и разметку
  • написанный таким образом код проходит через eval
  • и работает в глобальной области

Простейшей задачей было бы добавить атрибут name к вашему элементу <a>, тогда вы могли бы сделать:

document.myelement.onclick = function() {
    window.popup('/map/', 300, 300, 'map');
    return false;
};

хотя лучше всего использовать id вместо имени и использовать addEventListener() вместо использования onclick, поскольку это позволяет связывать несколько функций с одним событием.

Ответ 4

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

Возможно, вы видели файлы JS, которые выглядят так:

(function(){
    ...[some code]
}());

Это выраженные выражения с мгновенной выдержкой (IIFE), и любая заявленная внутри них функция будет существовать только в пределах их внутренней области.

Если вы объявите function doSomething(){} внутри IIFE, сделайте doSomething() действие onClick элемента на вашей HTML-странице, вы получите сообщение об ошибке.

Если, с другой стороны, вы создаете eventListener для этого элемента внутри этого IIFE и вызываете doSomething(), когда слушатель обнаруживает событие клика, вы хороши, потому что слушатель и doSomething() разделяют область IIFE.

Для маленьких веб-приложений с минимальным количеством кода это не имеет значения. Но если вы стремитесь написать большие, поддерживаемые кодовые базы, onclick="" - это привычка, которую вы должны избегать.

Ответ 5

Есть несколько причин:

  • Я нахожу, что это помогает поддерживать разметку, то есть HTML и клиентские скрипты. Например, jQuery упрощает добавление обработчиков событий программно.

  • Пример, который вы даете, будет нарушен в любом пользовательском агенте, который не поддерживает javascript, или отключен javascript. Концепция прогрессивного улучшения будет способствовать простой гиперссылке на /map/ для пользовательских агентов без javascript, а затем добавляет обработчик кликов для пользовательских агентов, которые поддерживают JavaScript.

Например:

Разметка:

<a id="example" href="/map/">link</a>

JavaScript:

$(document).ready(function(){

    $("#example").click(function(){
        popup('/map/', 300, 300, 'map');
        return false;
    });

})

Ответ 6

Это a новая парадигма, называемая ненавязчивый JavaScript ". В текущем" веб-стандарте" говорится о разделении функциональности и презентации.

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

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

Ответ 7

Ваш вопрос вызовет обсуждение, я полагаю. Общая идея заключается в том, что хорошо отделить поведение и структуру. Кроме того, afaik, встроенный обработчик кликов должен быть eval, чтобы "стать" реальной функцией javascript. И это довольно старомодно, тем не менее, это довольно шаткий аргумент. Ах, ну, читайте об этом @quirksmode.org

Ответ 8

Редакция

Ненавязчивый подход JavaScript был хорош в PAST - особенно связывание обработчиков событий в HTML считалось плохой практикой (главным образом потому, что onclick events run in the global scope and may cause unexpected error было упомянуто YiddishNinja)

Однако...

В настоящее время кажется, что этот подход немного устарел и нуждается в некотором обновлении. Если кто-то хочет стать профессиональным разработчиком веб-интерфейса и писать большие и сложные приложения, ему нужно использовать такие фреймворки, как Angular, Vue.js и т.д. Однако эти фреймворки обычно используют (или позволяют использовать) HTML-шаблоны где обработчики событий привязываются непосредственно к коду html-шаблона, и это очень удобно, понятно и эффективно - например, в angular шаблонах обычно пишут люди:

<button (click)="someAction()">Click Me</button> 

В необработанном js/html эквивалентом этого будет

<button onclick="someAction()">Click Me</button>

Разница в том, что в raw js событие onclick запускается в глобальной области видимости, но платформы обеспечивают инкапсуляцию.

Так в чем же проблема?

Проблема в том, что начинающий программист, который всегда слышал, что html-onclick плох, и кто всегда использует btn.addEventListener("onclick", ... ), хочет использовать какую-то инфраструктуру с шаблонами (у addEventListener также есть недостатки - если мы обновляем DOM динамически используя innerHTML= (что довольно быстро) - тогда мы теряем привязку обработчиков событий таким образом). Тогда он столкнется с чем-то вроде вредных привычек или неправильного подхода к использованию фреймворка - и он будет очень плохо использовать фреймворк - потому что он сосредоточится в основном на js-части, а не на шаблонной части (и будет производить неясные и сложные в обслуживании код). Чтобы изменить эти привычки, он потеряет много времени (и, возможно, ему понадобится удача и учитель).

Так что, на мой взгляд, исходя из опыта моих учеников, было бы лучше для них, если бы они использовали html-handlers-bind в начале. Как я уже сказал, это правда, что обработчики вызываются в глобальной области, но на этом этапе студенты обычно создают небольшие приложения, которыми легко управлять. Для написания больших приложений они выбирают несколько фреймворков.

Так что же делать?

Мы можем ОБНОВИТЬ ненавязчивый подход JavaScript и разрешить обработчики событий связывания (в конечном итоге с простыми параметрами) в html (но только обработчик связывания - не помещать логику в onclick, как в задании OP). Так что, по моему мнению, в raw js/html это должно быть разрешено

<button onclick="someAction(3)">Click Me</button>

или

function popup(num,str,event) {
   let re=new RegExp(str);  
   // ... 
   event.preventDefault();
   console.log("link was clicked");
}
<a href="https://example.com" onclick="popup(300,'map',event)">link</a>

Ответ 9

  • События onclick запускаются в глобальной области видимости и могут вызвать непредвиденную ошибку.
  • Добавление событий onclick ко многим элементам DOM замедлит
    производительность и эффективность.