Javascript Knockout.js-组件之间的发布/订阅,双向对话

Javascript Knockout.js-组件之间的发布/订阅,双向对话,javascript,knockout.js,Javascript,Knockout.js,我的淘汰应用程序由代表表单不同部分的不同组件组成,因此我有一个“语言”组件、“国家”组件、“标签”组件等等。在每一个组件中,我都有一个可观察数组,我可以订阅该数组,并在这些可观察数组发生变化时通过ko.postbox.notifySubscribers发送通知。在另一个名为filters的组件中,它作为用户在表单中选择的所有过滤器的收集器,我通过ko.postbox.subscribe接收这些观察值中的更改 我的问题是:如果我想在过滤器组件中进行更改,并让它们也反映在其他组件中,该怎么办?也就是

我的淘汰应用程序由代表表单不同部分的不同组件组成,因此我有一个“语言”组件、“国家”组件、“标签”组件等等。在每一个组件中,我都有一个可观察数组,我可以订阅该数组,并在这些可观察数组发生变化时通过ko.postbox.notifySubscribers发送通知。在另一个名为filters的组件中,它作为用户在表单中选择的所有过滤器的收集器,我通过ko.postbox.subscribe接收这些观察值中的更改

我的问题是:如果我想在过滤器组件中进行更改,并让它们也反映在其他组件中,该怎么办?也就是说,如何将这种单向对话转换为双向对话

例如,在语言组件中,我有一个下拉菜单,用户可以选择语言。在filters菜单中,我有一个包含所选语言(复选框)的列表,我希望用户能够在这里取消选择项目,同时仍然更新主组件中的下拉列表

语言组件和过滤器组件的过帐代码, 谢谢

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>'
});
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>'
});
ko.components.register(“语言”),{
viewModel:function(){
var self=这个;
self.languages=ko.observearray();
self.selectedLangs=ko.observableArray();
xhr.languages()
.完成(功能(LAGS){
自我语言;
}); 
self.selectedLangs.subscribe(函数(值)){
ko.postbox.com(
_.map(值、函数(val){
var obj=uu.findWhere(self.languages(),{id:val});
返回obj.text;
}),“选定语言”);
});
},
模板:
'\
\
\
语言\
多选可用\
\
\
\
\
'
});
Filters.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>'
});
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>'
});
ko.components.register(“过滤器”,{
viewModel:function(){
var self=这个;
self.selectedLangs=ko.observableArray();
ko.postbox.subscribe(函数(langs){
自我选择语言(langs);
},self,“selectedLangs”);
},
模板:
“
    \
  • \ 语言\ \ \ \
  • \
' });
复制约翰·帕帕的答案():

一个选项是创建一个独立的datacontext来维护可观察对象的模型。viewmodels都会在datacontext中查找数据,并引用相同的对象,因此当更新时,它们都会这样做。VM依赖于datacontext,但不依赖于其他VM。我最近一直在这样做,效果很好


我看你只需要另一个酒吧/子频道来处理反向变化。哦,天哪,那容易吗?我以为会有其他更干净的方法来处理它-我真的不想用邮箱填充代码。。。但在这种情况下,我不得不这么做。谢谢Michael。另一种选择是不让任何一个组件“拥有”所选语言的数据,而是向两个组件提供相同的可观察数据。这样,它们总是同步的。这个问题与我不久前问的问题类似:。我想你会发现这些答案很有用。选择“全局”
selectedLangs
可观察实际上是我的首选……我还将看看另一个问题,谢谢Michael。嗨,Michael,谢谢你指出这一点。这绝对是我将要遵循的方式,因为对于我必须做的事情和组件之间的交互级别,它比我以前实现的pub/sub要干净得多。