14 корисних методів, приміток і кращих вправ jQuery

21

Від автора:

Якщо і є щось погане в jQuery, це те, що початковий рівень настільки низький, що вражає тих, хто зовсім не знайомий з JavaScript. З одного боку, це фантастика. Однак, зі зворотного боку, наслідком цього є поверхневі знання і, якщо чесно, огидно поганий код (який я і сам писав!).

Але це нормально; страхітливо жалюгідний код, який змусив би навіть зітхнути вашу бабусю – щось на кшталт обряду посвячення. Головне – здійснити сходження на цю гору, і це як раз те, що ми сьогодні обговоримо в цьому підручнику.

1. Методи повернення об’єкта Object jQuery

Важливо пам’ятати, що більшість методів повернуть об’єкт jQuery. Це надзвичайно корисно і дозволяє будувати широко використовуються ланцюжки функцій.

$someDiv
.attr(‘class’, ‘someClass’)
.hide()
.html(‘new stuff’);

Знаючи, що об’єкт jQuery завжди повертається, час від часу ми можемо користуватися цим для видалення надлишкового коду. Наприклад, розглянемо наступне:

var someDiv = $(‘#someDiv’);
someDiv.hide();

Причина, по якій ми «кешуємо» місце розміщення елемента someDiv, полягає в обмеженні кількості разів, коли ми змушені простежувати DOM цього елемента.

Код вгорі повністю гарний; однак ви могли б майже так само легко об’єднати два рядки в одну для досягнення того ж результату.

var someDiv = $(‘#someDiv’).hide();

Таким чином, ми все ще приховуємо елемент someDiv, але цей метод так само, як ми і дізналися, повертає об’єкт jQuery — на який ми потім посилаємося через змінну someDiv.

2. Селектор Find

Якщо ваші селектори не настільки сміховинно погані, jQuery виконає фантастичну роботу по їх оптимізації, і, загалом, вам не потрібно занадто про них турбуватися. Однак, поряд зі сказаним, ви можете дозволити собі деяку кількість удосконалень, злегка покращують продуктивність вашого скрипта.

Одним з таких рішень є використання, коли це можливо, методу find(). Основна ідея – це відхід від примусу jQuery використовувати движок Sizzle, коли це не є необхідним. Звичайно, будуть моменти, коли це неможливо — і це нормально; але, якщо вам не потрібні додаткові витрати, не нарывайтесь на них.

// добре для сучасних браузерів, хоча Sizzle не починає "запускатися"
$(‘#someDiv p.someClass’).hide();
// добре для всіх браузерів, а Sizzle не включає запалювання.
$(‘#someDiv’).find(‘p.someClass’).hide();

В останніх сучасних браузерів є підтримка QuerySelectorAll,що дозволяє передавати селектори, аналогічні CSS, не потребуючи jQuery. Сам по собі jQuery з тим же успіхом використовує цю функцію, коли це можливо.

Однак старі браузери, а саме IE6/IE7, природно, не забезпечують підтримку цієї функції. Отже, такі більш складні селектори запускають двигун jQuery Sizzle – безсумнівно чудовий, але вимагає великих ресурсів.

Sizzle – блискуча реалізація, яку я, можливо, ніколи не зрозумію. Тим не менш, якщо коротко, він спочатку бере селектор і перетворює його в «масив», що складається з кожного компонента вашого селектора.

// туманне уявлення про те, як це працює
[‘#someDiv, ‘p’];

Потім справа наліво починає розшифровувати кожен елемент стандартними регулярними виразами. Крім усього іншого, ще це означає, що крайня праворуч частина вашого селектора повинна бути як можна більш конкретної, наприклад, id або назва тега.

Отже, коли це можливо:

Намагайтеся зробити свої селектори простими

Використовуйте метод find(). Таким чином, замість використання Sizzle, можна продовжити застосовувати вбудовані функції браузера.

Як можна краще покажи праву частину селектора при використанні Sizzle.

Контекст замість цього?

Також можна використовувати в своїх селекторах поточний контекст, наприклад:

$(‘.someElements’, ‘#someContainer’).hide();

Цей код наказує jQuery упакувати в колекції безліч всіх елементів класу someElements — є дочірніми елементами someContainer — всередині jQuery. Використання контекстів – корисний спосіб обмеження обходу вузлів DOM, оскільки «за лаштунками» jQuery у цьому разі використовують метод find.

$(‘#someContainer’)
.find(‘.someElements’)
.hide();

Підтвердження:

// ДЕСКРИПТОР: $(expr, context)
// (еквівалентний: $(context).find(expr)
} else {
return jQuery( context ).find( selector );
}

3. Не зловживайте $(this)

Не знаючи про всіляких властивостях і функціях DOM, можна легко без потреби зловжити об’єктом jQuery. Наприклад:

$(‘#someAnchor’).click(function() {
// нісенітниця
alert( $(this).attr(‘id’) );
});

p>Якщо об’єкт jQuery вам потрібен тільки для того, щоб мати доступ до атрибуту id тега-прив’язки, це марнотратно. Краще дотримуватися «звичайного» JavaScript’а.

$(‘#someAnchor’).click(function() {
alert( this.id );
});

Будь ласка, зверніть увагу на те, що є три атрибути, до яких завжди слід отримувати доступ c допомогою jQuery: «src,» «href» і «style.». Для цих атрибутів в старих версіях IE потрібне використання getAttribute.

Підтвердження:

// джерело jQuery
var rspecialurl = /href|src|style/;
// …
var special = rspecialurl.test( name );
// …
var attr = !jQuery.support.hrefNormalized && notxml && special ?
// деякі атрибути в IE вимагають спеціального виклику
elem.getAttribute( name, 2 ) :
elem.getAttribute( name );

Численні об’єкти jQuery

Ще гірше процес неодноразових запитів до DOM і створення множинних об’єктів jQuery.

$(‘#elem’).hide();
$(‘#elem’).html(‘bla’);
$(‘#elem’).otherStuff();

Будемо сподіватися, що ви вже обізнані про те, наскільки це неефективний код. Якщо немає, нічого страшного; всі ми вчимося. Рішення складається або у реалізації послідовності, або в «кешування» розташування #elem.

// Це працює краще
$(‘#elem’)
.hide()
.html(‘bla’)
.otherStuff();
// Або, якщо ви з якоїсь причини віддаєте перевагу так.
var elem = $(‘#elem’);
elem.hide();
elem.html(‘bla’);
elem.otherStuff();

4. Скорочений запис методу jQuery Ready

Обробка події ready документа за допомогою jQuery до смішного просто.

$(document).ready(function() {
// давайте станемо в захваті
});

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

$(function() {
// давайте станемо в захваті
});

Хоча остання частково менш удобочитаема, два уривка вгорі ідентичні. Не вірите? Просто погляньте в исходники jQuery.

// ДЕСКРИПТОР: $(function)
// шлях навпростець до документа готовий
if ( jQuery.isFunction( selector ) ) {
return rootjQuery.ready( selector );
}

rootjQuery – просто посилання на кореневій jQuery(document). При передачі селектора функції jQuery вона визначить тип селектора: string, tag, id, function, і т. д. Якщо була передана функція, jQuery викликає свій метод ready() і передає вашу анонімну функцію як селектор.

5. Створюйте безпечний код

Розробляючи код для дистрибуції, дуже важливо виключити будь-який можливий конфлікт імен. Що відбудеться, якщо якийсь скрипт, імпортований услід за вашим, теж мав би функцію $? Повна фігня!

Рішення – або викликати jQuery noConflict(), або зберігати свій код в самовызываемой анонімної функції, а потім передати їй jQuery.

Метод 1: NoConflict

var j = jQuery.noConflict();
// тут замість $ ми використовуємо j.
j(‘#someDiv’).hide();
// рядок внизу пошлеться на функцію $ іншої бібліотеки.
$(‘someDiv’).style.display = ‘none’;

Будьте обережні з цим методом і постарайтеся не використовувати його при дистрибуції свого коду. Він реально зіб’є з пантелику користувача вашого скрипта!

Метод 2: Передача jQuery

(function($) {
// у цій функції $ завжди буде посилатися на jQuery
})(jQuery);

Останні круглі дужки внизу автоматично викликають функцію – function(){}(). Однак при виклику функції ми також передаємо jQuery, який потім представлений $.

Метод 3: Передача $ допомогою методу Ready

jQuery(document).ready(function($) {
// $ посилається на jQuery
});
// $ або не визначено, або посилається на функцію іншого бібліотеки.

6. Будьте розумні

Пам’ятайте – jQuery це просто JavaScript. Не думайте, що він здатний виправити ваш поганий код.

Це означає, що якщо ми повинні оптимізувати такі речі, як пропозиції for з JavaScript, те ж саме стосується методу jQuery each. А чому ні? Це просто допоміжний метод, який потім «за лаштунками» створює пропозицію for.

// джерело методу jQuery each
each: function( object, callback, args ) {
var name, i = 0,
length = object.length,
isObj = length === undefined || jQuery.isFunction(object);
if ( args ) {
if ( isObj ) {
for ( name in object ) {
if ( callback.apply( object[ name ], args ) === false ) {
break;
}
}
} else {
for ( ; i < length; ) {
if ( callback.apply( object[ i++ ], args ) === false ) {
break;
}
}
}
// спеціальний швидкий випадок самого звичайного використання each
} else {
if ( isObj ) {
for ( name in object ) {
if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
break;
}
}
} else {
for ( var value = object[0];
i < length && callback.call( value, i, value ) !== false; value = object [i++] ) {}
}
}
return object;
}

Жахливо

someDivs.each(function() {
$(‘#anotherDiv’)[0].innerHTML += $(this).text();
});

Шукає anotherDiv в кожній ітерації циклу

Двічі підхоплює властивість innerHTML

Створює новий об’єкт jQuery тільки для того, щоб мати доступ до тексту елемента.

Набагато краще

var someDivs = $(‘#container’).find(‘.someDivs’),
contents = [];
someDivs.each(function() {
contents.push( this.innerHTML );
});
$(‘#anotherDiv’).html( contents.join(«) );

Таким чином, єдина дія, яку ми виконуємо всередині методу each (for) – це додавання в масив нового ключа…в протилежність запитом до DOM, використанню двічі властивості innerHTML елемента і т. д.

Ця порада стосується взагалі JavaScript, чим конкретно jQuery. Головне пам’ятати, що jQuery не виправляє поганий код.

Фрагменти документа

У подібних ситуаціях є альтернатива– використання фрагментів документа.

var someUls = $(‘#container’).find(‘.someUls’),
frag = document.createDocumentFragment(),
li;
someUls.each(function() {
li = document.createElement(‘li’);
li.appendChild( document.createTextNode(this.innerHTML) );
frag.appendChild(li);
});
$(‘#anotherUl’)[0].appendChild( frag );

Суть в тому, що існує безліч способів виконання таких простих завдань, як ця, і кожен має свої переваги і недоліки в плані продуктивності від браузера до браузеру. Чим більше ви дотримуєтеся jQuery і вивчаєте JavaScript, тим частіше можете помітити, що звертаєтеся до вбудованим властивостям і методам JavaScript. Якщо так, то це чудово!

jQuery забезпечує вражаючий рівень абстракції, і його перевагами ви повинні користуватися, але це не означає, що вас цими методами змушують користуватися. Наприклад, у вищезгаданому фрагменті ми вживаємо метод jQuery each. Якщо ви віддасте перевагу використовувати замість нього пропозицію for або while, теж вийде добре!

Поряд зі сказаним пам’ятайте про те, що розробники jQuery ретельно оптимізували цю бібліотеку. Суперечки навколо jQuery each() проти «рідного» пропозиції for дурні і банальні. Якщо ви в своєму проекті використовуєте jQuery, заощаджуйте час і використовуйте його власними допоміжними методами. Вони створені для цього!

7. Методи AJAX

Якщо ви тільки починаєте заглиблюватися в jQuery, різні доступні в ньому методи AJAX, на які ви могли наткнутися, трохи бентежать; не повинні. Фактично, більшість з них – просто допоміжні методи, які ведуть прямо до $.ajax.

get

getJSON

post

ajax

Як приклад давайте розглянемо getJSON, який дозволяє нам отримати JSON.

$.getJSON(‘path/to/json’, function(results) {
// зворотний виклик
// results містить повернутий об’єкт data
});

За лаштунками цей метод спочатку викликає $.get.

getJSON: function( url, data, callback ) {
return jQuery.get(url, data, callback, «json»);
}

$.get потім компілює переслані дані і заново викликає «хазяйський» (як би) метод $.ajax.

get: function( url, data, callback, type ) {
// переміщення аргументів, якщо аргумент data було пропущено
if ( jQuery.isFunction( data ) ) {
type = type || callback;
callback = data;
data = null;
}
return jQuery.ajax({
type: «GET»,
url: url,
data: data,
success: callback,
dataType: type
});
}

Нарешті, $.ajax виконує велику кількість роботи, щоб дати нам можливість успішно провести асинхронні запити через всі браузери!

Це значить – ви можете з тим же успіхом використовувати метод $.ajax безпосередньо і винятково для всіх запитів AJAX. Інші методи – просто допоміжні, які, як би то не було, зрештою роблять те ж саме. Отже, якщо хочете, виключіть посередника. Це в будь-якому випадку незначна проблема.

Воістину вищий клас:

$.getJSON(‘path/to/json’, function(results) {
// зворотний виклик
// results містить повернутий об’єкт data
});

Ще ефективніше:

$.ajax({
type: ‘GET’,
url : ‘path/to/json’,
data : yourData,
dataType : ‘json’,
success : function( results ) {
console.log(‘success’);
})
});

8. Організація доступу до вбудованим властивостям і методам

Отже, ви трохи вивчили JavaScript і дізналися, що, приміром, до значень атрибутів тегів-прив’язок можна отримати доступ безпосередньо:

var anchor = document.getElementById(‘someAnchor’);
//anchor.id
// anchor.href
// anchor.title
// .etc

Єдина проблема полягає в тому, що це, схоже, не працює, коли ви за допомогою jQuery робите посилання на елементи DOM, вірно? Ну звичайно, немає.

Не запрацює

// невдача
var id = $(‘#someAnchor’).id;

Отже, якщо вам знадобиться організувати доступ до атрибуту href (або для цього до будь-якого іншого «рідному» властивості або методу), то у вас є певна кількість варіантів.

// ВАРІАНТ 1 – використовуйте jQuery
var id = $(‘#someAnchor’).attr(‘id’);
// ВАРІАНТ 2 – отримаєте доступ до елемента DOM
var id = $(‘#someAnchor’)[0].id;
// ВАРІАНТ 3 – використовуйте метод get jQuery
var id = $(‘#someAnchor’).get(0).id;
// ВАРІАНТ 3А – не передавайте покажчик get
anchorsArray = $(‘.someAnchors’).get();
var thirdId = anchorsArray[2].id;

Методget надзвичайно корисний, так як може перетворити колекцію jQuery в масив.

9. Відстежуйте запити AJAX за допомогою PHP

Природно, для великої кількості своїх проектів не можна покладатися тільки на JavaScript для таких речей, як перевірка даних (валідація) або запити AJAX. А що якщо JavaScript відключений? Тому звичайна методика – це визначити, чи був зроблений запит AJAX на стороні сервера за допомогою використовуваного вами мови програмування.

jQuery робить цю задачу простий, встановлюючи заголовок з методу $.ajax.

// встановіть заголовок так, щоб викликається скрипт знав, що це XMLHttpRequest
// просто відправте заголовок, якщо це не віддалений XHR
if ( !remote ) {
xhr.setRequestHeader(«X-Requested-With», «XMLHttpRequest»);
}

Коли заголовок встановлений, ми можемо використовувати PHP (або будь-який інший мову) для перевірки і відповідної обробки. Для цього ми перевіряємо значення $_SERVER[‘HTTP_X_REQUESTED_WITH’].

Оболонка

function isXhr() {
return $_SERVER[‘HTTP_X_REQUESTED_WITH’] === ‘XMLHttpRequest’;
}

10. jQuery та $

Коли-небудь цікавилися, навіщо/як можна взаємозамінні використовувати jQuery і $? Щоб дізнатися відповідь, відкрийте исходники jQuery і перейдіть до самого кінця. Там ви побачите:

window.jQuery = window.$ = jQuery;

Весь скрипт jQuery, звичайно, упакований в самоисполняющуюся функцію, яка дозволяє скрипту як можна сильніше обмежити кількість глобальних змінних. Тим не менш, це також означає, що об’єкт jQuery недоступний поза анонімної функції-пакувальника.

Щоб це виправити, jQuery публікується в глобальному об’єкт window і в процесі, ще створюється псевдонім — $.

11. Умовна завантаження jQuery

Стандартний текст HTML5 Boilerplate пропонує витончену однострочную конструкцію, яка завантажить локальну копію jQuery у разі, якщо з якоїсь причини вибраний вами CDN не функціонує.

!window.jQuery && document.write(«)

«Озвучимо» вищевказаний код: якщо window.jQuery не визначено, повинна існувати проблема із закачуванням скрипта з CDN. У цьому випадку переходимо до правій частині оператора && і вставляємо скрипт, який посилається на локальну версію jQuery.

12. Фільтри jQuery

$(‘p:first’).data(‘info’, ‘value’); // populates $’s data object to have something to work with
$.extend(
jQuery.expr[«:»], {
block: function(elem) {
return $(elem).css(«display») === «block»;
},
hasData : function(elem) {
return !$.isEmptyObject( $(elem).data() );
}
}
);
$(«p:hasData»).text(«has data»); // grabs paras that have data attached
$(«p:block»).text(«are block level»); // grabs only paragraphs that have a display of block»

Примітка: jQuery.expr[‘:’] — просто псевдонім для jQuery.expr.filters.

13. Одиночна функція Hover

Що стосується jQuery 1.4, ми тепер можемо передати методу hover єдину самостійну функцію. До цього були потрібні два методу — in і out.

До:

$(‘#someElement’).hover(function() {
// mouseover
}, function() {
// mouseout
});

Тепер:

$(‘#someElement’).hover(function() {
// тут можна використовувати метод toggle(), якщо він застосовний
});

Зверніть увагу, що це не підхід «старе проти нового». Багато разів вам ще знадобиться передавати hover дві функції, і це абсолютно прийнятно. Тим не менше, якщо вам потрібно всього лише перемкнути який-небудь елемент (або щось подібне), передача одиночної анонімної функції заощадить деяку кількість символів!

14. Передача об’єкта-атрибута

Починаючи з jQuery 1.4 тепер можна передати об’єкт як другий параметр функції jQuery. Це корисно, коли потрібно вставити в DOM нові елементи. Наприклад:

До:

$(«)
.attr({
id : ‘someId’,
className : ‘someClass’,
href : ‘somePath.html’
});

Після:

$(«, {
id : ‘someId’,
className : ‘someClass’,
href : ‘somePath.html’
});

Це не тільки економить кілька знаків, але також сприяє тому, щоб код став чистішим. Додатково до атрибутів елементів ми можемо навіть передати специфічні атрибути і події jQuery, на зразок click або text.

Спасибі за прочитання!

14 корисних методів, приміток і кращих вправ jQuery

E-mail: [email protected]

Проект webformyself.com — Як створити свій сайт. Основи самостійного сайтобудування

P. S. Хочете опублікувати цікавий тематичний матеріал і заробити? Якщо відповідь «Так», то тисніть сюди.