Эта статья не про ваши сладкие интерфейсы на реакте, ангуляре или что вы там используете? Это статья про те ситуации, когда у вас есть кучка jQuery лапши. Нет, пусть это будут горы jQuery лапши, завернутой во вьюшки бэкбона.
В статье используется библиотека Backbone.View.Elements
Все мы видели лапшу, все мы знаем: лапша в JSе — наверно и в верстке не все хорошо. А раз все так, то код, скорее всего, кишит непонятными манипуляциями с домом. Читать такой код сложно, ведь надо, не упуская мысли автора о том, что здесь вообще происходит, держать в уме кучку невнятных названий для элементов. Итак, давайте придадим коду немножко выразительности:
В нашем случае вы можете сказать, что это мало добавило выразительности, но не забывайте, что у вас, скорее всего, не проект, использующий БЭМ для именования классов, а сладко пахнущие сверх семантичные селекторы вида
Помимо возможности выбрать элемент внутри нашей вьюшки, мы также получили возможность получить сам селектор по имени:
Еще одно преимущество — если изменит��я верстка, то нам надо будет изменить селектор только в одном месте, потому что мы уменьшили дублирование кода.
Знаете, бывает вот так:
Отодрав ладонь от лица, вы вынесете это в переменную
На самом деле не стоит —
Да, мы тоже слышали, что в программировании две проблемы. Поэтому
А еще мы завернули в jQuery наиболее часто используемые элементы, чтобы не делать это больше одного раза в приложении. Встречайте:
Вроде бы целый язык есть, чтобы стили описывать, но нет — то и дело в лапше можно найти красители:
Можно получить селектор, если класс уже описан:
Бывает, селекторы и классы формируются динамически:
А манипуляция описанная выше будет выполняться следующим образом:
Немножко сахара для дата атрибутов.
GitHub: github.com/backbonex/backbone.view.elements
todomvc с использованием Backbone.View.Elements и без него
В статье используется библиотека 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');
Еще одно преимущество — если изменит��я верстка, то нам надо будет изменить селектор только в одном месте, потому что мы уменьшили дублирование кода.
Проблема вторая: хранение элементов
Знаете, бывает вот так:
а через 10 строк вот так:$(‘div > tr.row[data-active=”true”] a.red-Button’).blahBlah();
$(‘div > tr.row[data-active=”true”] a.red-Button’).anotherBlahBlah();
Отодрав ладонь от лица, вы вынесете это в переменную
ой нет, у вас же Backbone — вынесете в свойствоvar $buyButton = $(‘div > tr.row[data-active=”true”] a.red-Button’);
или вы уже подключили Backbone.View.Elements?this._$buyButton = this.$(‘div > tr.row[data-active=”true”] a.red-Button’);
this._$buyButton = this._elem(‘buyButton’);
На самом деле не стоит —
_elem и так все кеширует, так что простоthis._elem(‘buyButton’);
Кеширует, говорите? А что, если все изменится?
Да, мы тоже слышали, что в программировании две проблемы. Поэтому
ищет без использования кешаthis._findElem('elemName');
почистит кеш для конкретного элемента, аthis._dropElemCache(‘elemName’);
отчистит весь ваш кеш до блеска, когда вы поймете, что время пришло. Например, после рендеринга.this._dropElemCache();
Глобальные элементы
А еще мы завернули в jQuery наиболее часто используемые элементы, чтобы не делать это больше одного раза в приложении. Встречайте:
this._$window; this._$body; this._$document;
Проблема третья: императивные стили
Вроде бы целый язык есть, чтобы стили описывать, но нет — то и дело в лапше можно найти красители:
Скорее поперчите все декларативностью и хорошенько перемешайте CSS:$(‘div > tr.row[data-active=”true”] a.red-Button’).css({color: ‘magenta’});
А уж об манипуляции классами мы позаботились. Сначала обозначим все классы в одном месте:.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]’
А манипуляция описанная выше будет выполняться следующим образом:
Класс item_state_highlighted добавится элементу, найденному по селектору .item[data-id=5]var id = 5, state = ‘highlighted’; this._addClass([‘itemInState’, state], [‘itemById’, id]);
Терминальная сложность селекторов
Каждому месту свое имя_classes: function () { return { item: 'item_%(mod)s_%(value)s' }; }
Найдет jQuery коллекцию по селекторуthis._elem(‘item’, { mod: ‘state’, value: ‘focused’ });
‘.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 и без него
