Прогрессивное улучшение в JavaScript

Прогрессивное улучшение в JavaScript

Всем привет из армии, а точнее с военных сборов ;-)

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

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

Ликбез

Итак, думаю вы помните, что суть прогрессивного улучшения состоит в слудующем:

  • доступность и семантичность верстки;
  • внешние стили и скрипты;
  • верстка, стили и скрипты выступают отдельными «слоями», которые накладываются один на другой, а не смешываются как коктейль.

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

«Слойность» позволяет, опять же, проще и правильнее работать с ними: например, переход с одного фреймворка на другой (или с одного дизайна на другой) делается заменой файлов, а не копанием во всех шаблонах с целью найти инлайновый стиль или привязанное событие. Кроме того, при командной разработке верстальщик и фронт-энд девелопер не будут мешать друг другу и их работа будет быстрее и проще.

Подключение скриптов

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

Вот плохой пример подключения и выполнения клиентских скриптов:

...
<link rel="stylesheet" href="typo.css"/>
<script type="text/javascript" src="huge-file.js"></script>
</head>
<body onload="runMyScripts();">
...

А вот хороший:

...
<script type="text/javascript" src="huge-file.js"></script>
<script type="text/javascript" src="init.js"></script>
</body>
</html>

Файл init.js запусткает необходимые скрипты и может выглядеть как-то так (обычно запускаемых функций намного больше):

$(document).ready(function() {
runMyScripts();
});

Привязка функций

Часто разработчики делают вот такие вещи. Им кажется, что прописать событие или функцию непосредственно в HTML-коде страницы быстрее и правильнее, но это не так. Этим они только усложняют жизнь себе, другим разработчикам, пользователям и браузеру, создавая лишний код. Кроме того, если у вас всего одна привязка событий, то это еще не так смертельно, но если нужно сделать 30 одинаковых привязок, то от копипэйста могут заболеть пальцы.

Итак, плохой пример:

<a href="#" onclick="runMyFunc(this);" class="onclickLinks">ссылка №1</a>;
<a href="#" onclick="runMyFunc(this);" class="onclickLinks">ссылка №2</a>;
...
<a href="#" onclick="runMyFunc(this);" class="onclickLinks">ссылка №N</a>;

А вот это уже хороший:

$('a.onclickLinks').each(function() {
this.click(function(e) {
runMyFunc($(e.target));
});
});

Количество кода не меняется от количества таких ссылок, плюс они в принципе не завязаны друг на друга, так что процесс редактирвания занимает намного меньше времени.

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

Работа со стилями

Представим себе, что необходимо у какого-то блока поменять шрифт на жирный, цвет на красный и сделать прерывистую обводку в 3 пиксела толщиной. Все это нужно сделать при каком-то там клике на чем-то. Первое решение, которое приходит на ум, это прописать все это добро через стили прямо из JavaScript. И многие делают именно так (это плохо):

<script type="text/javascript">
...
$('#someDiv').css({
'font-weight': 'bold',
'color': '#990000',
'border': '#000 3px dotted'
});
...
</script>

Это кошмар. Во-первых, это неудобно, так как если вы захотите (или скажет дизайнер) сменить цвет (то есть часть стиля), то менять его вы будете внутри JavaScript (программная часть) — не логично, не так ли? Так что лучше завести для этого отдельный класс — при смене визуалки логика не будет затронута, только стили. Делать лучше вот так:

<style>
.someClass {
font-weight: bold;
color: #990000;
border: #000 3px dotted;
}
</style>

...

<script type="text/javascript">
...
$('#someDiv').addClass('someClass');
...
</script>

Вывод: разделяем стили и клиентскую логику, не мешаем JavaScript и CSS.

 

Итак, думаю, что этой статьей я смог убедить вас в том, что следования принципам прогрессивного улучшения помогают писать более правильный, удобный и красивый код. Если есть, что добавить, то комментарии к вашим услугам.

Расскажите друзьям

Оцените статью:
  • 1
  • 2
  • 3
  • 4
  • 5

Комментарии — 15

андрей
согласен с автором на все 100.
Особенно ценно последнее замечание по изменению стилевых свойств элемента непосредственно в js коде. Это ведёт к не меньшей неразберихе и негибкости, чем интеграция js в html-код.
#
андрей
Сашко
Согласен тоже. Стал умнее :)
#
Сашко
sanchosrancho
При разработке сайта (страницы) от начала до конца можно использовать следующий подход:
1. Сначала создать структуру документа (xhtml)
2. Затем описать представление с помощью стилей (css + images)
3. В конце добавить интерактивность (javascript)

На каждом этапе, нужно вносить минимум изменений в уже реализованные слои. При этом, на каждом шаге сайт (страница) должен полностью работать.
Bonch
Довольно тривиальные советы.
Думаю, вам стоило бы рассказать про разделение логики в javascript на внешний вид и поведение подробнее.
Например, знаете ли вы, почему в xhtml strict запретили аттрибут target? Все потому, что ребята хотят отделить поведение (javascript) от внешнего вида (css) и описания (xhtml) документа.

Вот про это я бы почитал - может бы что-то новое для себя открыл :)
А так просто лень самому писать у себя. Трудно выдавить из себя текст :)
Alex
>Им кажется, что прописать событие или функцию непосредственно в HTML-коде страницы >быстрее и правильнее, но это не так.

Тут вы не совсем правы. Дело в том, что на выборку селекторов тоже будет тратиться время, а иногда и очень много времени. Например, на странице 500 комментариев и надо привязать к каждому комменту (какому-то его блоку) несколько событий. В таком случае - выборка всех сенлекторов может занять много времени, поэтому возникает как бы эффект подвисания браузера. (Особенно это ярко выражено в случае FF и IE)
#
Alex
r-ip
ХМ

$('a.onclickLinks').each(function() {
    this.click(function(e) {
        runMyFunc($(e.target));
    });
});


а не проще ли так?


$('a.onclickLinks').click(function() {
   runMyFunc($(this));
});
N13
В целом - присоединяюсь к автору. Вот только интересно (по поводу последнего примера): хорошо, когда событие влияет на мгновенное переключение класса (клик - и блок мгновенно должен стать оранжевым). А если требуется плавное (анимированное) изменение свойства? Простые примеры:
- уведомление о совершенном действии (обычно AJAX): появляется с ярким фоном (дабы обратить внимание), а затем затухает в обычный фон
- удаление элемента (либо затухание в нулевую прозрачность, либо свертывание по высоте)
Лично я для реализации таких вещей не знаю способов, отличных от воздействия на конкретные css-свойства блоков. Если кто-то подскажет, буду признателен (Методы animate, toggle, fadeIn и fadeOut не предлагать, потому что это по сути те же манипуляции с конкретными css-свойствами).
#
N13
Grin
N13, в том же мутулзе есть Морф, который позволяет делать плавный переход от одного класса к другому.
C0vax
Интересно. Многое из написанного уже знакомо, но иногда на практике забываю применить. А вот по поводу того что js файлы в конце нужно подключать - это для меня открытие :)
Вобщем спасибо, хороший пост.
Тарас
А кнопочка класная получилась!
B@rmaley.e>
[quote]$('a.onclickLinks').click(function() {
runMyFunc($(this));
});[/quote]
Тогда вообще так:
$('a.onclickLinks').click(runMyFunc); И в runMyFunc использовать указатель this.
Кстати, в статье неправильно - при использовании each ссылка this ведет на DOM-объект, а не его jQuery версию.
#
B@rmaley.e>
dizelbox
Статья понятная, но я вот не очень пойму, как сделать, чтобы к примеру новый записы, подгружаемые, меняли свой фон.
Иван
Что-то никто ничего не говорит про первый пункт, а я скажу. Не согласен с мнением что в самом конце страницы грузить будет всегда правильно. На самом деле все зависит от содержания подключаемого скрипта.

- если там идут одни определения функций, то нужно загрузить их до использования, соответсвенно, чем раньше - тем лучше. А head у нас - самый первый.

- если там непосредственно в теле идет что-то типа document.write(...), то скорее всего это генерируется текст для вывода - значит, вероятнее всего, помещать нужно в body.
#
Иван
Maxin
как-то я не очень согласна по поводу того, что скрипты вешать в конце кода. не получится ли так, что события onClick будут выполняться с задержкой? + часть функций вообще может начать выполняться не правильно, да и на внешний вид может повлиять, особенно, если скриптом какие-нибудь рюшечки налеплены (
#
Maxin

Новый комментарий

как выглядит какой тег
жирный текст <b>жирный текст</b>
курсивный тект <i>курсивный тект</i>
зачеркнутый текст <s>зачеркнутый текст</s>
подчеркнутый текст <u>подчеркнутый текст</u>
ссылка <a href="адрес">ссылка</a>
function foo() { ... }
<pre><code>function foo() { ... } </code></pre>
разрешенные теги или посмотреть как будет выглядеть
как выглядит какой тег
жирный текст <b>жирный текст</b>
курсивный тект <i>курсивный тект</i>
зачеркнутый текст <s>зачеркнутый текст</s>
подчеркнутый текст <u>подчеркнутый текст</u>
ссылка <a href="адрес">ссылка</a>
function foo() { ... }
<pre><code>function foo() { ... } </code></pre>
разрешенные теги или посмотреть как будет выглядеть
counter strike mt2 silkroad pvp metin2 metin2 pvp knight pvp gm olarak başlayan pvpler pvp silkroad pvp serverler counter strike serverler msn show cam show görüntülü sohbet oyunlar suskunlar gazete oku