(重新)呈现更改事件处理程序中的 Backbone 视图不起作用
(Re)rendering Backbone view in change event handler does not work
我有两个表单元素,都通过 backbone.stickit 双向数据绑定。
第二个表单元素 (#input) 只是装饰品 - 用于显示它确实有效。
我的想法是,每次下拉菜单中的选项(#select)更改时,我的视图都会(重新)呈现。
我试图通过捕获#select 的 'changed' 事件并调用 this.render() 来(重新)渲染视图来实现这一点。
显然这不起作用。 selected 选项没有保存回模型中,我不明白为什么。
我不是在寻找解决方案,而是解释,为什么以下代码不起作用。解决方案(如:对我有用)是 fiddle 的一部分 - 已注释掉。
HTML:
<script type="text/template" id="tpl">
<h1>Hello <%= select %></h1>
<select id="select">
</select>
<p>Select:
<%= select %>
</p>
<hr>
<input type="text" id="input">
<p>Input:
<%= input %>
</p>
</script>
<div id="ctr"></div>
JavaScript:
Foo = Backbone.Model.extend({
defaults: {
select: "",
input: "",
}
});
FooView = Backbone.View.extend({
el: '#ctr',
template: _.template($('#tpl').html()),
initialize() {
this.model.bind('change', function() {
console.log("model change:");
console.log(this.model.get('select'));
console.log(this.model.get('input'));
}, this);
//this.model.bind('change:select', function() { this.render(); }, this); // <--------------------- WORKS
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
this.stickit();
return this;
},
events: {
'change #select': function(ev) {
console.log('change event triggered:');
console.log(this.model.get('select'));
console.log(this.model.get('input'));
this.render(); // <--------------------- DOES NOT WORK - WHY?
},
/* 'click #render': function(ev) {
console.log('render event triggered:');
console.log(this.model.get('select'));
console.log(this.model.get('input'));
this.render();
} */
},
bindings: {
'#input': 'input',
'#select': {
observe: 'select',
selectOptions: {
collection: function() {
return [{
value: '1',
label: 'Foo'
}, {
value: '2',
label: 'Bar'
}, {
value: '3',
label: 'Blub'
}]
}
}
},
},
});
new FooView({
model: new Foo()
}).render();
从您的 change #select
事件处理程序中调用 this.render()
不起作用的原因是因为您破坏了 Backbone.stickit 为您提供的双向数据绑定。流程如下所示:
- 用户更改了“#select”的值。
- 您的
change #select
处理程序触发并调用 this.render()
。
render
使用没有 selected option
. 的新 select 菜单重新填充 #ctr
- Backbone.stickit 响应
#select
的变化。
- Backbone.stickit 尝试获取
#select
的值,但由于它不包含 selected option
,因此值为 undefined
.
- Backbone.sticket 将
model
的 select
属性设置为 undefined
。
如果您将 this.render()
调用移动到 model
的 change:select
处理程序中,它会起作用的原因是 Backbone.stickit 能够正确更新模型而无需DOM 在它获得机会之前改变了。
我有两个表单元素,都通过 backbone.stickit 双向数据绑定。 第二个表单元素 (#input) 只是装饰品 - 用于显示它确实有效。
我的想法是,每次下拉菜单中的选项(#select)更改时,我的视图都会(重新)呈现。
我试图通过捕获#select 的 'changed' 事件并调用 this.render() 来(重新)渲染视图来实现这一点。
显然这不起作用。 selected 选项没有保存回模型中,我不明白为什么。
我不是在寻找解决方案,而是解释,为什么以下代码不起作用。解决方案(如:对我有用)是 fiddle 的一部分 - 已注释掉。
HTML:
<script type="text/template" id="tpl">
<h1>Hello <%= select %></h1>
<select id="select">
</select>
<p>Select:
<%= select %>
</p>
<hr>
<input type="text" id="input">
<p>Input:
<%= input %>
</p>
</script>
<div id="ctr"></div>
JavaScript:
Foo = Backbone.Model.extend({
defaults: {
select: "",
input: "",
}
});
FooView = Backbone.View.extend({
el: '#ctr',
template: _.template($('#tpl').html()),
initialize() {
this.model.bind('change', function() {
console.log("model change:");
console.log(this.model.get('select'));
console.log(this.model.get('input'));
}, this);
//this.model.bind('change:select', function() { this.render(); }, this); // <--------------------- WORKS
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
this.stickit();
return this;
},
events: {
'change #select': function(ev) {
console.log('change event triggered:');
console.log(this.model.get('select'));
console.log(this.model.get('input'));
this.render(); // <--------------------- DOES NOT WORK - WHY?
},
/* 'click #render': function(ev) {
console.log('render event triggered:');
console.log(this.model.get('select'));
console.log(this.model.get('input'));
this.render();
} */
},
bindings: {
'#input': 'input',
'#select': {
observe: 'select',
selectOptions: {
collection: function() {
return [{
value: '1',
label: 'Foo'
}, {
value: '2',
label: 'Bar'
}, {
value: '3',
label: 'Blub'
}]
}
}
},
},
});
new FooView({
model: new Foo()
}).render();
从您的 change #select
事件处理程序中调用 this.render()
不起作用的原因是因为您破坏了 Backbone.stickit 为您提供的双向数据绑定。流程如下所示:
- 用户更改了“#select”的值。
- 您的
change #select
处理程序触发并调用this.render()
。 render
使用没有 selectedoption
. 的新 select 菜单重新填充 - Backbone.stickit 响应
#select
的变化。 - Backbone.stickit 尝试获取
#select
的值,但由于它不包含 selectedoption
,因此值为undefined
. - Backbone.sticket 将
model
的select
属性设置为undefined
。
#ctr
如果您将 this.render()
调用移动到 model
的 change:select
处理程序中,它会起作用的原因是 Backbone.stickit 能够正确更新模型而无需DOM 在它获得机会之前改变了。