我目前正在使用Backbone.Mediator在Backbone + RequireJS项目中利用Mediator Pattern的好处;但是,我遇到了Pattern的特殊行为,不能确定它是“按设计”生成的,还是不确定Mediator Pattern的标准行为,而是插件中的错误。
举一个人为的例子:
AMD模块1
var View1 = Backbone.View.extend({
...
events: {
'click div: switchList'
},
switchList: function() {
Backbone.Mediator.pub('list:switch');
}
});
AMD模块2
var View2 = Backbone.View.extend({
...
subscriptions: {
'list:switch': 'shrinkDiv'
},
shrinkDiv: function() {
Backbone.Mediator.pub('div:shrink');
this.shrinkAndMore();
}
});
return View2;
AMD模块3
define(function(require) {
var View2 = require(**AMD Module 2**);
var View3 = Backbone.View.extend({
...
subscriptions: {
'div:shrink': 'createSiblingDiv'
},
createSiblingDiv: function() {
this.siblingView = new View2();
this.$el.after(this.siblingView.$el);
this.siblingView.render();
}
});
});
我认为它会像这样工作:
**View1**.switchList();
│
Channel 'list:switch' │
↓
**View2**.shrinkDiv();
│
├─┐
│ │ Channel 'div:shrink'
│ ↓
│ **View3**.createSiblingDiv();
│ │
│ └──→ "SiblingDiv created and rendered"
│
└────→ "View2 Div shrinked and more"
但是,事实是,因为
SiblingDiv
是 View2 的另一个实例,它订阅了 channel “list:switch”,所以SiblingDiv
在创建后立即也会由仍然在 channel “list:switch”上发生的事件信号触发(只会在**View2**.shrinkAndMore();
执行之后停止。因此,实际的代码流如下所示:
**View1**.switchList();
│
Channel 'list:switch' │
↓
**View2**.shrinkDiv(); ←──────────────────┐
│ │
├─┐ │
│ │ Channel 'div:shrink' │
│ ↓ │
│ **View3**.createSiblingDiv(); │
│ │ │
│ └──→ "SiblingDiv created and rendered" ─┘
│
└────→ "View2 Div shrinked and more"
无限循环...糟糕!
通过对代码进行一些修改,我可以使事情正常进行:
AMD模块2修改后的
var View2 = Backbone.View.extend({
initialize: function() { // new code
if (this.options.subscriptions) { // new code
this.subscriptions = this.options.subscriptions; // new code
} // new code
}, // new code
...
subscriptions: {
'list:switch': 'shrinkDiv'
},
shrinkDiv: function() {
Backbone.Mediator.pub('div:shrink');
this.shrinkAndMore();
}
});
return View2;
AMD模块3修改后的
define(function(require) {
var View2 = require(**AMD Module 2**);
var View3 = Backbone.View.extend({
...
subscriptions: {
'div:shrink': 'createSiblingDiv'
},
createSiblingDiv: function() {
this.siblingView = new View2({ // new code
subscriptions: {} // new code
}); // new code
this.$el.after(this.siblingView.$el);
this.siblingView.render();
}
});
});
但是,我很感兴趣地了解,在Mediator Pattern方法中,是否将无限循环行为(在期间在事件信号广播中创建的新对象也会触发该信号)视为“标准”?还是这仅仅是插件部分的错误?
最佳答案
似乎这是插件中的错误。看一看this line。它将遍历此 channel 中注册的所有事件。问题在于,它会在调用每个已注册事件时停止,并且会在每个循环步骤中检查已注册事件数组的长度。所以发生的是:
将行更改为:
for (var i = 0, l = channels[channel].length; i < l; i++) {
应该可以解决此问题,因为您可以从一开始就获得数组的长度。添加新元素不会在无限循环中结束。