this.model.on 更改事件未触发
this.model.on change event not firing
"change" 事件未在以下代码中触发。
var PageView = Backbone.View.extend({
el: $("body"),
initialize: function(){
this.model.on("change:loading", this.loader, this);
},
loader: function(){
if(this.model.get("loading")){
this.$el.find('.loader').fadeIn(700);
}
else
this.$el.find('.loader').fadeOut(700);
},
});
var PageModel = Backbone.Model.extend({
defaults: {
loading: null,
},
initialize: function(){
this.set({loading:false});
},
});
$(function(){
var pageModel = new PageModel({});
var pageView = new PageView({model: pageModel});
})
如果我在模型的 initialize
函数中添加它,它会起作用:
setTimeout(function() {
this.set({'loading': 'false'});
}, 0);
我可以这样保留,但这是一个错误。
情况说明
代码运行顺序如下:
- 模型已创建,
- 模型的
initialize
函数被调用,设置loading
属性为false
,
- 然后模型传递给视图,
- 然后为
"change:loading"
注册一个监听器
永远不会调用事件处理程序,因为事件在注册后永远不会发生。
快速修复
首先从模型中删除集合。
var PageModel = Backbone.Model.extend({
defaults: {
loading: null
}
});
然后,在创建视图后,设置 loading
属性。
var pageModel = new PageModel();
var pageView = new PageView({ model: pageModel });
pageModel.set('loading', false); // now the event should trigger
由于侦听器现在是在模型的 loading
属性更改之前注册的,因此将调用事件处理程序。
优化方案
使用 Backbone 的最佳实践:
- Favor
.listenTo
over .on
避免内存泄漏
视图是一个原子组件,应该只关心它自己和它的子视图。
虽然在您的情况下,在视图上使用 el
属性 并不重要,但它仍然超出了视图的职责范围。让调用代码处理传递用于此视图的元素。
var PageView = Backbone.View.extend({
initialize: function() {
this.model = new PageModel();
this.$loader = this.$('.loader');
this.listenTo(this.model, "change:loading", this.loader);
},
loader: function() {
this.$loader[this.model.get("loading")? 'fadeIn': 'fadeOut'](700);
},
render: function() {
this.loader();
return this;
}
});
将默认值放在它们所属的地方。
var PageModel = Backbone.Model.extend({
defaults: {
loading: false
}
});
这里我们选择 body
作为用于视图的元素,使用 el
选项,然后在准备就绪时调用 render
。
$(function() {
var pageView = new PageView({ el: 'body' }).render();
});
侦听器不会立即触发事件,相反,我们使用 render
函数将视图置于默认状态。然后,loading
属性的任何后续更改都将触发回调。
我在个人资料页面上列出了 most useful answers I've written about Backbone。您应该看一看,它从入门到高级,甚至提供了一些聪明的 Backbone 组件来解决常见问题(例如检测点击 外部 视图)。
"change" 事件未在以下代码中触发。
var PageView = Backbone.View.extend({
el: $("body"),
initialize: function(){
this.model.on("change:loading", this.loader, this);
},
loader: function(){
if(this.model.get("loading")){
this.$el.find('.loader').fadeIn(700);
}
else
this.$el.find('.loader').fadeOut(700);
},
});
var PageModel = Backbone.Model.extend({
defaults: {
loading: null,
},
initialize: function(){
this.set({loading:false});
},
});
$(function(){
var pageModel = new PageModel({});
var pageView = new PageView({model: pageModel});
})
如果我在模型的 initialize
函数中添加它,它会起作用:
setTimeout(function() {
this.set({'loading': 'false'});
}, 0);
我可以这样保留,但这是一个错误。
情况说明
代码运行顺序如下:
- 模型已创建,
- 模型的
initialize
函数被调用,设置loading
属性为false
, - 然后模型传递给视图,
- 然后为
"change:loading"
注册一个监听器
永远不会调用事件处理程序,因为事件在注册后永远不会发生。
快速修复
首先从模型中删除集合。
var PageModel = Backbone.Model.extend({
defaults: {
loading: null
}
});
然后,在创建视图后,设置 loading
属性。
var pageModel = new PageModel();
var pageView = new PageView({ model: pageModel });
pageModel.set('loading', false); // now the event should trigger
由于侦听器现在是在模型的 loading
属性更改之前注册的,因此将调用事件处理程序。
优化方案
使用 Backbone 的最佳实践:
- Favor
.listenTo
over.on
避免内存泄漏
视图是一个原子组件,应该只关心它自己和它的子视图。
虽然在您的情况下,在视图上使用 el
属性 并不重要,但它仍然超出了视图的职责范围。让调用代码处理传递用于此视图的元素。
var PageView = Backbone.View.extend({
initialize: function() {
this.model = new PageModel();
this.$loader = this.$('.loader');
this.listenTo(this.model, "change:loading", this.loader);
},
loader: function() {
this.$loader[this.model.get("loading")? 'fadeIn': 'fadeOut'](700);
},
render: function() {
this.loader();
return this;
}
});
将默认值放在它们所属的地方。
var PageModel = Backbone.Model.extend({
defaults: {
loading: false
}
});
这里我们选择 body
作为用于视图的元素,使用 el
选项,然后在准备就绪时调用 render
。
$(function() {
var pageView = new PageView({ el: 'body' }).render();
});
侦听器不会立即触发事件,相反,我们使用 render
函数将视图置于默认状态。然后,loading
属性的任何后续更改都将触发回调。
我在个人资料页面上列出了 most useful answers I've written about Backbone。您应该看一看,它从入门到高级,甚至提供了一些聪明的 Backbone 组件来解决常见问题(例如检测点击 外部 视图)。