我的Knockout应用程序由代表表单不同部分的不同组件组成 - 所以我有一个"语言"组件,a"国家"组件,a"标签"组件等。在每个组件中,我都有一个可观察的数组,我订阅并通过ko.postbox.notifySubscribers在这些可观察量发生变化时发送通知。在另一个名为filters的组件中,它充当用户在表单中选择的所有过滤器的收集器,我通过ko.postbox.subscribe接收这些observable中的更改。
我的问题是:如果我想在过滤器组件中进行更改并将它们反映在其他组件中,该怎么办?也就是说,如何在双向对话中改变这种单向对话?
例如,在语言组件中,我有一个下拉菜单,用户选择语言。在过滤器菜单中,我有所选语言的列表(复选框),我希望用户能够从这里取消选择项目,同时仍然更新主要组件中的下拉列表。
发布语言组件和过滤器组件的代码, 感谢
Languages.js
ko.components.register("languages",{
viewModel: function(){
var self = this;
self.languages = ko.observableArray();
self.selectedLangs = ko.observableArray();
xhr.languages()
.done(function (langs) {
self.languages(langs);
});
self.selectedLangs.subscribe(function(values) {
ko.postbox.notifySubscribers(
_.map(values,function(val){
var obj = _.findWhere(self.languages(), {id: val});
return obj.text;
}), "selectedLangs");
});
},
template:
'<fieldset id="language" class="wfp-u-1">\
<div class="wfp-grid">\
<label for="dss-language" class="wfp-u-1 wfp-u-lg-1-4">\
Language <span class="loader"><i class="icon-loader"></i></span>\
<em>Multiselection available</em>\
</label>\
<select id="dss-language" name="language" multiple="" class="wfp-u-1 wfp-u-lg-3-4 ui dropdown search selection"\
data-bind="\
options: languages,\
optionsText: \'text\',\
optionsValue: \'id\',\
optionsCaption: \'Select one or more languages\',\
selectedOptions: selectedLangs\">\
</select>\
</div>\
</fieldset>'
});
Filters.js
ko.components.register("filters",{
viewModel: function(){
var self = this;
self.selectedLangs = ko.observableArray();
ko.postbox.subscribe(function(langs) {
self.selectedLangs(langs);
}, self, "selectedLangs");
},
template:
'<ul class="wfpList wfpFieldList mCustomScrollbar">\
<li>\
<a data-target="language">Language</a><i class="ico-angle-down"></i>\
<!-- ko foreach: selectedLangs -->\
<span data-bind="text: $data"></span>\
<!-- /ko -->\
</li>\
</ul>'
});
答案 0 :(得分:1)
复制John Papa的回答(https://stackoverflow.com/a/10818849/1287183):
一个选项是创建一个隔离的datacontext来维护可观察的模型。 viewmodels都会查看datacontext的数据并引用相同的对象,所以当一个更新时,它们都会这样做。 VM的依赖关系在datacontext上,但不在其他VM上。我最近一直这样做,而且运作良好。