正如大多数指南所示,我有一个简单的视图,当模型发生更改时,它会将自身绑定到重绘:
this.model.bind('change', this.render, this);
这个视图有一个带有输入框和提交按钮的表单。我正在绑定输入框的“更改”事件以更改模型上的相关项。(我可以手动执行此操作,也可以使用 ModelBinder 项目执行此操作,两种方式都一样。)
用户更改表单输入框中的值,然后单击提交按钮。模型被更新,视图和表单被重新渲染。提交按钮的点击事件被压扁。
我正在使用 Backbone 的 events 属性:
events : {
'submit form' : 'save'
},
我知道该事件被忽略了,因为单击的 DOM 元素不再存在。我可以在 render() 中放置一个小的 setTimeout 以防止 HTML 被换出并且事情按预期工作,但这需要等待。
我不能成为第一个为此苦苦挣扎的人——在不丢失一些按键点击或按键信息的情况下,捕获表单“更改”事件、更新模型和重绘视图的标准方法是什么?
同样,如果我有多个表单项,则在重绘表单时更改内容后,用户无法在项目之间切换。
更新 1 - 3 天后
仍在努力寻找一个好的解决方案。我尝试过的事情:
- 将视图的内容移动或克隆到页面上的不同区域。仍然从未收到点击事件。
- 使用 $(document).on 或 $(document).live 而不是标准视图事件对象注册点击事件
- 分离表单,使整个表单(输入和按钮)保持在一起而不被重绘。重绘父元素(依赖于表单值)并重新插入已绘制的表单。这修复了无法在元素之间切换的相关问题,但不修复点击事件。
- 在 Firefox 4 中可以正常工作,但不能在 ie9 或 chrome 中使用。*
更新 2 - 带有示例代码
其中一条评论要求提供一些代码。我已将代码大量简化为一页并将其包含在下面。实际应用要复杂得多。使用下面简单的代码,我可以在更改时手动重新渲染页面的某些部分。在实际应用程序中,我使用的是dustjs模板,即使我不重新渲染表单,而是重新渲染包含表单的元素,我在点击提交时遇到问题。我希望有一个典型的主干应用程序的“模式”,包括复杂的页面、模型和表单。
大多数“演示”应用程序,甚至我看到的使用主干的网站似乎大多是专注于演示的应用程序,实际上并没有从用户那里收集大量输入。如果您知道基于主干的以数据收集为重点的良好应用程序/演示,那将很有帮助。
代码:
<!doctype html>
<html lang="en">
<head>
<script src="libs/jquery.js"></script>
<script src="libs/underscore.js"></script>
<script src="libs/backbone.js"></script>
</head>
<body>
<div id="container"></div>
<script type="text/template" id="edit_user_template">
<h3>Edit User <%=id%> : <%=name%></h3>
<form>
Name: <input type="text" name="name" value="<%=name%>"><br/>
Email: <input type="text" name="email" value="<%=email%>"><br/>
<input type="submit">
</form>
</script>
<script>
var UserModel = Backbone.Model.extend({});
var model = new UserModel({id: '1', name:'Joe', email:'a@a.com'});
var UserView = Backbone.View.extend({
events : {
'submit form' : 'save',
'change input' : 'inputChange'
},
initialize: function(){
this.model.bind('change', this.render, this);
},
render: function(){
var template = _.template($('#edit_user_template').html(), this.model.toJSON());
this.$el.html(template);
},
inputChange : function(evt){
var target = $(evt.currentTarget);
this.model.set(target.attr('name'), target.val());
},
save : function(event){
console.log('saving');
event.preventDefault();
//this.model.save();
}
});
var view = new UserView({model: model, el: '#container'});
view.render();
</script>
</body>
</html>