Я много раз слышал, что использование событий JavaScript, например onClick()
, в HTML, является плохой практикой, потому что это плохо для семантики. Я хотел бы знать, каковы недостатки и как исправить следующий код?
<a href="#" onclick="popup('/map/', 300, 300, 'map'); return false;">link</a>
javascript
html
Нилл
источник
источник
#
, любой, кто решит отключить javascript, застрянет и не сможет ничего делать. Для некоторых сайтов это хорошо, но для простого открытия окна просто глупо не предоставлять «настоящую» ссылку.<button>
, потому что ссылки должны указывать на реальный ресурс. Так он более семантичен и понятен пользователям программ чтения с экрана.Ответы:
Вы, наверное, говорите о ненавязчивом Javascript , который выглядел бы так:
с логикой в центральном файле javascript, выглядящей примерно так:
Преимущества
источник
onClick
. Вы также можете писать модульные тесты, если хотите противостоять своим скриптам, что также очень сложно, я бы предположил, что код находится внутриonClick
и никакая логика не разделена. Лично у меня нет проблем с отладкой ненавязчивого JavaScript, и преимущества в управлении и тестировании кода JavaScript слишком велики, чтобы не использовать его.onclick
могут более четко отобразить причинно-следственные связи между взаимодействием элемента и эффектом (вызовом функции), а также снизить когнитивную нагрузку. Многие уроки бросают учащихся в то,addEventListener
что объединяет гораздо больше идей в более сложный синтаксис. Более того, последние компонентные фреймворки, такие как Riot и React, используют этотonclick
атрибут и меняют представление о том, каким должно быть разделение. Переход от HTMLonclick
к компоненту, который поддерживает это, может быть более эффективным «пошаговым» процессом обучения.Если вы используете jQuery, тогда:
HTML:
JS:
Преимущество этого заключается в том, что он по-прежнему работает без JS или если пользователь среднего уровня щелкает ссылку.
Это также означает, что я мог обрабатывать общие всплывающие окна, снова переписав их на:
HTML:
JS:
Это позволит вам добавить всплывающее окно к любой ссылке, просто присвоив ему класс всплывающего окна.
Эту идею можно было бы расширить еще дальше:
HTML:
JS:
Теперь я могу использовать один и тот же фрагмент кода для множества всплывающих окон на всем моем сайте, без необходимости писать множество файлов onclick! Ура за возможность повторного использования!
Это также означает, что если позже я решу, что всплывающие окна - плохая практика (а это так!) И что я хочу заменить их модальным окном в стиле лайтбокса, я могу изменить:
в
и все мои всплывающие окна на всем моем сайте теперь работают совершенно по-другому. Я мог бы даже выполнить обнаружение функций, чтобы решить, что делать во всплывающем окне, или сохранить предпочтения пользователей, разрешать им или нет. С встроенным onclick это требует огромных усилий по копированию и вставке.
источник
С очень большими приложениями JavaScript программисты используют больше инкапсуляции кода, чтобы избежать загрязнения глобальной области. И чтобы сделать функцию доступной для действия onClick в элементе HTML, она должна быть в глобальной области.
Возможно, вы видели файлы JS, которые выглядят так ...
Это выражения с немедленным вызовом функций (IIFE), и любая объявленная в них функция будет существовать только в пределах их внутренней области.
Если вы объявляете
function doSomething(){}
в IIFE, а затемdoSomething()
выполняете действие onClick элемента на своей HTML-странице, вы получите сообщение об ошибке.Если, с другой стороны, вы создаете eventListener для этого элемента внутри этого IIFE и вызываете его,
doSomething()
когда слушатель обнаруживает событие щелчка, вы в порядке, потому что слушатель иdoSomething()
разделяют область действия IIFE.Для небольших веб-приложений с минимальным объемом кода это не имеет значения. Но если вы стремитесь писать большие, поддерживаемые кодовые базы,
onclick=""
это привычка, которой вам следует избегать.источник
Это нехорошо по нескольким причинам:
eval
Самым простым было бы добавить
name
атрибут к вашему<a>
элементу, после чего вы могли бы сделать:хотя современная передовая практика - использовать
id
вместо имени и использоватьaddEventListener()
вместо использования,onclick
поскольку это позволяет вам привязать несколько функций к одному событию.источник
addEventListener()
и почему.Причин несколько:
Я считаю, что это помогает разделить разметку, то есть HTML и клиентские скрипты. Например, jQuery позволяет легко добавлять обработчики событий программно.
Приведенный вами пример не работает в любом пользовательском агенте, который не поддерживает javascript или у которого отключен javascript. Концепция прогрессивного улучшения будет поощрять простую гиперссылку
/map/
для пользовательских агентов без javascript, а затем добавление обработчика кликов для пользовательских агентов, поддерживающих javascript.Например:
Разметка:
Javascript:
источник
<a href="https://stackoverflow.com/map/" onclick="popup('/map/', 300, 300, 'map'); return false;">link</a>
пересмотр
Ненавязчивый подход JavaScript был хорош в прошлом - особенно привязка обработчика событий в HTML считалась плохой практикой (в основном потому,
onclick events run in the global scope and may cause unexpected error
что то, что было упомянуто YiddishNinja )Тем не мение...
В настоящее время кажется, что этот подход немного устарел и нуждается в некотором обновлении. Если кто-то хочет быть профессиональным разработчиком внешнего интерфейса и писать большие и сложные приложения, ему необходимо использовать такие фреймворки, как Angular, Vue.js и т. Д. Однако эти фреймворки обычно используют (или позволяют использовать) HTML-шаблоны, к которым привязаны обработчики событий. непосредственно в коде html-шаблона, и это очень удобно, понятно и эффективно - например, в шаблоне angular обычно пишут:
В raw js / html эквивалент этого будет
Разница в том, что в raw js
onclick
событии запускается в глобальной области, но фреймворки обеспечивают инкапсуляцию.Так в чем же проблема?
Проблема в том, что начинающий программист, который всегда слышал, что html-onclick - это плохо и который всегда использует,
btn.addEventListener("onclick", ... )
хочет использовать какой-то фреймворк с шаблонами (addEventListener
также есть недостатки - если мы обновляем DOM динамически с использованиемinnerHTML=
(что довольно быстро ) - тогда мы теряем события обработчики связываются таким образом). Тогда он столкнется с чем-то вроде дурных привычек или неправильного подхода к использованию фреймворка - и он будет использовать фреймворк очень плохо - потому что он сосредоточится в основном на js-части, а не на части-шаблоне (и будет производить нечеткие и трудные для поддержки код). Чтобы изменить эту привычку, он потеряет много времени (и, вероятно, ему понадобится удача и учитель).Так что, на мой взгляд, исходя из опыта моих студентов, для них было бы лучше, если бы они использовали html-handlers-bind вначале. Как я уже сказал, обработчики вызываются в глобальном масштабе, но на этом этапе студенты обычно создают небольшие приложения, которыми легко управлять. Для написания приложений большего размера они выбирают несколько фреймворков.
Так что делать?
Мы можем ОБНОВИТЬ подход ненавязчивого JavaScript и разрешить привязку обработчиков событий (в конечном итоге с простыми параметрами) в html (но только обработчик привязки - не помещать логику в onclick, как в OP quesiton). Так что, на мой взгляд, в raw js / html это должно быть разрешено
или
Показать фрагмент кода
Но приведенные ниже примеры НЕ должны допускаться
Реальность меняется, наша точка зрения тоже должна
источник
addEventListener
. Объявление 2. Да, их можно перезаписать (но обычно этого никто не делает) - в чем проблема? Объявление 3. Обработчик не будет уволен после удаления атрибута onclick - доказательство здесьЭто
новаяпарадигма под названием « Ненавязчивый JavaScript ». Текущий «веб-стандарт» говорит о разделении функциональности и представления.Это не совсем «плохая практика», просто большинство новых стандартов требуют, чтобы вы использовали прослушиватели событий вместо встроенного JavaScript.
Кроме того, это может быть просто личным делом, но я думаю, что это намного легче читать, когда вы используете прослушиватели событий, особенно если у вас есть более одного оператора JavaScript, который вы хотите запустить.
источник
Думаю, ваш вопрос вызовет обсуждение. Общая идея состоит в том, что хорошо разделять поведение и структуру. Кроме того, afaik, встроенный обработчик кликов должен
eval
«стать» настоящей функцией javascript. И это довольно старомодно, хотя это довольно шаткий аргумент. А, ну, почитайте об этом @ quirksmode.orgисточник
производительность и эффективность.
источник
Еще две причины не использовать встроенные обработчики:
Они могут потребовать утомительных проблем с выходом цитаты
Учитывая произвольную строку, если вы хотите иметь возможность создать встроенный обработчик, который вызывает функцию с этой строкой, для общего решения вам придется избегать разделителей атрибутов (со связанным объектом HTML), и вы должны избегать разделителя, используемого для строки внутри атрибута, как показано ниже:
Это невероятно уродливо. В приведенном выше примере, если вы не заменили
'
s, это приведет к ошибке SyntaxError, посколькуalert('foo'"bar')
это недопустимый синтаксис. Если вы не заменили"
s, браузер интерпретировал бы это как конецonclick
атрибута (разделенного"
s выше), что также было бы неверным.Если кто-то обычно использует встроенные обработчики, нужно обязательно помнить, что нужно делать что-то подобное вышеизложенному (и делать это правильно ) каждый раз , что утомительно и трудно понять с первого взгляда. Лучше полностью избегать встроенных обработчиков, чтобы произвольную строку можно было использовать в простом закрытии:
Разве это не намного лучше?
Цепочка областей видимости встроенного обработчика чрезвычайно своеобразна.
Как вы думаете, что будет записывать следующий код?
Попробуйте, запустите сниппет. Вероятно, это не то, чего вы ожидали. Почему он производит то, что делает? Потому что встроенные обработчики работают внутри
with
блоков. Приведенный выше код находится внутри трехwith
блоков: один дляdocument
, один для<form>
и один для<button>
:Показать фрагмент кода
Поскольку
disabled
это свойство кнопки, ссылкаdisabled
внутри встроенного обработчика относится к свойству кнопки, а не к внешнейdisabled
переменной. Это довольно нелогично.with
имеет много проблем: он может быть источником сбивающих с толку ошибок и значительно замедляет код. Это вообще не разрешено даже в строгом режиме. Но со встроенными обработчиками вы вынуждены запускать код черезwith
s - и не только через одинwith
, а через несколько вложенныхwith
s. Это безумие.with
никогда не следует использовать в коде. Поскольку встроенные обработчики неявно требуютwith
наряду со всем его запутанным поведением, встроенных обработчиков также следует избегать.источник