10 советов, как составлять JavaScript без jQuery

JQuery - отличная библиотека. Она появилась примерно в то же время, когда IE6 считался браузером номер один. В то время было много специфических нюансов и различий между разными приложениями.

Их было довольно утомительно обходить, а JQuery - это идеальный инструмент для написания кода для разных браузеров:

Однако сегодня веб-браузеры очень серьезно продвинулись по сравнению с теми временами. Мы можем спокойно использовать все возможности ES5, а кроме того в нашем распоряжении есть невероятные HTML5 API, которые делают работу с DOM намного приятнее.

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

Не поймите меня превратно - JQuery прекрасная библиотека, и случаев, когда она вам понадобится, будет намного больше, чем наоборот. Тем не менее, для более мелких проектов, таких как простые страницы, с ограниченными JS-взаимодействиями, расширения браузеров и мобильные сайты, вы можете использовать Vanilla JS.

Ниже приводятся 10 советов, которые помогут вам в работе.

1. Ожидание готовности документа

Первое, что вы делаете, когда создаете JQuery, это укладываете код в вызов $(document).ready() так, чтобы вы знали, когда DOM готов к действиям. Без JQuery мы имеем событие DOMContentLoaded. Вот как оно используется:

JS

// Добавляем ожидание события DOMContentLoaded ко всему документу и вызываем анонимную функцию.
// Вы можете заключить код в функцию,
// и он будет выполняться сразу после того, как завершится загрузка.
document.addEventListener('DOMContentLoaded', function () {
    // Наше гавайское приветствие высветится на экране, как только загрузится страница,
    console.log('Aloha');
});

2. Выбор элементов

Когда-то, мы могли выбирать элементы только по ID, классам и именам тегов, и JQuery с его смарт CSS-подобными селекторами был нашим спасителем. Теперь браузеры исправили этот недочет и представили два важных приложения - querySelector и querySelectorAll:

JS

// Этот единственный аргумент является строкой, содержащей один или больше CSS-селекторов.
var lochNess = document.querySelector(".monsters");
console.log("It's from Scotland - " + lochNess.textContent);
// Мы также можем извлечь элемент определенного типа или класса, используя document.querySelectorAll.
// Этот код возвращает NodeList всех элементов, отвечающих нашему критерию.
var scary = document.querySelectorAll(".monsters");
console.log("Hide and seek champions: ");
for (var i = 0; i < scary.length; i++) {
    console.log(scary[i].innerHTML);
}

HTML

<ul>
<li class="monsters">Несси</li>

    <li class="monsters">Бигфут</li>

    <li class="monsters">Чупакабра</li>

</ul>

3. Установка и удаление обработчиков событий

Обработчики событий являются фундаментальной частью построения веб-приложений. Когда-то существовало два основных лагеря, которые отличались между собой тем, как они работали - IE и остальные. Но сегодня мы просто используем AddEventListener:

JS

var btn = document.querySelectorAll("button"),
    list = document.querySelector("ul");

// Мы вызываем метод addEventListener для отслеживания нужного нам события (в данном случае кнопки).
// Этот код запускает обработчик, который ожидает, пока в элементе не будет зафиксирован клик кнопки.

btn[0].addEventListener("click", function () {

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

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

    list.addEventListener("mouseover", enlarge);
});

// Чтобы отключить увеличение мы можем просто использовать removeEventListener.

btn[1].addEventListener("click", function () {

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

    list.removeEventListener("mouseover", enlarge);
});

// Давайте создадим функцию увеличения.

var enlarge = function () {

    // Добавляем класс увеличения для маркированного списка.

    list.classList.add("zoomed");

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

    list.addEventListener("mouseout", function () {

        list.classList.remove("zoomed")

    });

};

// Теперь мы хотим окрашивать названия в разные цвета при нажатии на них мышью.

// Когда на одном из элементов списка зарегистрирован 'click', он должен менять свой цвет на зеленый.
// Благодаря делегированию событий мы можем добавить обработчик событий непосредственно ко всему родительскому объекту.
// Таким образом, мы можем не добавлять отдельный обработчик событий к каждому элементу списка <li>.

list.addEventListener("click", function (e) {

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

    e.target.classList.add('green');

});

HTML

<button>Отключить увеличение</button>
<br><br>
Кликните на любое название, что оно стало зеленого цвета
<ul>
    <li>Чюбака</li>
    <li>Хан Соло</li>
    <li>Люк</li>
    <li>Боба Фетт</li>
</ul>

CSS

.green {
    color: green;
}

.zoomed {
    cursor: pointer;
    font-size: 23px;
}

addEventListener применен с третьим аргументом (useCapture), но некоторое время это было опционально. В результате, код выглядит еще больше похожим на JQuery.

4. Действия с классами и атрибутами

Производить действия с именами классов элемента без JQuery раньше было очень неудобно. Благодаря свойству classList теперь это осталось в прошлом. А если вам нужно управлять атрибутами, в вашем распоряжении есть setAttribute:

JS

console.log(classes);
});
btn[2].addEventListener("click", function () {
    // Он поддерживает добавление и удаление классов.
    classes.add("red");
});
btn[3].addEventListener("click", function () {
    // Вы можете также установить переключатель для класса включить/отключить
    classes.toggle("hidden");
});

HTML

<div id='myDiv' class="square"></div>

<button>Display id</button>

<button>Display classes</button>
<button>Color red</button>
<button>Toggle visibility</button>

CSS

.square {
    width: 100px;
    height: 100px;
    margin-bottom: 20px;
    border: 1px solid grey;
    border-radius: 5px;
}

.hidden {
    visibility: hidden;
}

.red {
    background-color: red;
}

5. Получение и установка содержимого элемента

JQuery имеет удобные методы text() и html(). Вместо них вы можете использовать свойства textContent и innerHTML, которые применяются уже очень давно:

JS

myText.textContent = " Koalas are the best animals ";

});
// Если мы хотим забрать весь HTML-узел  (в том числе и теги),мы можем использовать innerHTML.
var myHtml = myText.innerHTML;
console.log("innerHTML:  " + myHtml);
// Чтобы заменить html просто предложите новый контент.
// Естественно мы не ограничены в применении текста только этим одним случаем.
btn[1].addEventListener('click', function () {

    myText.innerHTML = "<button> Penguins are the best animals </button>";

});

HTML

<p id="myParagraph"><strong> Какое животное самое лучшее? </strong></p>

<button>Коала</button>

<br>

<button>Пингвин</button>

6. Вставка и удаление элементов

Хотя с помощью JQuery это делается намного проще, добавление и удаление элементов DOM возможно и с помощью простого JavaScript. Вот, как можно добавить, удалить и заменить любой элемент, который вы хотите:

JS

// Вставка верхнего слоя:
    // Возьмите говядину (это сэндвич) и примените для нее insertBefore.
    // Первый аргумент для insertBefore и будет элементом, который мы хотим добавить.
    // Второй аргумент будет узлом, перед которым вставляется новый элемент.
    beef.parentNode.insertBefore(topSlice, beef);
    // Нижний слой:
    // Здесь нам придется применить маленькую хитрость!
    // Предложите следующий ближайший элемент в качестве второго аргумента для  insertBefore,
    // таким образом, мы можем осуществить вставку непосредственно после элемента, который нам нужен.
    beef.parentNode.insertBefore(bottomSlice, beef.nextSibling);
};
var removePickles = function () {
    // Наконец мы хотим избавиться от этих элементов. Это тоже можно сделать с помощью javascript!

HTML

<button>Добавить к ланчу мясо </button>
<button>Добавить в сэндвич сыр</button>
<button>Убрать соленые огурцы</button>

<h3>Мой ланч</h3>
<ul id="lunch">
    <li><h4>Мой сэндвич</h4></li>
    <li>Хлеб</li>
    <li id="pickles">Соленые огурцы</li>
    <li id="Beef">Мясо</li>
    <li>Майонез</li>
    <li>Хлеб</li>
</ul>

7. Переходы по дереву DOM

Каждый истинный JS-ниндзя знает, что в DOM сокрыты огромные возможности. По сравнению с JQuery, простые DOM API предлагают ограниченный набор функций по выборке элементов высшего или одного уровня. Тем не менее, есть еще много вещей, которые вы можете сделать для путешествий по дереву DOM:

JS

snakes.addEventListener('click', function (e) {
    // Для того чтобы получить доступ к родительским элементам дерева  DOM мы используем метод parentNode .
    var parent = e.target.parentNode;
    console.log("Parent: " + parent.id);
    // И наоборот, вызов метода .children выдает все подчиненные элементы выбранного объекта.
    console.log("Children: ");
    var children = e.target.children;
    // Этот код возвращает HTMLCollection (тип массива), так что мы должны перебрать каждый элемент подчиненного содержимого.
    for (var i = 0; i < children.length; i++) {
        console.log(children[i].textContent);
    }
});
birds.addEventListener('click', function (e) {

HTML

Кликните на объект, чтобы увидеть все его подчиненные элементы

<div id="snakes">
    Змеи
    <ul id="venomous">
        Ядовитые
        <li>Кобра</li>
        <li>Гремучая змея</li>
    </ul>

    <ul id="non-venomous">
        Не ядовитые
        <li>Питон</li>
        <li>Анаконда</li>
    </ul>

</div>

Кликните на название любой птицы, чтобы увидеть список всех птиц того же вида

<div>
    Птицы
    <ul id="birds">
        <li>Фламинго</li>
        <li>Чайка</li>
        <li>Ворон</li>
        <li>Додо</li>
    </ul>
</div>

CSS

div {
    color: white;
    background-color: #93d0ea;
    font-family: sans-serif;
    width: 180px;
    text-align: center;
    padding: 10px;
    margin: 5px;
}

8. Обработка массивов через цикл

Некоторые из полезных методов, предоставляемых JQuery, доступны в стандарте ES5. Для перебора массивов, мы можем использовать forEach и map вместо их JQuery версий - each() и map(). Только обратите внимание на различия в аргументах и значении по умолчанию для this в обратных вызовах:

JS

var ninjaTurtles = ["Donatello", "Leonardo", "Michelangelo", "Raphael"];
// ForEach автоматически перебирает массив .
ninjaTurtles.forEach(function (entry) {
    console.log(entry);
});
// Метод map  вызывает функцию для каждого элемента массива и создает новый массив с результатами обработки.
var lovesPizza = ninjaTurtles.map(function (entry) {
    return entry.concat(" loves pizza!");
});
console.log(lovesPizza);

9. Анимация

Метод анимации JQuery превосходен для всего, что вы можете соединить самостоятельно, и если для приложения вам нужны сложные сценарии анимации, вы все равно должны использовать его.

Но благодаря чудесам CSS3 некоторые простые варианты анимации могут быть обработаны с помощью небольшой библиотеки наподобие Animate.css, которая позволяет вызывать для элементов анимацию, добавлять или удалять имена классов:

JS

circle.classList.add('animated');
// Мы перебираем каждую из кнопок и добавляем к каждой обработчик событий.
for (var i = 0; i < btn.length; i++) {
    // Здесь определяется анонимная функция, чтобы сделать возможным использование переменной  i.
    (function (i) {
        btn[i].addEventListener('click', function () {
            // Чтобы запустить анимацию, вам нужно просто добавить к объекту определенный класс.
            // В нашем случае все имена классов содержатся в атрибуте data-animation каждой кнопки.
            var animation = btn[i].getAttribute('data-animation');

HTML

<button data-animation="bounce">Bounce</button>
<button data-animation="pulse">Pulse</button>
<button data-animation="fadeInLeftBig">Fade in</button>
<button data-animation="fadeOutRightBig">Fade out</button>
<button data-animation="flip">Flip</button>

<div id="circle"></div>

CSS

body {
    text-align: center;
}

#circle {
    border-radius: 50%;
    margin: 50px auto;
    width: 50px;
    height: 50px;
    background-color: #93d0ea;
}

10. AJAX

AJAX являлся еще одной технологией, с которой не было определенности для разных браузеров. Теперь мы уже можем использовать тот же код везде.

Однако создание экземпляров объектов и отправка AJAX запросов с помощью XMLHttpRequest по-прежнему очень громоздки, так что лучше делать это с помощью библиотеки.

Но вы не обязаны подключать исключительно для этой цели весь JQuery. Вы можете использовать одну из многочисленных легких библиотек. Вот пример построения AJAX запроса напрямую, с помощью небольшой библиотеки reqwest:

JS

// Этот простой пример регистрирует тело url-адреса (html-файл) в консоли.
// В принципе можно вручную выполнить запрос GET, но это несколько утомительное занятие.
var request = new XMLHttpRequest();
request.open('GET', 'http://tutorialzine.com/misc/files/my_url.html', true);
request.onload = function (e) {
    if (request.readyState === 4) {
        // Проверяем, успешно ли прошло получение данных.
        if (request.status === 200) {
            console.log(request.responseText);
        } else {
            console.error(request.statusText);
        }
    }
};

Заключение

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

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

РедакцияПеревод статьи «10 Tips for Writing JavaScript without jQuery»