Оригинальный текст на английском языке: Семь правил ненавязчивого JavaScript.
Исходный адрес: http://icant.co.uk/articles/seven-rules-of-unobtrusive-javascript/
Автор оригинала: Крис Хейлманн
Адрес перевода: http://www.zhuoqun.net/html/y2008/1103.html
Написано впереди: Когда Кеджун некоторое время назад обучал нас JavaScript, он рекомендовал на слайдах множество классических статей, включая эту статью One. Я чувствую себя очень хорошо после прочтения, но часто не до конца понимаю статьи. Так уж получилось, что я не нашел китайской версии этой статьи, поэтому мне пришла в голову идея перевести ее, поэтому. что я могу поделиться этим и углубить свое понимание. Автор этой статьи Крис Хейлманн — британский инженер Yahoo! (фигура «крестного отца», по словам Кеджуна), и перевод этой статьи также был одобрен им.
И еще вот что, я много чего переводил и раньше, но тогда я переводил больше ради перевода, и многих технических статей я не понимал, поэтому до сих пор являюсь переводчиком. Я продолжу переводить некоторые статьи в будущем, но мне следует переводить только классические статьи, которые необходимо внимательно понимать. Если у вас есть время, вам все равно следует писать больше кода. Практика — это то, что вам нужно.
Перевод терминологии: Что касается термина «Ненавязчивый JavaScript», я не могу придумать особенно подходящего перевода. После поиска в Интернете я обнаружил, что некоторые из них были переведены как «сдержанный JavaScript», некоторые — как «ненавязчивый JavaScript», а некоторые на Тайване были переведены как «ненавязчивый JavaScript»… После многих исследований, Я решил использовать «не навязчивый JavaScript». Этот перевод — «навязчивый JavaScript» (хотя меня это все равно не совсем устраивает), подробности смотрите в этой статье. На самом деле, «Ненавязчивый JavaScript» содержит множество значений, и его сложно суммировать одним словом. Если вам интересно, вы можете взглянуть на объяснение «Ненавязчивого JavaScript» в Википедии. Кроме того, я считаю, что перевод должен выражать авторский смысл, и его не обязательно переводить дословно. Поэтому, чтобы облегчить понимание читателями, я кое-что удалил, а кое-что добавил в статье, но это так. без ущерба для смысла исходного текста, выполненного на основе.
Следует отметить еще один момент: мои навыки перевода очень любительские, поэтому в переводе обязательно будут ошибки, поэтому, пожалуйста, поправьте меня.
После многих лет разработки, обучения и написания ненавязчивого JavaScript я обнаружил следующие рекомендации. Я надеюсь, что они помогут вам немного понять, почему лучше проектировать и выполнять JavaScript именно таким образом. Эти правила помогли мне доставлять продукцию быстрее, качественнее и проще в обслуживании.
1. Не делайте никаких предположений (JavaScript — ненадежный помощник).
Возможно, самая важная характеристика ненавязчивого JavaScript — это то, что вам нужно перестать делать какие-либо предположения:
не предполагайте, что JavaScript доступен, лучше подумайте, что это возможно недоступен, вместо того, чтобы полагаться на него напрямую.
Не предполагайте, что браузер поддерживает методы и свойства, пока вы не протестируете их и не подтвердите, что они работают.
Не думайте, что HTML-код настолько правильный, насколько вы думаете, проверяйте его каждый раз и ничего не делайте, если он недоступен.
Сделайте функцию JavaScript независимой от устройств ввода. Помните, что другие сценарии могут повлиять на функциональность вашего JavaScript, поэтому убедитесь, что область действия ваших сценариев максимально безопасна.
Прежде чем приступить к разработке сценария, первое, о чем следует подумать, — это проверить HTML-код, для которого вы собираетесь создать сценарий, и посмотреть, есть ли что-нибудь, что может помочь вам в достижении вашей цели.
2. Найдите перехватчики и связи между узлами (HTML — краеугольный камень сценариев).
Прежде чем приступить к написанию сценариев, взгляните на HTML, для которого вы хотите написать JavaScript. Если HTML неорганизован или неизвестен, практически невозможно найти хорошее решение для сценариев — вполне вероятно, что вы либо создадите слишком много разметки в JavaScript, либо приложение будет слишком зависеть от JavaScript.
В HTML есть некоторые вещи, которые следует учитывать, а именно перехваты и отношения узлов.
<1>.HTML-перехват
Исходным и самым важным перехватчиком HTML является идентификатор, и доступ к идентификатору можно получить с помощью самого быстрого метода DOM — getElementById. Если все идентификаторы в допустимом HTML-документе уникальны (в IE есть ошибка, связанная с именем и идентификатором, но некоторые хорошие библиотеки решают эту проблему), использование идентификаторов безопасно, надежно и легко тестируется.
Некоторые другие перехватчики представляют собой элементы HTML и классы CSS. Доступ к элементам HTML можно получить через метод getElementsByTagName, но к классам CSS нельзя получить доступ через собственные методы DOM в большинстве браузеров. Однако существует множество внешних библиотек классов, предоставляющих методы, которые могут получать доступ к именам классов CSS (аналогично getElementsByClassName).
<2>.Связь узлов .HTML
Еще один интересный момент в HTML — это связь между тегами. Подумайте над следующим вопросом:
как мы можем достичь целевого узла наиболее легко и с наименьшим количеством обходов DOM?
Изменив какую метку, мы сможем получить доступ к как можно большему количеству дочерних узлов, которые необходимо изменить?
Какие атрибуты или информацию имеет данный элемент, которые можно использовать для достижения другого элемента?
Обход DOM — ресурсоемкий и медленный процесс, поэтому вам следует попытаться использовать для этого методы, уже используемые в браузерах.
3. Оставьте обход экспертам (CSS, быстрее перемещайтесь по DOM).
Написание сценариев DOM и использование методов или свойств (getElementsByTagName, nextSibling, previousSibling, ParentNode и других) для обхода DOM, похоже, сбивает с толку многих людей. . интересный. Интересно то, что мы уже сделали это с помощью другой технологии — CSS.
CSS — это метод, использующий селекторы CSS для доступа к целевым элементам и изменения их визуальных свойств путем перемещения по DOM. Сложный фрагмент JavaScript, использующий DOM, можно заменить селектором CSS:
var n = document.getElementById('nav');
если (п) {
var as = n.getElementsByTagName('a');
если (as.length > 0) {
for(var i=0;as[i];i++){
as[i].style.color = '#369';
as[i].style.textDecoration = 'none';
}
}
}
/* Следующий код имеет ту же функцию, что и приведенный выше*/
#nav a{
цвет: #369;
текстовое оформление: нет;
}
Это очень мощная техника, которую можно найти с пользой. Этого можно добиться путем динамического добавления классов к элементам высокого уровня в DOM или изменения идентификатора элемента. Если вы используете DOM для добавления класса CSS в тело документа, дизайнеры могут легко определять статические и динамические версии документа.
JavaScript:
вар DynamicClass = 'js';
вар б = document.body;
b.className = b.className ? b.className + 'js': 'js';
CSS:
/* Статическая версия*/
#nav {
....
}
/* Динамическая версия*/
body.js #nav {
....
}
4. Понимайте браузеры и пользователей (и создавайте то, что вам нужно, на основе существующих шаблонов использования).
Большая часть ненавязчивого JavaScript — это понимание того, как работают браузеры (особенно, как браузеры выходят из строя) и чего ожидают пользователи. Независимо от браузера вы можете легко создать совершенно другой интерфейс с помощью JavaScript. Интерфейсы перетаскивания, области сгиба, полосы прокрутки и ползунки — все это можно создать с помощью JavaScript, но эта проблема не является простой технической проблемой. Вам нужно подумать над следующими вопросами:
Может ли этот новый интерфейс быть независимым от устройств ввода? Если нет, то на что можно положиться?
Соответствует ли новый интерфейс, который я создаю, рекомендациям браузера или другого богатого интерфейса (можете ли вы переключаться между многоуровневыми меню непосредственно с помощью мыши? Или вам нужно использовать клавишу табуляции?)
Какую функциональность мне нужно предоставить, основанную на JavaScript?
Последний вопрос на самом деле не является проблемой, поскольку при необходимости вы можете использовать DOM для создания HTML из воздуха. Примером этого является ссылка «Печать». Поскольку браузеры не предоставляют функций, не связанных с JavaScript, для печати документа, вам необходимо использовать DOM для создания таких ссылок. То же самое относится и к кликабельной строке заголовка, в которой реализованы модули развертывания и свертывания содержимого. Строку заголовка нельзя активировать с помощью клавиатуры, но ссылки можно. Таким образом, чтобы создать кликабельную строку заголовка, вам необходимо добавить ссылку с помощью JavaScript, и тогда все пользователи с клавиатурой смогут свернуть и развернуть модуль контента.
Отличным ресурсом для решения проблем такого типа является Библиотека шаблонов проектирования. Что касается знания того, какие вещи в браузере не зависят от устройств ввода, это зависит от накопленного опыта. Первое, что вам нужно понять, это механизм обработки событий.
5. Понимание событий (обработка событий приводит к изменениям)
Обработка событий — это второй шаг к ненавязчивому JavaScript. Дело не в том, чтобы сделать все перетаскиваемым, кликабельным или добавить к ним встроенную обработку, а в том, чтобы понять, что обработку событий можно полностью разделить. Мы разделили HTML, CSS и JavaScript, но не очень далеко продвинулись в разделении обработки событий.
Обработчик событий будет отслеживать изменения, происходящие с элементами в документе. Если событие произойдет, обработчик найдет замечательный объект (обычно параметр с именем e). Этот объект сообщит элементу, что произошло и что с ним можно сделать. .
Что действительно интересно в обработке большинства событий, так это то, что она происходит не только с элементом, к которому вы хотите получить доступ, но и со всеми элементами выше в DOM (но не все события такие, как фокус и Исключением является событие размытия). . Например, вы можете использовать эту функцию, чтобы добавить в список навигации только один обработчик событий и использовать метод обработчика событий, чтобы получить элемент, который фактически инициировал событие. Этот метод называется делегированием событий, и он имеет несколько преимуществ:
вам нужно только проверить, существует ли элемент, а не проверять каждый элемент. Вы можете динамически добавлять или удалять дочерние узлы, не удаляя соответствующий обработчик событий. Вы можете еще одну вещь запомнить. при ответе на одно и то же событие в разных элементах вы можете остановить распространение события на родительский элемент и переопределить поведение элементов HTML по умолчанию (например, ссылок). Однако иногда это не очень хорошая идея, поскольку браузеры не без причины придают HTML-элементам такое поведение, которое они имеют. Например, ссылки могут указывать на цель внутри страницы, и оставление их неизмененными гарантирует, что пользователь также сможет добавить в закладки текущее состояние сценария страницы.
6. Подумайте о других (пространствах имен, областях видимости и схемах).
Ваш код почти никогда не будет единственным кодом сценария в документе. Поэтому особенно важно убедиться, что в вашем коде нет глобальных функций или глобальных переменных, которые другие скрипты могут переопределить. Существует несколько шаблонов, позволяющих избежать этой проблемы, самый простой из которых — использовать ключевое слово var для инициализации всех переменных. Предположим, мы напишем следующий скрипт:
var nav = document.getElementById('nav');
функция инициализации(){
// делаем что-то
}
функция шоу(){
// делаем что-то
}
сброс функции(){
// делаем что-то
}
Приведенный выше код содержит глобальную переменную с именем nav и три функции с именами init, show и reset. Эти функции могут обращаться к переменной nav и друг к другу через имя функции:
var nav = document.getElementById('nav');
функция инициализации(){
показывать();
if(nav.className === 'показать'){
перезагрузить();
}
// делаем что-то
}
функция шоу(){
вар c = nav.className;
// делаем что-то
}
сброс функции(){
// делаем что-то
}
Вы можете избежать вышеуказанного глобального кодирования, инкапсулировав код в объект, чтобы функции можно было превратить в методы объекта, а глобальные переменные можно было превратить в свойства объекта. Вам необходимо использовать метод «имя + двоеточие» для определения методов и свойств, а также добавлять запятую в качестве разделителя после каждого свойства или метода.
вар myScript = {
nav:document.getElementById('nav'),
инициализация: функция () {
// делаем что-то
},
показать: функция() {
// делаем что-то
},
сброс: функция() {
// делаем что-то
}
}
Доступ ко всем методам и свойствам можно получить как снаружи, так и внутри, используя «имя класса + оператор точки».
вар myScript = {
nav:document.getElementById('nav'),
инициализация: функция () {
мойСкрипт.шоу();
if(myScript.nav.className === 'показать'){
мойScript.reset();
}
// делаем что-то
},
показать: функция() {
вар c = myScript.nav.className;
// делаем что-то
},
сброс: функция() {
// делаем что-то
}
}
Недостатком этой модели является то, что каждый раз, когда вы получаете доступ к другим методам или свойствам из метода, вы должны добавлять имя объекта впереди, и ко всему, что находится в объекте, можно получить доступ извне. Если вы просто хотите, чтобы какой-то код был доступен другим сценариям в документе, рассмотрите следующий шаблон модуля:
вар myScript = функция(){
//Это частные методы и свойства
var nav = document.getElementById('nav');
функция инициализации(){
// делаем что-то
}
функция шоу(){
// делаем что-то
}
сброс функции(){
// делаем что-то
}
//Публичные методы и свойства заключаются в оператор возврата с использованием синтаксиса объекта
возвращаться {
общественный: функция () {
},
фу:'бар'
}
}();
Вы можете получить доступ к возвращенным общедоступным свойствам и методам так же, как и в предыдущем коде, в данном случае: myScript.public() и myScript.foo. Но здесь есть еще один неудобный момент: когда вы хотите получить доступ к публичному методу снаружи или к приватному методу внутри, вам все равно придется писать длинное имя (имя объекта может быть очень длинным). Чтобы избежать этого, вам нужно определить их как частные и возвращать псевдоним только в операторе return:
вар myScript = функция() {
// Это частные методы и свойства
var nav = document.getElementById('nav');
функция инициализации(){
// делаем что-то
}
функция шоу(){
// делаем что-то
// делаем что-то
}
сброс функции(){
// делаем что-то
}
вар foo = 'бар';
function public(){
}
//Возвращаем только указатели на те частные методы и свойства, к которым вы хотите получить доступ
возвращаться {
публичный: публичный,
фу: фу
}
}();
Это обеспечивает единообразный стиль кода и позволяет использовать более короткие псевдонимы для доступа к методам или свойствам.
Если вы не хотите раскрывать какие-либо методы или свойства внешнему миру, вы можете инкапсулировать весь код в анонимный метод и выполнить его сразу после его определения:
(function(){
// это все частные методы и свойства
var nav = document.getElementById('nav');
функция инициализации(){
// делаем что-то
show(); // Здесь не требуется префикс имени класса.
}
функция шоу(){
// делаем что-то
}
сброс функции(){
// делаем что-то
}
})();
Этот шаблон отлично подходит для модулей кода, которые выполняются только один раз и не зависят от других функций.
Следуя приведенным выше правилам, ваш код будет лучше работать для пользователей, а также ваш код будет лучше работать на машинах и лучше сочетаться с кодом других разработчиков. Однако есть одна группа, которую необходимо принять во внимание.
7. Подумайте о разработчиках, которые возьмут на себя ваш код (облегчает обслуживание).
Последний шаг в том, чтобы сделать ваш скрипт по-настоящему ненавязчивым, — это перепроверить его после того, как вы его написали, и позаботиться о разработчиках, которые возьмут на себя управление вашим кодом после его написания. сценарий выходит в эфир. Рассмотрите следующие вопросы:
Все ли имена переменных и функций разумны и понятны?
Правильно ли организован код? Протекает ли все гладко от начала до конца?
Все ли зависимости очевидны?
Были ли добавлены комментарии, где это возможно, которые могут вызвать путаницу?
Самое важное, на что следует обратить внимание: осознайте, что код HTML и CSS в документе будет изменен с большей вероятностью, чем код JavaScript (потому что они отвечают за визуальный эффект). Поэтому не включайте в код сценария классы и идентификаторы, которые могут быть видны конечным пользователям, а выделите их в объект, содержащий информацию о конфигурации.
мойскрипт = функция(){
вар конфиг = {
Идентификатор навигации: 'nav',
видимыйКласс:'показать'
};
вар nav = document.getElementById(config.navigationID);
функция инициализации(){
показывать();
if(nav.className === config.visibleClass){
перезагрузить();
};
// делаем что-то
};
функция шоу(){
вар c = nav.className;
// делаем что-то
};
сброс функции(){
// делаем что-то
};
}();
Таким образом, сопровождающий знает, где изменить эти свойства, не меняя при этом другой код.
Дополнительная информация
Вот семь рекомендаций, которые я обнаружил. Если вы хотите узнать больше о темах, обсуждавшихся выше, перейдите по следующим ссылкам: