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


HTML

В чем дело, DOCTYPE?

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

В идеале используйте DOCTYPE HTML5. Все современные браузеры поддерживают его, и даже браузеры, не поддерживающие HTML5, такие как IE6 и IE7, переключатся в режим стандартов благодаря ему. См.Источник。

<!DOCTYPE html>

Пишите валидную и семантически понятную разметку

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

Все заголовки должны начинаться с<h2>и создаваться иерархически. Текстовые абзацы всегда должны размещаться в<p>тегах, и так далее. Если вы пишете HTML с четкой семантикой, получающиеся страницы будут чище, более краткими и легче разбираемыми для поисковых роботов. Это самое простое исправление SEO, которое вы можете сделать.

Посмотрите на следующие абзацы. Какой, по вашему мнению, чище? Этот?

<span class="sectionHeading">A Heading</span>
<br /> <br />
Lorem ipsum dolor sit amet. ...
<br /> <br />

Или этот?

<h2>A Heading</h2>
<p>
    Lorem ipsum dolor sit amet. ...
</p>

Обработка кликов средней кнопкой мыши

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

Популярный современный сайт, который прекрасно иллюстрирует эту проблему, — Twitter. Во всем его приложении клик средней кнопкой мыши по имени пользователя или аватару дает совершенно разные результаты.

<!-- 旧的方式,破坏网页语义 -->
<a href="../index.html"></a>

<!-- 如果鼠标点击不能产生一个页面,那就不是超链接 -->
<span class="link" role="link"></span>

Другая альтернатива — использовать#guided paths, которые сопоставляют обычные URL с#guided links, а затем получают фрагменты страницы через AJAX. Библиотеки, предоставляющие эту функциональность, должны иметь возможность отображать страницу обычно при нажатии средней кнопкой мыши или загружать содержимое страницы в выделенную область при нажатии левой кнопкой. Однако будьте осторожны; многие считают, что#-ссылки ломают веб-приложения。

Используйте микроформаты для представления контактной информации

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

<span class="tel">
    <span class="type">home</span>:
    <span class="value">+1.415.555.1212</span>
</span>

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

Для получения дополнительной информации о микроформатах см.http://microformats.org/wiki/hcard

Изображениям нужен текст 'Alt'

<img>Тегу нуженaltтекст, чтобы проверять и соблюдать требования к удобочитаемости. В атрибутеaltтекст должен описывать, что отображает изображение или какого эффекта предполагается достичь, если только изображение не является неважным.

Если изображение — всего лишь маркер списка или какой-либо другой незначительный значок, лучше задатьaltпустую строку для атрибута, но всё равно оставить его. Так программы чтения с экрана проигнорируют его, а не будут читать «маркер» 20 раз подряд.

<img src="dog.gif.html" alt="Fido and I at the park!" />
<!-- 很好,描述清晰 -->

<img src="bullet.gif.html" alt="bullet" />
<!-- 不好,显得多余 -->

<img src="bullet.gif.html" alt="" />
<!-- 好 -->

Используйте теги table только для табличных данных

Тег table следует использовать только для отображения табличных данных. Единственное исключение — написание писем в формате HTML, где table может быть единственным методом вёрстки, поддерживаемым некоторыми проблемными почтовыми клиентами.

Для удобочитаемости заголовки таблиц всегда должны использовать<th>элементы. Также не забудьте задатьcellpadding, cellspacingиborderзначение ... до0, потому что эти стили легче поддерживать согласованными, когда они управляются через CSS.

<table cellpadding="0" cellspacing="0" border="0">
    <thead>
        <tr>
            <th>
                Cell Header
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                Cell Item
            </td>
        </tr>
    </tbody>
</table>

Используйте jQuery и виджеты jQuery UI

jQuery и jQuery UI созданы так, чтобы вести себя почти одинаково с точки зрения внешнего вида и функциональности в разных браузерах. jQuery UI разработан в соответствии с WAI WCAG 2.0 и WAI ARIA, поэтому использование этого фреймворка позволяет избежать всех неопределённостей, связанных с плагинами или скриптами, работающими на вашем сайте.


JavaScript

Отступы и форматирование кода

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

Согласованное форматирование кода делает код более читаемым, а также означает, что его легко изменять с помощью команд поиска/замены. К счастью, наши привычки программирования очень близки к официально рекомендованному стилю jQuery. Есть небольшие различия, но это личные предпочтения или вещи, которые, по нашему мнению, невозможно поддерживать. См.Руководство по стилю ядра jQuery

Пробелы между символами

// 不好
if(blah==="foo"){
    foo("bar");
}

// 好 :)
if (blah === "foo") {
    foo("bar");
}

Не переносите фигурные скобки на новую строку

// 不好
if (foo)
{
    bar();
}

// 好 :)
if (foo) {
    bar();
}

Всегда используйте фигурные скобки

// 不好
if (foo)
    bar();

// 好 :)
if (foo) {
    bar();
}

Обработка строк

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

Комментарии

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

if (user.hasPermission) {
    editPage();
}

По крайней мере в этом сценарии комментарии совершенно не нужны.

Случаи, когда комментарии важны

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

// 校验美国电话号码的正则表达式,号码格式是 (XXX) XXX-XXXX (减号、空格和括号都是可选的,可以有也可以没有)
var phoneRegEx = /^\(?(\d{3})\)?[- ]?(\d{3})[- ]?(\d{4})$/;

Всегда используйте оператор сравнения ===

Использование оператора сравнения == может заставить раздражающие ошибки бесследно исчезнуть. Это позволяет ... вJavaScript GardenСлабая типизация ясно объясняется в. Использование строгого оператора сравнения === не выполняет приведение типов, что позволяет строго оценивать различия между двумя объектами. Опять же, для более подробной информации см.JavaScript Garden。

var zeroAsAString = "0";

if (zeroAsAString == 0) {
    // 这样也能判断为true,呵呵...
}

if (zeroAsAString === 0) {
    // 判断为false
}

Исключение

При сравнении с null оператор == допустим, потому что он проверяет и null, и undefined. Если вы не полностью понимаете этот принцип, я всё же рекомендую использовать вместо него ===.

var foo = null;

// foo 是 null, 但 bar 是 undefined ,因为它尚未被声明
if (foo == null && bar == null) {
    // 上面的判断还是成立的
}

При использовании .parseInt() всегда указывайте второй параметр 'radix'

При преобразовании строки в целое число хорошая привычка — указывать второй параметр radix -- он определяет, в какую систему счисления преобразуется строка. Когда строка имеет префикс0в начале, по умолчанию это вызывает16основание в качестве radix.10Это основание. Спасибо João Moreno за документирование этойопечатки.。

alert( parseInt("08") ); // alerts: 2

alert( parseInt("08", 10) ); // alerts: 8

Избегайте сравнения с true и false

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

if (foo === true) {
    // 用了 === 倒是不错,可这是多余的
}

if (foo) {
    // 赞!
}

if (!bar) {
    // 反过来也赞
}

Избегайте загрязнения глобального пространства имён

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

Дуглас КрокфордЯ твёрдо уверен, что качество кода JavaScript-приложения можно измерить по количеству используемых в нём глобальных переменных; чем меньше, тем лучше. Поскольку не всё можно определить как локальное (хотя, честно говоря, то, что вы рассматриваете прямо сейчас, можно, так что не ленитесь), нужно найти способы организовать переменные так, чтобы избежать конфликтов и минимизировать разрастание пространства имён. Самый простой подход — использовать одну переменную или свести к минимуму количество модулей, использующих эти глобальные переменные. Крокфорд упоминал, что YUI использует только одну глобальную переменную — YAHOO. В своей публикации в блоге«Global Domination»он обсуждает более подробные вопросы.

Рассмотрим такую ситуацию: в небольших веб-приложениях глобальные переменные часто используются для хранения настроек уровня приложения. Можно определить объект, используя в качестве имени название вашего проекта или settings, что обычно лучше.

// 被污染的全局命名空间
var settingA = true;
var settingB = false;
var settingC = "test";

// 用 settings 作为对象命名
var settings = {
    settingA: true,
    settingB: false,
    settingC: "test"
}

Однако если мы можем снизить вероятность конфликтов, избегая глобальных переменных, но стандартизируем пространства имён к одному и тому же, не увеличит ли это вероятность конфликтов между приложениями? Что ж, это опасение действительно обоснованно. Поэтому рекомендуется использовать собственное конкретное имя приложения в качестве пространства имён глобальных переменных или применять тот же метод, что и в jQuery:$.noConflict()— шаблон для переназначения вашего пространства имён.

var myAppName = {
    settings: {
        settingA: true
    }
}

//访问全局变量
myAppName.settings.settingA; // true

Используйте camelCase для именования переменных

Именование переменных JavaScript в стиле CamelCase является стандартом в большинстве сред программирования. Читатель отметил в комментариях единственное исключение: используйте заглавные буквы и подчёркивания для обозначения констант.

var X_Position = obj.scrollLeft;

var xPosition = obj.scrollLeft; // 更好,更简洁

SCENE_GRAVITY = 1; // 常量

Производительность циклов — кэшируйте длину массива

Циклы — вероятно, самая важная часть оптимизации производительности JavaScript. Экономия одной-двух миллисекунд внутри цикла может в сумме дать несколько секунд. Один из приёмов здесь — кэшировать длину массива, чтобы внутри цикла не приходилось вычислять её на каждой итерации.

var toLoop = new Array(1000);

for (var i = 0; i < toLoop.length; i++) {
    // 败家玩意 - 长度会反复算 1000 次你知道不?
}

for (var i = 0, len = toLoop.length; i < len; i++) {
    // 会过日子 - 长度只计算一次,然后缓存了
}

Исключение

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

Производительность циклов — используйте 'break;' и 'continue;'

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

Если вы выполняете поиск внутри цикла, что вы делаете после успешного поиска? Например, в цикле из 1000 элементов вы находите нужное на середине. Неужели вы, несмотря ни на что, позволите циклу продолжить перебор оставшихся 500 элементов, даже зная, что последующие операторы if не будут иметь шанса совпасть? Нет! Вам абсолютно точно следует прервать цикл!

var bigArray = new Array(1000);

for (var i = 0, len = bigArray.length; i < len; i++) {
    if (i === 500) {
        break;
    }
    console.log(i); // 这样只会输出 0 - 499
}

Ещё одна проблема — пропуск конкретной итерации с последующим продолжением цикла. Хотя такими условиями, как чётность/нечётность, можно управлять с помощьюi++замены наi + 2в качестве способа управления. Некоторые условия всё ещё нужно специально обнаруживать, а затем вызывать операцию пропуска. Всё, что позволяет избежать выполнения полного процесса итерации, очень полезно.

var bigArray = new Array(1000);

for (var i = 0, len = bigArray.length; i < len; i++) {
    if (condition) {
        continue;
    }
    doCostlyStuff();
}

Не передавайте слишком много аргументов при вызовах функций

По крайней мере ради читаемости следующий подход ужасен:

function greet(name, language, age, gender, hairColour, eyeColour) {
    alert(name);
}

В следующем примере объект заранее создаётся как аргумент или передаётся объект прямо на месте, что гораздо лучше.

function greet(user) {
    alert(user.name);
}

greet({
    name: "Bob",
    gender: "male"
});

Сопоставьте 'this' с 'self'

При написании объектно-ориентированного (ОО) кода JavaScript вы должны пониматьthisобласть видимости. Независимо от того, какой шаблон проектирования вы используете для создания псевдоклассов, ссылка наthis— это самый простой способ указать на экземпляр. Когда вы начнете интегрировать вспомогательные методы jQuery со своими псевдоклассами, вы заметитеthisизменение области видимости.

Bob.findFriend("Barry");

Person.prototype.findFriend = function(toFind) {
    // this = Bob
    $(this.friends).each(function() {
        // this = Bob.friends[i]
        if (this.name === toFind) {
            // this = Barry
            return this;
        }
    });
}

В приведенном выше примере,thisпроисходит изменение от ссылки наBobк ссылке на его другаBarryпроцесс обращения.thisПониманиеthisизменение его значения со временем важно. Внутри функции прототипа,Бобон указывает на текущий экземпляр псевдокласса, к которому принадлежит (здесь$.each()цикл,thisон будет переназначен наi-й элемент разбираемого массива.

Решение состоит в том, чтобыthisпереназначить значениеselfили_self.self(без подчёркивания) не являетсязарезервированным словом,; это действительно window— свойство объекта.selfПример взят из исходного кода jQuery, но они также признали эту ошибку и планируютисправить текущую ситуацию,_selfто есть переключиться наself.selfЛично я всё ещё предпочитаю использовать

, не по какой-либо другой причине, кроме его простоты -- но это может выявить некоторые очень запутанные ошибки. Короче говоря, использование$.each()рискованно; используйте с осторожностью.thisВ следующем примере я лучше использую

Bob.findFriend("Barry");

Person.prototype.findFriend = function(toFind) {

    // 就这一次用到了 "this"
    var _self = this;

    $(_self.friends).each(function(i,item) {
        if (item.name === toFind) {
            return item;
        }
    });

}

Можно ли использовать Boolean?

значение.является, можетМожно ли использовать Boolean?имеетПеременные Boolean должны легко идентифицироваться по своим именам. Вы можете использовать такие префиксы, как

isEditing = true;

obj.canEdit = true;

user.hasPermission = true;  

Сведите перерисовки и перекомпоновки к минимуму

в качестве префикса для образования вопроса.Сведите перерисовки и перекомпоновки к минимумуПерерисовки и перекомпоновки связаны с процессом повторного рендеринга DOM, который происходит при изменении определённых свойств или элементов. Перерисовка запускается, когда внешний вид элемента изменяется без изменения макета.

Николь Салливан в подробной

записи блога,

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

var myList = document.getElementById("myList");

for (var i = 0, len = arr.length; i < len; i++) {

    myList.innerHTML += "<li>" + arr[i].title + "</li>"; //重新布局 -- 增加到元素

}

Пример перекомпоновкиforНа самом деле, код ниже не так уж ужасен. Но давайте сначала предположим, что массив

содержит 10 элементов

var constructedHTML = "";

for (var i = 0, len = arr.length; i < len; i++) {
    constructedHTML += "<li>" + arr[i].title + "</li>"; //没有重新布局 - 增加到字符串
}

document.getElementById("myList").innerHTML = constructedHTML; //在这里重新布局

В приведённом вышеinnerHTMLцикле каждая итерация вызывает перекомпоновку. 10 итераций означают 10 перекомпоновок.

Теперь рассмотрим следующий код:В этом сценарии элементы, которые нужно добавить, формируются в строке. Внутри цикла перекомпоновка не происходит, потому что DOM не изменился. Только когда массив полностью перебран и построенная строка применена к объекту, только тогда происходит единственная перекомпоновка в функции.canvasСуществует бесчисленное множество перекомпоновок и перерисовок, которых можно избежать; надеюсь, вам посчастливилось изучить эти приёмы. По этой теме есть множество материалов для чтения, но большинство из них будут ссылаться на Николь Салливан

Не используйте микросекунды для генерации уникальных идентификаторов

, что является идеальной отправной точкой. Помимо уроков здесь, есть и другие важные уроки, которые стоит усвоить, когда речь заходит о различных технических терминах эпохи 'web 3.0' и HTML5. Приведённый выше анализ напрямую применим к написанию кода jQuery. Когда возишься с

var myID = "static" + new Date().getTime();

эти принципы также важны, а также старайтесь поддерживать частоту кадров в диапазоне 30-60.

Это может вызвать ошибки, которые трудно отлаживать традиционными методами. Поскольку ваш DOM создаётся во время выполнения, традиционная проверка исходного кода страницы не может выявить ошибки, связанные с несколькими дублирующимися идентификаторами. Обработка ошибок JavaScript и jQuery будет считать первое совпадение идентификатором и игнорировать остальные дублирующиеся идентификаторы. Так что она даже не выбросит ошибку JS!

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

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

var myID = "static" + Math.round(Math.random() * 10000);

Лично я предпочитаю генерировать GUID вручную. Технически говоря, GUID создаются на основе вашего аппаратного обеспечения, но следующая функция JavaScript справляется довольно хорошо. Я позаимствовал это изпоста на Stack Overflow— это довольно удобная функция.

function S4() {
   return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
}
function guid() {
   return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
}

var myID = "static" + guid();

Определяйте возможности, а не типы браузеров

Поддерживает ли браузер пользователя геолокацию? Поддерживает ли он Web Workers? HTML5-видео? HTML5-аудио? Раньше ответ был таким:

if ($.browser.msie) {
    // 哦,是IE啊,那肯定不支持
}

Но мир меняется быстро. Последнюю версию IE почти можно считать современным браузером, но она всё ещё причиняет боль фронтенд-разработке. Более ранние версии IE были в основном такими же плохими, как и предыдущие, что заставило ленивых JavaScript-программистов привыкнуть определятьif (ie), а затем выполняется какой-то сломанный синтаксис, работающий только в Microsoft. Теперь IE9 объявил те проприетарные функции устаревшими, поэтому старыеif (ie)реликты вместо этого начинают создавать проблемы.

Так как насчёт обнаружения каждой возможности без проверки user-agent (который и ненадёжен, и может быть подделан)?

Если ваш ответ —«Это довольно надёжно», то вы правы.

использоватьModernizrЧто ж, это JavaScript-библиотека, совместно разработанная Полом Айришем, мастером, о котором мечтает вся индустрия. Она сочетает широкую применимость, легковесный дизайн и огромнуюдокументациюв одном, и не требует умственных усилий для внедрения — поистине незаменимая вещь для дома, путешествий и затыкания людей. Она создаётModernizrобъект, который содержит результаты всех её тестов на обнаружение, делая проверку поддержки возможности такой же простой, как в примере ниже:

// 检测浏览器是否支持canvas的老办法
if (!!document.createElement('canvas').getContext) { ... }

// 用 Modernizr 检测
if (Modernizr.canvas) { ... }

Используйте читаемые миллисекунды

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

// 这是3秒,30秒还是300秒啊?
var timeout = 30000;

// 增加了额外的计算开销,但是读和修改会更容易
var timeout = 30 * 1000;

О коде jQuery

Выстраивайте цепочки, как бешеный пёс

Одна из лучших возможностей jQuery — это цепочки функций. Возможно, вы немного ими пользовались, может, соединяли простые вызовы один за другим... но доводилось ли вам носиться вверх и вниз по DOM, как бешеный пёс? Потратьте немного времени, чтобы освоиться с.end()функцией. Она будет критически важна, когда вы прыгаете вверх и вниз по DOM от вашего исходного селектора.

$(".quote")
    .hide()
    .find("a").text("Click here").bind("click",doStuff).end()
    .parent().removeClass().addClass("testimonial").draggable().end()
    .fadeIn("slow");

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

Используйте атрибуты data-*

Те из вас, кто долго писал на JavaScript (нативном, не jQuery), вероятно, знакомы с атрибутами. Вы находите способы устанавливать их, получать их или злоупотреблять ими.relиtitle ...

Не говорите, что HTML5 или jQuery не помогли. Новая спецификация позволяет использовать в HTML-элементах префиксdata-для обозначения атрибутов, содержащих данные. jQuery отлично справляется с преобразованием указанных строк в правильные типы данных JavaScript. Давайте создадим элемент с несколькими data-атрибутами.DIV 。

<div id="test" data-is-bool="true" data-some-number="123"></div>

Теперь, хотя наши значения заключены в кавычки, они не будут рассматриваться как строки:

typeof $("#test").data("isBool"); // boolean

typeof $("#test").data("someNumber"); // number

Особый случай

Обратите внимание: чтобы эти фрагменты кода работали, определения атрибутов (в HTML) должны использовать строчные буквы. Это важно. Но если вы опытный фронтенд-разработчик, вы всё равно захотите использовать camelCase для именования ваших переменных данных. Как и во многих местах JavaScript, ведущий дефис означает, что следующая буква подлежит капитализации в camelCase. Однако использование camelCase в определениях HTML-атрибутов в примере нижене разрешено, и приведёт к тому, что JavaScript выше вернётundefined。

не работает :(

<div id="test" data-isBool="true" data-someNumber="123"></div>

работает :)

<div id="test" data-is-bool="true" data-some-number="123"></div>

'.stop()' останавливает взаимодействие и прослушивание

Привязка анимационных эффектов jQuery к событиям мыши — ключевая часть современного веб-взаимодействия с пользователем, но даже некоторые из самых известных сайтов делают это плохо.Эта статьяпредставляет прямой пример реализации анимаций и демонстрирует, насколько визуально дисгармонично эти анимации выглядят вместе. К счастью, эту проблему легко решить, используя префикс функции или в вызове$.animate, добавив параметр, чтобы легко её решить.

При использовании$.animate, можно добавитьqueue: falseв параметры, чтобы избежать цепочки. Сокращённые методы анимации, такие как$.fadeInили$.slideDownне принимаютqueueнастройки; вы должны использовать$.stopэтот метод, чтобы остановить эти анимации заранее.clearQueueиjumpToEndсвязаны с этими двумя параметрамидокументация, потому что, ради всего святого, иначе я не могу вам помочь.

$("selector").stop(true,true).fadeOut();

$("selector").animate({
    property: value
}, {
    duration: 1000,
    queue: false
}

Оптимизируйте свои селекторы

jQuery очень крут. Он умеет почти всё, но пока всё ещё не может сварить для вас кофе — я слышал, эта функция есть в планах версии 2.0. Одна вещь, за которой нужно следить, — не злоупотреблять егоsizzleJSмощью движка селекторов. Чтобы избежать этой проблемы, есть две стратегии:Кэшируйте результаты селекторовииспользуйте эффективные селекторы。

Кэшируйте результаты селекторов

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

// before
$(".quote a").bind("click", doStuff); // DOM查询

// now
$(".quote a").addClass("quoteLink"); // DOM查询!!

// later
$(".quote a").fadeIn("slow"); // 又一次DOM查询!!!

Игнорируйте цепочки; так лучше:

// before
var $quoteLinks = $(".quote a");  // 只需一次DOM查询
$quoteLinks.bind("click", doStuff);

// now
$quoteLinks.addClass("quoteLink");

// later
$quoteLinks.fadeIn("slow");

Используйте эффективные селекторы

Хорошо, jQuery/SizzleJS может легко использовать селекторы CSS3, но какова реальная цена? В этом сценарии браузер может использоватьdocument.querySelector(), но он также может разбить строку селектора и затем вручную запросить DOM.

// ID搜索是最快的查询方式,然后它获取孩子节点的列表,匹配其中class为'quotes'的元素
$("#quoteList").children(".quotes");

// 只在预先确定的bar元素下查找'foo'class
$(".foo",bar); 

Циклы 'for' всегда быстрее, чем циклы 'each()'

Независимо от того, что произойдёт в разработке браузеров в ближайшие годы, нативныеforциклы всегда будут быстрее, чем циклы$.each()в jQuery. Когда вы задумываетесь над большим вопросом, что такое jQuery на самом деле (библиотека, которая оборачивает нативные функции JS), вы начинаете понимать, что нативный код JavaScript всегда будет быстрее. Использование библиотеки вместо нативного кода — это компромисс между скоростью выполнения и скоростью написания кода.

Очень важно всегда использоватьforциклы для функций, критичных к производительности, которые могут вызываться сотни раз в секунду. Например:

  • движение мыши
  • интервалы времени
  • циклы внутри циклов

CSS

Понимание блочной модели — ключ к успеху

«Блочная модель» — критически важный, определяющий фактор в понимании того, как браузеры отображают страницы. Полное понимание её сложности может чудесным образом упростить вашу работу. Блочная модель описывает способ вычисления физических размеров HTML-элементов. Если блочный элемент имеет фиксированную ширину, скажем, 100px, как следует определять его padding, border и margin?

Многие сайты содержат подробные объяснения, но давайте упростим: в браузерах, соответствующих стандартам, border и padding располагаются за пределами указанной ширины. Лучше всего это объяснить с помощью диаграммы. Например, следующий код:

.foo {
    width: 150px;
    height: 150px;
    padding: 25px;
    border: 25px solid;
    margin: 20px;
}

Что вы могли бы ожидать (Режим совместимости)

padding и border вычисляются внутрь, сохраняя и высоту, и ширину на уровне 150px.

Что вы на самом деле видите (режим стандартов)

Однако фактическая итоговая ширина и высота равны 250px. То есть 150px + (2 * 25) + (2 * 25).

Если вам этот результат кажется странным, вы не один (ну, вы человек, просто говорю, что другие тоже так думают). Теперь есть решение: нужно ввести CSS-свойство под названиемbox-sizing, которое поддерживается вIE8 и выше. Оно позволяет выбрать точный способ расчета размеров элемента, что может избавить вас от проблем. Конкретные поддерживаемые параметры различаются в зависимости от браузера, и требуются вендорные префиксы. Подробности см. наcaniuse.com 。

/* 旧方法 (178 + 20 + 2 = 200) */
.foo {
    width: 178px;
    padding: 10px;
    border: 1px;
}

/* 更好的方法 */
.foo {
    width: 200px;
    padding: 10px;
    border: 1px;
        -webkit-box-sizing: border-box;
        -moz-box-sizing: border-box;
        box-sizing: border-box;
}

Хотя вы всегда можете считать в уме ширины, вычитая значения в пикселях то тут, то там (как это делал тот первый метод), когда задействованы разные единицы измерения ширины (например, проценты или EM), никто не может сообразить, что делать. В настоящее время, кроме оборачивания элементов в родительский элемент, чтобы гарантировать, что ширина иpadding/margin/bordersмогут быть полностью разделены, другого решения нет.

Знайте, когда использовать float, а когда position

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

Использование float для извлечения элементов из DOM и принудительного смещения их влево или вправо довольно надежно. Они стали панацеей эпохи после табличной верстки во фронтенд-разработке, возможно, потому что браузеры в прошлом плохо поддерживалиdisplay: inlineиinline-blockэто, а также из-за ошибок, возникших при поддержке position.z-indexошибок. Но теперь действительно нет оправдания. inline-block уже хорошо поддерживается, и простое изменение может заставить его работать в IE7.

Слава богу, старые споры против использования CSS для абсолютного позиционирования элементов утихли. Теоретически свойство позиционирования позволяет размещать элементы на странице с координатами X и Y — простой и прямой подход, знакомый разработчикам Flash.

Понимание позиционирования

При позиционировании элементов с помощью CSS очень важно понимать один факт: позиционирование всегда происходит относительно ближайшего родительского элемента, у которого есть свойство позиционирования. Когда люди впервые начинают использовать CSS, распространено ошибочное представление, чтоposition: absolute;он позиционируется относительно корневого элемента страницы. Я думаю, это заблуждение возникает из случаев, когда у элемента нет родительского элемента со стилем position -- в таком случае их вывод верен. При обходе вверх по DOM-дереву, если не найден ни один элемент со стилем позиционирования, он будет позиционирован относительно корневого элемента страницы.

Итак, еслиposition: absolute;он выводит элементы из потока, в котором они находятся, как позиционировать элемент относительно его родителя? Метод прост. Родительскому элементу нужно задатьposition: relative;стиль, и тогда все дочерние элементы будут размещены в порядке top, right, bottom, left. Используя это знание, как бы вы реализовали следующую интуитивную раскладку?

Используяfloat, вам нужно обернуть эти элементы в родительский элемент, а затем задать.onefloat left, а затем изменить.twoи.threeдляfloatиmargin. В конце концов, вы должны написать что-то вроде следующего:

.parent {
    /* ghetto clearfix */
    width: 310px;
    overflow: auto;
}
.one {
    width: 200px;
    height: 210px;
    float: left;
}
.two {
    width: 100px;
    height: 100px;
    float: right;
    margin-bottom: 10px;
}
.three {
    width: 100px;
    height: 100px;
    float: right;
}

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

.parent {
    position: relative;
    width: 310px;
    height: 210px;
}
.one, .two, .three {
    position: absolute;
}
.one {
    top: 0;
    left: 0;
    width: 200px;
    height: 210px;
}
.two {
    top: 0;
    right: 0;
    width: 100px;
    height: 100px;
}
.three {
    bottom: 0;
    right: 0;
    width: 100px;
    height: 100px;
}

Как упоминалось ранее, нужно рассмотреть некоторые вопросы, связанные сz-index. Хотя приведенный выше пример может показаться немного чрезмерным, как только вы начнете думать о позиционировании, перед вами откроется новый мир возможностей.

Пробельные символы

Если мы будем постоянно переключаться между однострочным и многострочным форматами параметров CSS, пробельные символы в CSS также будут различаться. Я не буду вдаваться в это слишком подробно.

Правильные пробельные символы

/* 不好 */
.selector {display:none;background:#FF0000;color:#000000;}

/* 好 -- 单行 */
.selector { display: none; background: #FF0000; color: #000000; }

/* 好 -- 多行 */
.selector {
    display: none;
    background: #FF0000;
    color: #000000;
}

Фигурные скобки на одной строке

.selector {
    display: none;
    background: #FF0000;
    color: #000000;
}

Отступы дочерних элементов

Использовать это или нет — дело вкуса; лично я использовал бы этот формат только в CSS-документах с однострочными определениями.

.selector { display: none; background: #FF0000; color: #000000; }
    .selector a { text-decoration: none; }
    .selector span { font-weight: bold; }

Группировка и отступы для свойств с вендорными префиксами

.selector {
    background: #FFF; border: 1px solid #000; color: #EAEAEA;
        -webkit-border-radius: 3px;
        -moz-border-radius: 3px;
        border-radius: 3px;
}

Формат сокращенной записи CSS

Группировка свойств

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

/* 逐个定义,太长了 */
padding-top: 1px;
padding-right: 2px;
padding-bottom: 1px;
padding-left: 2px;

/* 上,右,下,左,好很多 */
padding: 1px 2px 1px 2px;

/* 上和下,左和右,最优 */
padding: 1px 2px;

От 0px до героя

Присваивать значение0свойству избыточно. Неважно, отстоит ли элемент от левого края на0pxили на0 слонов; главное — знать, что он прижат к левому краю.

/* 不好 */
padding: 0px 10px;

/* 好 */
padding: 0 10px;

Блоки комментариев

Для задачи поддержки нескольких разделов стилей в таблице стилей добавление комментариев к большим участкам CSS — отличный способ. Очевидно, это лучше работает в сочетании с однострочным стилем CSS, но и в многострочном стиле CSS это не совсем бесполезно. Использовать ли в комментариях дефисы, знаки равенства или подчёркивания для выделения — вопрос мнения, но вот способ, который нравится мне:

/* === HORIZONTAL NAV === */
#horizNav { width: 100%; display: block; }
#horizNav li { display: block; float: left; position: relative; }
#horizNav li a { display: block; height: 30px; text-decoration: none; }
#horizNav li ul { display: none; position: absolute; top: 30; left: 0; }

/* === HOME PAGE - CAROUSEL === */
#carousel { width: 960px; height: 150px; position: relative; }
#carousel img { display: none; }
#carousel .buttons { position: absolute; right: 10px; bottom: 10px; }

Очистка обтекания

Очистка<div>раньше означала лишний DOM, потому что требовала добавления дополнительного очищающего элемента. Лучший метод — задать явную ширину родительскому элементу ('auto' неэффективно во всех браузерах и сценариях) и установить свойство overflow в 'auto' или 'hidden'. У 'hidden' явно лучше совместимость, но в некоторых IE-совместимых версиях 'auto' работает лучше.

HTML:

<div class="parentElement">
    <div class="childElement">
        I'm floated left!
    </div>
    I'm normal text that wraps around the float
</div>

CSS:

.parentElement {
    width: 100%;
    overflow: hidden;
}
.childElement {
    float: left;
}

Один из участников этого проекта напомнил мне обратить внимание на новейший clearfix.micro clear-fixсчитается достаточно стабильным и кроссбраузерным, чтобы войти в последний выпуск HTML5 boilerplate. Янастоятельнорекомендую вам взглянуть. Хотя я не большой поклонник браузерно-специфичного CSS и:afterподобных псевдоэлементов, этот micro clearfix действительно более надёжен. Он также позволяет избежать проблемы схлопывания верхнего отступа.

Вертикальное и горизонтальное центрирование

Горизонтальное центрирование элементов на самом деле не ракетостроение, и я уверен, что большинство из вас знакомы со следующим фрагментом кода:

.class {
    width: 960px;
    margin: 0 auto;
}

Фронтенд-разработчики давно используют этот код и не поняли, почему этот подход не работает для вертикального центрирования. С моей точки зрения, важно помнить, что родительский элемент обычно имеетheight: auto;style, а также не имеет 100% высоты, необходимой для вертикального центрирования. Применениеposition: absolute;может эффективно перевести элемент в режим позиционирования, а отступы, установленные в auto, автоматически помогут ему скорректировать своё положение для достижения центрирования.

.exactMiddle {
    width: 100px;
    height: 100px;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: auto;
}

К недостаткам этого метода относится отсутствие поддержки в IE6 и IE7, а также отсутствие полосы прокрутки, когда окно браузера уменьшено меньше центрируемого объекта. Наэтой веб-страницеперечислено больше методов (этот сейчас 4-й), но текущий на данный момент — лучший.

Вертикальное центрирование текста в элементе тоже несложно. Если текст однострочный, например элемент горизонтальной навигации, можно задатьline-heightравным физической высоте элемента.

#horizNav li {
    height: 32px;
    line-height: 32px;
}

Определяйте возможности, а не типы браузеров

В более раннем обсуждении определения возможностей JavaScript определение того, что браузер являетсялюбой версиейIE, и затем применение определённых атрибутов становилось всё более проблематичным. Железный человек Пол Айриш возглавил использованиеопределения версии IEметоды для решения этих проблем, ноModernizrспас нас с тех пор. Modernizr помещает в корневой<html>элемент некоторые классы, описывающие, поддерживаются ли определённые функции. Тогда прогрессивные стили могут легко каскадироваться из этих классов или удаляться из них.

.my_elem {
   -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.25);
   -moz-box-shadow: 0 1px 2px rgba(0,0,0,0.25);
   box-shadow: 0 1px 2px rgba(0,0,0,0.25);
}

/* 如果 box shadow 不支持, 就应用 borders 属性 */
.no-boxshadow .my_elem {
   border: 1px solid #666;
   border-bottom-width: 2px;
}

Не злоупотребляйте !important

Полагаться на!importantтег — опасная практика. Ситуации, когда вы абсолютно обязаны его использовать, крайне редки и представляют собой особые случаи. Эти ситуации обычно связаны с переопределением другой таблицы стилей, которую вы не можете редактировать или не имеете разрешения редактировать. Другой сценарий — жёстко прописать стили элемента, чтобы стили, сгенерированные JavaScript, не получали более высокого приоритета. Но в действительности,!importantчасто используется как ленивый обходной путь, чтобы один стиль переопределял другие, что в будущем вызовет много проблем.

Пара!importantБольшинство случаев использования этого тега можно избежать, лучше понимая специфичность селекторов CSS и то, как более точно нацеливаться на элементы. Чем конкретнее селектор, тем выше вероятность, что он будет принят как применимый стиль. Пример ниже от vanseodesign демонстрирует специфичность в действии.

p { font-size: 12px; }
p.bio { font-size: 14px; }

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

Агрессивная обратная совместимость

Стоит отметить, что это моё личное мнение, и оно применимо только к определённым ситуациям. В крупных коммерческих проектах или корпоративных решениях, которые зависят от старых браузеров, позиция прогрессивного улучшения не будет легко принята.

Прогрессивное улучшение означает, что если конкретный (более старый) браузер не может отобразить определённый эффект, его следует просто игнорировать. Кнопки CSS3 — хороший пример. Такие эффекты, какborder-radius, box-shadow, text-shadowиградиентыбудут отображаться в продвинутых браузерах. Для немного более старых браузеров вы можете использовать.PNGизображение в качестве безвредного запасного варианта, а самым элегантным из всех решений было бы предоставление PNG-Fix для IE6 или использованиеfilterпараметры для замены таких свойств, как градиенты и тени. Однако в этом случае прогрессивное улучшение заставит вас игнорировать старые браузеры и представлять в них плоский, приемлемый объект.

Проще говоря, прогрессивное улучшение — это:Если ваш браузер не может отображать градиенты или тени блоков, это просто вам не повезло.。

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


CSS3 и HTML5

Думаю, я достаточно сказал на эту тему. ИспользуйтеModernizrдля определения доступности конкретных функций HTML5 и CSS3.

Использование и злоупотребление @font-face

Прежде чем рассматривать встраивание пользовательского шрифта, очень важно проверитьEULAи узнать, разрешено ли веб-встраивание. Поставщики библиотек шрифтов, естественно, не хотят, чтобы дизайнеры и разработчики могли хранить файлы библиотек шрифтов непосредственно на сервере, откуда опытные конечные пользователи могут их скопировать. Некоторые поставщики также запрещают встраивание определённых типов файлов, таких как.TTFи.OTF。

Если после тщательного рассмотрения вы считаете, что нужный вам шрифт можно встраивать, посмотрите нагенератор @font-faceот Font Squirrel. Он использует разработку Fontspring:пуленепробиваемую структуру @font-faceи может автоматически генерировать все необходимые форматы файлов.

Обратная совместимость

К счастью, браузеры достигли изящной деградации при обработке функций HTML5 и CSS3, которые они не поддерживают. Добавленные к<input />новые типы тегов, такие как "email", "search" и т. д., обычно изящно деградируют до обычных текстовых полей ввода, когда браузер не поддерживает их нативно.<input type="text" />. Аналогично, неподдерживаемые функции CSS3 не появятся, а адаптивные макеты, управляемые медиазапросами по высоте и ширине, не будут применяться.

Изысканные эффекты CSS3 следует применять в качестве награды для пользователей современных браузеров.

В разделе "Ресурсы" ниже мы включили несколько библиотек, которые помогают поддерживать работоспособность функций HTML5 и CSS3 в ряде старых браузеров.


Ресурсы

Следующие ресурсы важны для стандартизации кода и взаимодействия на современных веб-страницах. Они обеспечивают работу функций CSS3 и HTML5 в ряде браузеров, которые ранее не поддерживали их.

  • jQuery вспомогательные библиотеки JavaScript
  • jQuery UI Делает для пользовательского взаимодействия/интерфейса то же, что jQuery делает для JavaScript
  • Modernizr Определяйте возможности, а не браузеры!
  • RespondJS Добавляет поддержку адаптивной вёрстки в старые браузеры
  • Генератор @font-face Комплексное встраивание шрифтов
  • RaphaelJS Удобная кроссбраузерная векторная графика
  • HTML5 Boilerplate Это хорошая отправная точка для любого проекта. Однако даже его "slim" версия немного раздута.
  • Twitter Bootstrap Позволяет быстро создавать прототипы и оформлять простые веб-приложения.

Эта статья была написана Tait Brown (@taitems), а эта китайская версия былаcoderLMNпереведена.