Durandal - 跨视图模型共享可观察对象

时间:2015-02-26 20:25:20

标签: javascript knockout.js durandal

我正在尝试在viewmodelB

中更新viewmodel的可观察对象

这是viewmodel A:

define(['knockout'], function(ko) {
 return {
  title: ko.observable('')
 }
})

和viewmodel B:

define(['knockout', 'viewmodelA'], function(ko, viewmodelA) {
 function vm() {

  this.changeName = function() {
   viewmodelA.title('test')
  }

}

return vm

})

在viewmodelA html中,有一个<p data-bind="text: title"></p>标记,changeName函数被挂钩到viewmodelB的html上的点击绑定。

但是,当我执行changeName函数时,viewmodelA.title()observable确实改变了它的值,但是html没有更新。

我错过了什么?

1 个答案:

答案 0 :(得分:3)

在视图之间进行通信时,最好不要将一个视图注入另一个视图,以免将一个视图紧密耦合到另一个视图并锁定应用程序的其他部分。

Durandal附带了一个pub / sub功能。只需要'durandal / app',然后分别使用app.trigger()app.on()发布和订阅。

viewmodelA.js 中,我们会有以下内容:

define(['durandal/app', 'knockout'], function(app, ko) {
    var          
        title = ko.observable(''),
        compositionComplete = function () {
            app.on('title:changed').then( function(aTitle) {
                title(aTitle);
            });
        },
        detached = function () {
            app.off('title:changed');
        };

    return {
        compositionComplete: compositionComplete,
        detached: detached,
        title: title
    }
});

viewmodelB.js 中,我们会:

define(['durandal/app', 'knockout'], function(app, ko) {
    var             
        changeTitle = function (aTitle) {
            app.trigger('title:changed', aTitle);
        };

    return {
        changeTitle: changeTitle
    }
});

我正在使用单身模式,以及揭示模块模式,将成员暴露给外界。

基本上,正在发生的事情是,只要在changeTitle中使用新标题(作为字符串)作为参数调用viewmodelB,它就会将更改广播为全局事件,并将新标题作为有效载荷。反过来,viewmodelA通过订阅该全局事件表达了对'title:changed'事件的兴趣,然后通过更改标题进行响应。

要对此进行测试,您只需要一个小的测试工具(可能是您点击的按钮,或者您现在甚至可以对测试值进行硬编码)来调用changeTitleviewmodelB的有效负载带有代表新标题的字符串。

通过采用上述方法,您完全将视图分离,允许其他视图或应用程序的某些部分响应'title:changed'事件。

如果您需要比Durandal的pub / sub更细粒度的控制,您可以随时使用PostalJS,它是AMQP风格的全面客户端消息总线。这就是我们使用的。