Skip to content
Yet another MVC for i-bem
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.bem
common.blocks
desktop.bundles
tests/specs/common.blocks/i-model
.gitignore
.jscs.json
.jshintignore
.jshintrc
CHANGELOG.md
README.md
package.json

README.md

Yet another MVC for i-bem

Набор 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;
                    }
                }
            }
        }
    }
});

И проверить на валидность

model.isValid();

Биндинги

Для провязывания модели с 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:

You can’t perform that action at this time.