我正在尝试在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没有更新。
我错过了什么?
答案 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'事件的兴趣,然后通过更改标题进行响应。
要对此进行测试,您只需要一个小的测试工具(可能是您点击的按钮,或者您现在甚至可以对测试值进行硬编码)来调用changeTitle
中viewmodelB
的有效负载带有代表新标题的字符串。
通过采用上述方法,您完全将视图分离,和允许其他视图或应用程序的某些部分响应'title:changed'事件。
如果您需要比Durandal的pub / sub更细粒度的控制,您可以随时使用PostalJS,它是AMQP风格的全面客户端消息总线。这就是我们使用的。