使用了Yeoman的Knockout生成器(2015年初,c .a。),其中包括require.js和router.js。只需使用KO的装载机。
我试图在组件" a"中调用一个函数(ko.observable与否)。 来自 组件" b"。 下面的所有绒毛都试图做:
// In componentB:
ComponentA.sayFoo();
阅读关于组件和加载器的KO文档,黑客攻击了几个小时等等。我不想要 postal.js 的开销 - 而且也无法获得订阅(KO pub / sub) )工作 - 我猜是出于同样的原因:以这种方式设置的视图模型没有相互引用(?) - 因此一个模块中的订阅者不会在另一个模块中看到发布者(右) ?)(......我头脑中有点% - )
1)这是因为模块没有看到对方......这个生成的代码没有将KO内容放在全局命名空间中吗?
2)尝试从一个模块到另一个模块,似乎取决于通过回调参数获取参考,使用下面的功能,还是不正确? :
ko.components.get (name, callback) ;
使用require的startup.js 如下所示:
define(['jquery', 'knockout', './router', 'bootstrap', 'knockout-projections'], function($, ko, router) {
// Components can be packaged as AMD modules, such as the following:
ko.components.register('component-a', { require: 'components/a/component-a' });
ko.components.register('component-b', { require: 'components/b/component-b' });
// [Scaffolded component registrations will be inserted here. To retain this feature, don't remove this comment.]
// [Scaffold component's N/A (I think?)]
// Start the application
ko.applyBindings({ route: router.currentRoute });
});
(组件)模块 A是直截了当的,如下所示:
define(['knockout', 'text!./component-a'], function(ko, templateMarkup) {
function ComponentA (params) { console.log ('CompA'); } ;
ComponentA.prototype.sayFoo = function () { console.log ('FOO!'); } ;
ComponentA.prototype.dispose = function(){};
return { viewModel: ComponentA, template: templateMarkup };
});
同样,模块 B 是:
define(['knockout', 'text!./component-b'], function(ko, templateMarkup) {
function ComponentB (params) { console.log ('Compb'); } ;
ComponentB.prototype.doFoo = function () {
//// B Needs to fire ComponentA.foo() … SEE CODE ATTEMPT BELOW
};
ComponentB.prototype.dispose = function(){};
return { viewModel: ComponentB, template: templateMarkup };
});
所以这就是我被困的地方:
ComponentB.prototype.doFoo = function () {
ko.components.get ('component-a', ( function (parms) {
console.log ('parms.viewModel : ' + parms.viewModel );
// parms.viewModel is (unexpectedly) undefined ! So how to get the ref?
console.log ('parms.template : ' + parms.template );
// does have expected html objects, eg. [object HTMLwhatever], [object HTML...]
})) ;
这应该很容易,或者我愚蠢地遗漏了一些明显的东西!?
可能需要以不同的方式定义/设置模块吗?
任何建议都会有所帮助! THX
答案 0 :(得分:2)
这不是你在淘汰赛组件之间正常沟通的方式。
您的选择是:
1)使用https://github.com/rniemeyer/knockout-postbox。这可能是最好的选择,因为它与淘汰赛很好地融为一体。它有详细记录,如果你设置麻烦,你可以随时寻求帮助。
2)使用任何其他全局javascript EventBus(f.i。postal.js
)并发出/订阅组件中的事件。
3)让你的根ViewModel将公共observable传递给每个组件作为参数 - 这样每个组件都可以修改/订阅相同的observable。
4)(可能你想要的,尽管是最差的扩展解决方案)如果你给不同组件的id,你可以使用ko.dataFor(document.getElementById("id"))
直接访问组件的属性和方法。
编辑:回应评论:
我没有 能够确定根视图模型的位置/位置: ko.applyBindings({route:router.currentRoute})是线索,但是 router.js是错综复杂的。关于如何确定的建议?
确实 - 在您的情况下,{ route: router.currentRoute }
对象是您的根ViewModel。它目前只有一个名为route
的属性,但你绝对可以扩展它。
例如:
var rootViewModel = {
route: router.currentRoute,
mySharedObservable: ko.observable('hi!')
}
ko.applyBindings(rootViewModel);
然后你可以将这个observable作为参数传递给多个组件:
<div id="component-a" data-bind="component: { name: 'component-a', params: {router: $root.router, mySharedObservable: $root.mySharedObservable} }"></div>
<div id="component-b" data-bind="component: { name: 'component-b', params: {router: $root.router, mySharedObservable: $root.mySharedObservable} }"></div>
最后,您可以在组件中使用新的observable,如下所示:
function ComponentB (params) {
this.mySharedObservable = params && params.mySharedObservable;
console.log(this.mySharedObservable());// This should log 'hi!'
};
您现在可以订阅observable,更改它等等。它将在组件之间共享,因此将其更改为一个组件将触发所有组件中的订阅。
答案 1 :(得分:1)
我的标准方法是通过父虚拟机控制通信。
父虚拟机可以创建一个可订阅的[1],并将其作为参数传递给componentA和componentB;然后ComponentA可以订阅可订阅的,而ComponentB可以触发可订阅的。
//ComponentA
function ComponentA (params) {
var shouldSayFoo = params.shouldSayFoo;
this.shouldSayFooSubscription = shouldSayFoo.subscribe(function () {
this.sayFoo();
});
} ;
ComponentA.prototype.sayFoo = function () { console.log ('FOO!'); } ;
ComponentA.prototype.dispose = function () { this.shouldSayFooSubscription.dispose(); };
//In ComponentB
function ComponentB (params) {
this._triggerFoo = params.triggerFoo; //Same subscribable as shouldSayFoo in ComponentA
}
ComponentB.prototype.doFoo = function () {
this._triggerFoo.notifySubscribers(); //notifySubscribers triggers any .subscription callbacks
}
如果ComponentA和ComponentB是兄弟姐妹并且你不是一直都在做这种事情,那么这就是一个非常简单的解决方案。如果组件是“远房亲戚”或者如果你发现自己做了很多,那么我会建议某种pub-sub。这种方法的一个优点是可以被许多单独的“A-B”对使用而不会相互干扰,这对于pub-sub系统来说更难。
[1]:ko.subscribable
是一个具有可观察功能子集的对象(ko.observable
继承自ko.subscribable
):它不允许您读取或写入值,但是允许您执行.subscribe
和.notifySubscribers
。 (由于某种原因,它们是用new
创建的。你也可以使用一个observable,如果你不打算保留一个值,那么创建一个observable的意图就会略微混淆。