私の解決策は、adeneoのものに似ていますが、もう少し一般的です。私は自分のプロジェクトでこれを使用しています。ネイティブ DOM API のみを使用し、js と html を完全に分離しています。
<ul class="list">
<li class="item">
<label><span class="name">Field:</span><input name="" type="" value="" /></label>
</li>
</ul>
クライアントに送信するときは、空白を削除する必要があることに注意してください。
最初に、配信された HTML に基づいてテンプレートを生成します。これは、ルート要素といくつかのバインディング ポイントをパラメーターとして受け取ります。
var ul = document.querySelector('.list');
var tpl = new Tmpl(ul.querySelector('li'), [['.name', 'input@name'], 'input@type', 'input@value']);
次に、データを使用して を生成し<li>
ます。
var data = [['test1', 'text', 'test value'], ['test2', 'checkbox', 'true']]
for (var i = 0; i < data.length; i++)
ul.appendChild(tpl.generate(data[i]));
1 つのインスタンスを更新する必要がある場合は、次のように実行できます。
tpl.apply(ul.querySelector('li'), ['test3', 'button', 'it\'s a button now']);
これでリストが生成されました。
Tmpl クラス (最小化され、他の機能が削除され、依存関係なしで動作する) が以下に貼り付けられます。
function Tmpl(node, targets, singleton) {
this.elem = node;
this.begins = [];
this.targets = [];
this.fields = [];
this.mapping = [];
for (var i = 0; i < targets.length; i++) {
var tmp = targets[i] instanceof Array ? targets[i] : [targets[i]];
this.begins.push(this.targets.length);
for (var j = 0; j < tmp.length; j++) {
var field = this.parse(node, tmp[j]);
if (field) {
this.targets.push(tmp[j]);
this.fields.push(field);
this.mapping.push(i);
}
}
}
this.begins.push(this.targets.length);
node.parentNode.removeChild(node);
return this;
}
Tmpl.prototype = {
generate: function(data) {
for (var i = 0; i < this.fields.length; i++)
this.fields[i].nodeValue = data[this.mapping[i]];
return this.elem.cloneNode(true);
},
apply: function(node, data) {
for (var i = 0; i < this.fields.length; i++)
this.parse(node, this.targets[i]).nodeValue = data[this.mapping[i]];
return node;
},
applySingle: function(node, index, datum) {
for (var i = this.begins[index]; i < this.begins[index+1]; i++)
this.parse(node, this.targets[i]).nodeValue = datum;
return node;
},
parse: function(that, selector) {
selector = selector.split('@');
var node = selector[0] == '.' ? that : that.querySelector(selector[0]);
if (selector[1]) {
var attr = node.getAttributeNode(selector[1]);
if (!attr) {
attr = document.createAttribute(selector[1]);
node.setAttributeNode(attr);
}
node = attr;
}
if (node instanceof HTMLElement && node.nodeType != 2 && node.nodeType != 3)
node = node.firstChild && node.firstChild.nodeType == 3 ?
node.firstChild : node.appendChild(document.createTextNode(''));
return node;
}
};