Набор i-bem блоков для реализации MVC-паттерна. Предоставляет API для работы с моделями и блоки для автоматического провязывания моделей с интерфейсом.
Требования к моделям
- Декларативный стиль описания моделей
- Доступ к созданным экземплярам моделей по имени и id
- Автоматическое приведение значений полей к заданному типу
- Валидация моделей
Требование к биндингам
- i-bem ориентированность
- Наследование собственной функциональности в использующих i-bem блоках
- Провязка с контролами из bem-controls
Зависимости
Модели
Для использования модели необходимо задекларировать её, указав имя модели и описав поля.
BEM.MODEL.decl('model', { name: 'string', birth: { type: 'string', preprocess: function(value) { return value.year + '.' + value.month + '.' + value.day; } }, height: 'number', weight: 'number' });
Также при декларации можно указать методы модели (переопределение базовых методов модели породит ошибку).
BEM.MODEL.decl('model', { name: 'string', hasBoyfriend: { type: 'boolean', default: false } }, { toggleStatus: function() { this.set('hasBoyfriend', !this.get('hasBoyfriend')); return this; } }); var model = BEM.MODEL.create('model', { name: 'Claudia Schiffer', hasBoyfriend: true }); model.toggleStatus(); model.get('hasBoyfriend'); // false
Типы полей
- string – строка
- number – число
- boolean – булеан
- model – модель
- array – массив произвольных данных
- models-list – список моделей одного типа
Чтобы создать модель, нужно указать имя модели и, если нужно, передать инициализационные параметры
var model = BEM.MODEL.create('model', { name: 'Claudia Schiffer', birth: { year: 1970, month: 8, day: 25 }, weight: 75, height: 180.5 });
В случае, когда отсутствует ссылка на экземпляр модели, ее можно запросить из хранилища, например, по имени
var model = BEM.MODEL.get('model')[0];
Теперь можно устанавливать поля модели
model .set('weight', '80') // будет приведено к number .set('height', 180) .update({ weight: 80, height: 180 });
И получать их значения
model.get('weight'); // 80 model.get('birth'); // '1970.8.25' model.toJSON(); // все поля модели
О изменениях можно узнавать с помощью событий
model.on('weight', 'change', function() { alert('Пора худеть!'); });
Чтобы валидировать модель, нужно задать правила валидации
BEM.MODEL.decl('model-with-validation', { name: 'string', birth: { type: 'string', preprocess: function(value) { return value.year + '.' + value.month + '.' + value.day; } }, height: { type: 'number', validation: { // задать функцию валидации validate: function(value) { return value >= 170; } } }, weight: { type: 'number', validation: { rules: { // или правила валидации: required: true, // стандартное toFat: { // и кастомное needToValidate: function() { // проверить нужно ли выполнять валидацию return this.get('height') > 170; }, validate: function(value) { return value <= 90; } } } } } });
И проверить на валидность
Биндинги
Для провязывания модели с DOM-представлением используется блок i-glue. Блок которой "проклеивает" модель и DOM. Для того, чтобы провязать модель с каким либо контролом, необходимо на родительский блок примешать блок i-glue, а на контрол элемент model-field блока i-glue и указать им параметры модели. BEMJSON в таком случае будет выглядеть так:
{ block: 'b-model', mix: [{ block: 'i-glue', // примешиваем блок i-glue js: { modelName: 'model', // указываем имя модели modelData: { name: 'Claudia Schiffer', // и данные weight: 75, height: 180.5 } } }], content: [ ... { block: 'input', mix: [{ // на поле ввода примешиваем элемент model-field block: 'i-glue', elem: 'model-field', js: { name: 'weight', // указываем ему с каким полем провязываться type: 'input' } }], name: 'weight', value: '75', mods: { size: 's' }, content: { elem: 'control' } } ... ] }
После инициализации будет создана модель, с указанными данным. И изменения в поле ввода, будут автоматически отражаться в модели (и наоборот).
Типы биндингов (модификаторы model-field)
- input – провязка с блоком input
- select – провязка с блоком select
- checkbox – провязка с блоком checkbox
- inline – вставка значения поля в html
- mod – изменение модификатора блока
Агрегация моделей
Иногда создание моделей с помощью блока i-glue может быть неудобной. Для случая, когда данные для модели генерируются во время шаблонизации, можно использовать блок i-model.
{ block: 'i-model', modelName: 'super-model', modelData: { name: 'Claudia Schiffer', weight: 75, height: 180.5 } } // или { block: 'i-model', modelParams: { name: 'super-model', data: { name: 'Claudia Schiffer', weight: 75, height: 180.5 } } }
В таком случае в DOM'е появится столько элементов, сколько в конечном bemjson'е блоков i-model. Чтобы избежать засорения DOM'а вспомогательными объектам, можно любой контент обернуть в блок i-model-aggregator
{ block: 'i-model-aggregator', content: [ { block: 'i-model', modelName: 'model1' }, { block: 'view-block', content: [ { block: 'i-model', modelName: 'model2' } ] }, { block: 'i-model', modelName: 'model3' } ] }
В итоге все блоки i-model внутри агрегатора будут объединены в один и модели будут проинициализированы до инициализации других блоков.
Unit-тестирование
В консоли
Тесты располагаются в директории tests/specs согласно файловой структуре.
Запуск npm test
В браузере
Тесты располагаются в файлах *.test.js.
Запуск bem server
Открыть страницу localhost:8080/desktop.bundles/tests/tests.html
Lint
Запуск npm run lint
Ссылки
JS Docs: