Быстрый вопрос:
Предоставит ли KnockoutJS прочную основу для разработки большого веб-приложения?Я боюсь иметь одну огромную модель представления, которая станет неуправляемой.
Справочная информация
Я буду создавать веб-приложение, которое будет в значительной степени основано на стороне клиента.Серверная часть будет просто конечной точкой RESTful.Весь интерфейс веб-приложения будет построен на чистом HTML / CSS / JS - без участия сценариев на стороне сервера.
Само веб-приложение будет состоять из нескольких небольших приложений с одним общим логином (вроде веб-приложений Google, где у вас есть Gmail, Документы, Календарь, Reader и т. Д.).
Каждое из этих веб-приложений будет обладать некоторыми общими функциями (такими как представление дерева боковой панели, представление меню верхней панели, система уведомлений) и некоторыми уникальными функциями приложения.Обычно я разбиваю свои приложения на инкапсулирующие функциональные возможности, например:
var myNamespace = {
common: {
settings: {},
user: {},
notifications: {}
},
app1: {},
app2: {},
app3: {}
};
Теперь мне действительно нравится работать с KnockoutJS, и я подумал, что это будет полезно при создании некоторых элементов моего проекта (таких как система уведомлений).или расширенный вид сетки с автоматическим обновлением, поскольку приложение будет поддерживать совместную работу).Но я просто не могу понять, куда поместить мою viewModel в эту структуру.
Я могу найти только тривиальные примеры того, как создавать приложения с KnockoutJS. Можете ли вы на самом деле создать что-то более продвинутое, чем читатель Twitter? Есть ли хорошие примеры того, как разбить множество функций в viewModel или, возможно, на многие viewModels?
Предлагаемое решение
Хотя более теоретический вопрос (Быстрый вопрос) все еще остается здесь без ответа, я думаю, что я нашел решение, которое работает на практике.Ответ @Simon дал мне пищу для размышлений, и вот что у меня так далеко:
// First: a collection of Observables that I want to share
ld.collectionOfObservables = {
notifications: ko.observableArray([]),
};
// Now let's define a viewModel. I put all my stuff inside the
// 'ld' namespace to avoid cluttering the global object.
ld.viewModel1 = function (args) {
// Look inside args and bind all given parameters
// Normally you will want args to be an object of Observables.
for (var key in args) {
if (args.hasOwnProperty(key)) {
this[key] = args[key];
}
};
// So, by now we already have some observables in
// 'this', if there were any supplied in 'args'.
// Additionally, we define some model-unique properties/observables
this.folders = [ 'Inbox', 'Archive', 'Sent', 'Spam' ];
this.selectedFolder = ko.observable('Inbox');
};
// *** Let's pretend I create similar class and call it ld.viewModel2 ***
ld.viewModel2 = function (args) { .... }
// OK, now go on and instantiate our viewModels!
// This is the fun part: we can provide 0-many observables here, by providing them in an object
// This way we can share observables among viewModels by simply suppling the same observables to different viewModels
var vm1 = new ld.viewModel1({
notifications: ld.collectionOfObservables.notifications, // we take an Observable that was defined in the collection
});
var vm2 = new ld.viewModel2({
notifications: ld.collectionOfObservables.notifications, // shared with vm1
});
// Of course, we could just send the entire ld.collectionOfObservables as an array
// but I wanted to show that you can be more flexible and chose what to share.
// Not easy to illustrate with *one* shared Observable - notifications -
// but I hope you get the point. :)
// Finally, initiate the new viewModels in a specified scope
ko.applyBindings(vm1, document.getElementById('leftPane'));
ko.applyBindings(vm2, document.getElementById('bottomPane'));
Теперь, если бы у JS было настоящее наследство, это было бы еще лучше, потому что сейчас я чувствую, чтовсе мои viewModels начинаются с этого:
for (var key in args) {
if (args.hasOwnProperty(key)) {
this[key] = args[key];
}
};
Но это всего лишь небольшое неудобство.Дайте мне знать, что вы думаете!
Edit 1: Может ли решение быть таким же простым, как использование привязки with:
?См. " 1. Привязки потока управления " для примера.
Редактировать 2: Я думаю, что мое последнее редактирование было слишком быстрым.with:
привязка может помочь со структурой вашего кода, но AFAIK не поможет вам разделить наблюдаемые между этими различными частями.Таким образом, предложенное выше решение по-прежнему остается верным.