Каков наилучший способ связать / синхронизировать модели представления в Knockout?
Если у вас есть несколько моделей просмотра на одной странице, как вы можете обеспечить их синхронизацию? Например, если добавлен один элемент или нажата кнопка на одной модели представления, и вы хотите, чтобы другая модель представления была чувствительной к этому изменению, может ли Knockout управлять этим изначально или лучше использовать некоторую систему обмена сообщениями или публикацию / подчиненную архитектуру.
Я хочу держаться подальше от необходимости управлять наблюдаемыми между моделями.
4 ответа
Knockout 2.0 включает в себя функциональность, которая позволяет вам делать основные паб / саб Вот пример, где две модели представления взаимодействуют через посредника.
var postbox = new ko.subscribable();
var ViewModelOne = function() {
this.items = ko.observableArray(["one", "two", "three"]);
this.selectedItem = ko.observable();
this.selectedItem.subscribe(function(newValue) {
postbox.notifySubscribers(newValue, "selected");
});
};
var ViewModelTwo = function() {
this.content = ko.observable();
postbox.subscribe(function(newValue) {
this.content(newValue + " content");
}, this, "selected");
};
ko.applyBindings(new ViewModelOne(), document.getElementById("choices"));
ko.applyBindings(new ViewModelTwo(), document.getElementById("content"));
Первая модель представления уведомляет через почтовый ящик о конкретной теме, а вторая модель представления подписывается на эту тему. Они не имеют прямой зависимости друг от друга.
Разумеется, почтовый ящик не обязательно должен быть глобальным и может передаваться в функции конструктора модели представления или просто создаваться внутри самовыполняющейся функции.
Пример: http://jsfiddle.net/rniemeyer/z7KgM/
Так же postbox
может быть просто ko.observable
(который включает в себя ko.subscribable
функции).
Вы, кажется, движетесь к противоречивым целям. В Knockout вы можете сделать это, чтобы создать наблюдаемые объекты, но, похоже, вы этого не хотите.
Если у вас есть объекты Foo и Bar с наблюдаемыми, вы, возможно, не хотите, чтобы наблюдаемые на Foo взаимодействовали с bar или наоборот, но почему бы не иметь виджет, который следит за Foo и Bar и опосредует его?
Я нашел способ синхронизации моделей с помощью библиотеки почтовых ящиков RP Niemeyer
Однако я нашел кое-что интересное в отношении наблюдаемого массива. И именно поэтому я создал новый ответ. Просто чтобы завершить ответ от Нимейера.
При использовании postbox и observableArray события "subscribeTo" и "publishOn" запускаются при добавлении или удалении элемента из observableArray. Он ничего не запускает, когда вы обновляете элемент в массиве. Я думаю, что это не имеет ничего общего с библиотекой почтовых ящиков, но ограничением нокаута.
Если вы пытаетесь получить событие при обновлении элемента наблюдаемого массива, лучше использовать методы "опубликовать" и "подписаться" из библиотеки почтовых ящиков.
Пожалуйста, смотрите следующую FIDDLE
Ссылка на код:
function FundEntity (fund)
{
var self = this;
self.id = fund.id;
self.fundName = fund.fundName;
self.description = fund.description;
self.isFavorite = ko.observable(fund.isFavorite);
}
function GridViewModel(model) {
var self = this;
self.fundList = ko.observableArray();
model.funds.forEach(function(fund) {
self.fundList.push(new FundEntity(fund));
});
self.favorite = function (id, index) {
var newValue = {
id: id,
index: index,
isFavorite: self.fundList()[index].isFavorite()
};
ko.postbox.publish("itemChanged", newValue);
return true;
};
self.isEditable = ko.observable().subscribeTo("myEditableTopic");
}
function FundDetailViewModel(model) {
var self = this;
self.fundList = ko.observableArray();
model.funds.forEach(function(fund) {
self.fundList.push(new FundEntity(fund));
});
ko.postbox.subscribe("itemChanged", function (newValue) {
self.fundList()[newValue.index].isFavorite(newValue.isFavorite);
});
self.editable = ko.observable(false).publishOn("myEditableTopic");
}
Я создал небольшое расширение, чтобы решить эту проблему для моего недавнего проекта. Немного похожа по методологии, но добавляет подписки к публикуемой наблюдаемой напрямую и ставит в очередь подписчиков, если она объявлена до объявления опубликованной наблюдаемой.