Skip to content

bem/bem-mvc

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 
 
 
 
 
 
 

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:

About

Yet another MVC for i-bem

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published