Як розплутувати локшину не впадаючи в депресію

Ця стаття не про ваші солодкі інтерфейси на реакте, ангуляре або що ви там використовуєте? Це стаття про ті ситуації, коли у вас є купка jQuery локшини. Ні, нехай це будуть гори jQuery локшини загорнутої у в'юшки бэкбона.

В статті використовується бібліотека Backbone.View.Elements

Проблема перша: маловиразні селектори
Всі ми бачили локшину, всі ми знаємо: локшина в JSе — напевно і у верстці не все добре. А раз так, то код швидше за все кишить незрозумілими маніпуляціями з будинком. Читати такий код складно, адже треба не упускаючи думки автора про те, що тут взагалі відбувається, тримати в розумі купку невиразних назв елементів. Отже, давайте додамо кодом трошки виразності:
_selectors: function () {
return {
elemName: '.block__elem-name'
};
}
Складемо всі селектори в одному місці і дамо ясна назва елементів, для вибору яких вони потрібні. Вибирати ми їх, до речі, будемо ось так:
this._elem('elemName');
вмсето
this.$('.block__elem-name');


У нашому випадку ви можете сказати, що це мало додало виразності, але не забувайте, що у вас швидше за все не проект, який використовує БЕМ для іменування класів, а солодко пахнуть понад семантичные селектори виду
'div > tr.row[data-active="true"] a.red-Button'
для кнопки «купити».

Крім можливості вибрати елемент всередині нашої в'юшки ми також отримали можливість одержати сам селектор по імені:
this._selector('elemName');
Це теж буває потрібно.

Ще одна перевага — якщо зміниться верстка, то нам треба буде змінити селектор тільки в одному місці, тому що ми зменшили дублювання коду.

Проблема друга: зберігання елементів
Знаєте, буває ось так:
$('div > tr.row[data-active="true"] a.red-Button').blahBlah();
а через 10 рядків ось так:
$('div > tr.row[data-active="true"] a.red-Button').anotherBlahBlah();

Віддерши долоню від особи ви винесете це в змінну
var $buyButton = $('div > tr.row[data-active="true"] a.red-Button');
ой ні, у вас же Backbone — винесете в властивість
this._$buyButton = this.$('div > tr.row[data-active="true"] a.red-Button');
чи ви вже підключили Backbone.View.Elements?
this._$buyButton = this._elem('buyButton');

Насправді не варто —
_elem
і так все кешує, так що просто
this._elem('buyButton');

Кешує говорите? А що якщо все зміниться?
Так, ми теж чули, що в програмуванні дві проблеми. Тому
this._findElem('elemName');
шукає без використання кешу
this._dropElemCache('elemName');
почистить кеш для конкретного елемента
this._dropElemCache();
відчистить весь ваш кеш до блиску, коли ви зрозумієте, що час настав. Наприклад, після візуалізації.

Глобальні елементи
А ще ми загорнули в jQuery найбільш часто використовувані елементи, щоб не робити це більше одного разу в додатку. Зустрічайте:
this._$window;
this._$body;
this._$document;


Проблема третя: імперативні стилі
Ніби цілий мова є, щоб стилі описувати, але немає — то й річ у локшині можна знайти барвники:
$('div > tr.row[data-active="true"] a.red-Button').css({color: 'magenta'});
Швидше поперчіть всі декларативністю і гарненько перемішайте CSS:
.button_active {
color: magenta;
}
А вже про маніпуляції класами ми подбали. Спочатку позначимо всі класи в одному місці:
_classes: function () {
return {
activeButton: 'button_active'
};
}
А потім, хочете — додавайте клас
this._addClass('activeButton', 'buyButton');
хочете — видаляйте:
this._removeClass('activeButton', 'buyButton');
хочете — перемикайте:
var condition = !!Math.round(Math.random());
this._toggleClass('activeButton', 'buyButton', condition);

Можна отримати селектор, якщо клас вже описаний:
this._selector('activeButton'); // returns '.button_active'
а можна і елементи пошукати:
this._elem('activeButton');
Тільки не забувайте про кеш, адже активна кнопка напевно змінюється
this._findElem('activeButton');

четверта Проблема: коли все складно
Буває селектори і класи формуються динамічно:
var id = 5,
state = 'highlighted';
$('.item[data-id="' + id + '"]').addClass('item_state_' + state);
Тут у справу вступають складні селектори:
_classes: function () {
return {
itemInState: 'item_state_%s'
};
},

_selectors: function () {
return {
itemById: '.item[data-id=%s]'
};
}
Тоді справедливо наступне:
this._class('itemInState', 'highlighted'); // поверне 'item_state_highlighted'
this._selector('itemInState', 'highlighted'); // поверне '.item_state_highlighted'
this._selector('itemById', 5); // поверне '.item[data-id=5]'

А маніпуляція описана вище буде виконуватися наступним чином:
var id = 5,
state = 'highlighted';
this._addClass(['itemInState', state], ['itemById' id]);
Клас item_state_highlighted додасться елементу, знайденому по селектору .item[data-id=5]

Термінальна складність селекторів
_classes: function () {
return {
item: 'item_%(mod)s_%(value)s'
};
}
Кожним місцем своє ім'я
this._elem('item', {
mod: 'state',
value: 'focused'
});
Знайде jQuery колекцію по селектору
'.item_state_focused'


п'ята Проблема: отримання даних
Трошки цукру для дата атрибутів.
this._data;
Зберігає дані кореневого елемента в'ю. Так що якщо у вас є
div

<div data-some-ids="[5,6,7]"></div>
на якому ініціалізована в'ю
this._data['someIds']; // поверне масив [5,6,7]
А якщо дані зберігаються в конкретному елементі, то вам допоможе
this._getElemData('elemName', 'someIds');
Для того, щоб отримати всі дані:
this._getElemData('elemName'); // поверне {someIds: [5,6,7]}


Про установку і використання
GitHub: github.com/backbonex/backbone.view.elements
todomvc з використанням Backbone.View.Elements і без нього

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.