Как распутывать лапшу, не впадая в депрессию

от автора

Эта статья не про ваши сладкие интерфейсы на реакте, ангуляре или что вы там используете? Это статья про те ситуации, когда у вас есть кучка 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 и без него

ссылка на оригинал статьи http://habrahabr.ru/post/249373/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *