与えられたモデル:
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 を非表示にします。
属性名をHTML要素文字列にマップするJavaScriptルックアップテーブル(単なるオブジェクト)のかなり醜いソリューションを手に入れた瞬間:
var AttributesMap = {
name: {
htmlRef: 'li.name',
attributeName: 'name'
},
age: {
htmlRef: 'li.age',
attributeName: 'age'
}
...
}
これはハッキリしているように感じられ、かなり肥大化したコードになってしまいました。