给定一个模型:
MyModel = Backbone.Model.extend({
defaults: {
name: '',
age: -1,
height: '',
description: ''
}
});
以及将模型呈现为列表的视图:
MyView = Backbone.View.extend({
tagName: 'ul',
className: 'MyView',
render() {
var values = {
name: this.model.get('name'),
age: this.model.get('age'),
height: this.model.get('height'),
description: this.model.get('description')
}
var myTemplate = $('#MyView-Template').html();
var templateWithValues = _.template(myTemplate , values);
}
});
和视图加载的模板:
<script type="text/template" id="MyView-Template">
<li class="name"><%= name %></li>
<li class="age"><%= age %></li>
<li class="name"><%= height%></li>
<li class="name"><%= description%></li>
</script>
一切正常,虽然这是一个人为的例子,但真实的代码在模型中有很多很多的属性。我遇到的问题是如何处理模型的更新。
我创建了一个 HTML 表单,其中每个字段都有一个适当的输入元素。该表单被建模并作为模板加载:
<script type="text/template" id="MyEditView-Template">
<input type"text" value="<%= name %>" /> <br />
<input type"text" value="<%= age%>" /> <br />
<input type"text" value="<%= height%>" /> <br />
<input type"text" value="<%= description%>" />
</script>
并加载到视图中:
MyEditView = Backbone.View.extend({
tagName: 'form',
className: 'MyEditView',
render() {
var values = {
name: this.model.get('name'),
age: this.model.get('age'),
height: this.model.get('height'),
description: this.model.get('description')
}
var myTemplate = $('#MyEditView-Template').html();
var templateWithValues = _.template(myTemplate , values);
}
});
当用户保存表单时,新值会在模型 (MyModel) 中设置。但是我不想重新渲染整个原始视图,它需要太长时间并且有很多嵌套元素。我只想更新在模型中更改了其值的 HTML 元素。
问题是如何优雅地将模型的属性链接到 HTML 元素,以便我可以对已渲染的视图执行以下操作:
- 迭代模型的属性。
- 确定哪些属性已被修改。
- 仅更新已修改属性的 UI。
- 隐藏任何以前呈现的不应再显示的属性的 UI。
有一刻我有一个 JavaScript 查找表(只是一个对象)的相当丑陋的解决方案,它将属性名称映射到 HTML 元素字符串:
var AttributesMap = {
name: {
htmlRef: 'li.name',
attributeName: 'name'
},
age: {
htmlRef: 'li.age',
attributeName: 'age'
}
...
}
这感觉很hacky,并导致了一些非常臃肿的代码。