Состояние интерфейса в noscript можно хранить одним из двух основных способов:
- в url, который затем преобразуется в параметры
- в данных модели.
Первый способ является основным и базовым. С его помощью формируется множество адресов сервиса, т.е. его внешний api.
Этот способ обладает следующими особенностями:
- он физически способен вместить очень ограниченное число атрибутов состояния
- при перезагрузке страницы он остаётся неизменным
- каждый атрибут, добавленный в url фактически добавляется во внешний api web-сервиса, что не всегда хорошо.
Эти особенности делают url непригодным для хранения
- атрибутов состояния элементов списка, количество которых может быть произвольным
- атрибутов состояния компонентов, которые должны быть возвращены в начальное состояние при перезагрузке страницы
- атрибутов состояния компонентов, которые не должны управляться извне
- атрибутов сущности, которые касаются только отображения и по смыслу не должны храниться в основной модели.
Для хранения перечисленных и других подобных атрибутов состояния рекомендуется использовать паттерн модель состояния.
Модель состояния - это обычная модель. В простейшем случае она локальная, инициализируется данными на клиенте и никогда не запрашивается с сервера. Она добавляется в зависимость вида, состояние которого она должна хранить. Её значения устанавливаются в runtime в методах видов и других моделях. При перезагрузке страницы модель создаётся заново и состояние сбрасывается.
Если вдруг появилось желание сохранить атрибуты, из моделей состояния, между перезагрузками страницы, никто не мешает сохранить их в любое хранилище (localStorage, сервер) и считывать при загрузке страницы.
В id модели рекомендуется использовать слово state, чтобы явно указать, что эта модель представляет не сущность всего сервиса, а специфическую сущность интерфейса - "состояние компонента".
Пример. Модель состояния элемента списка
ns.Model.define('letters', {
split: {
model_id: 'letter',
items: 'letter',
params: {
id: '.id'
}
}
});
ns.Model.define('letter', {
params: {
id: null
}
});
ns.Model.define('stateLetter', {
events: {
// записываем данные в модель при создании
'ns-model-init': function() {
this.setData({selected: false});
}
},
methods: {
toggleSelected: function() {
if (this.get('.selected')) {
this.set('.selected', false);
} else {
this.set('.selected', true);
}
}
}
params: {
id: null
}
});Определена модель-коллекция letters, которая при загрузке автоматически порождает какое-то количество моделей letter. Опраделена модель stateLetter (состояние письма), которая зависит от тех же параметров, что и letter.
Модель stateLetter инициализирует свои данные при создании.
ns.ViewCollection.define('letters', {
split: {
byModel: 'letters',
intoViews: 'letter'
},
models: ['letters']
});
ns.View.define('letter', {
models: {
'letter': true,
'stateLetter': 'keepValid'
},
events: {
'click .js-select-letter': 'toggleSelected'
},
methods: {
toggleSelected: function() {
this.getModel('stateLetter').toggleSelected();
}
}
});Определён вид-коллекция letters, который по модели letters создаёт внутри себя виды letter.
Каждый вид letter зависит от моделей letter и stateLetter.
При наступлении события click на dom-элементе .js-select-letter срабатывает метод toggleSelected, который изменяет модель состояния.
Если dom-элемент .js-select-letter - checkbox, то при клике перерисовывать вид letter уже не нужно.
Поэтому в зависимости вида letter от модели stateLetter указан метод keepValid, предотвращающий его перерисовку.
Данная конструкция позволяет хранить состояние выделенности неограниченного количества элементов списка между запусками ns.Update. При этом атрибут, относящийся только к списку писем хранится в отдельной модели. Этот атрибут никак не будет влиять на другие виды, зависящие от модели letter.