JavaScript模板有几个库(Mustache,下划线模板)。他们所做的是创建新的DOM节点。
在我的应用程序中,我尝试重用DOM节点以减少内存消耗。一个例子是带有分页的缩略图库。当我加载50个下一个缩略图时,我重复使用相同的50个节点。
我可以轻松地使用模板库渲染新节点,但是有一些模板库而不是创建新节点,可以重用或更新现有节点吗?
答案 0 :(得分:1)
根据我的经验,创建元素和使用它们的最快方法是尽可能少地创建,在必要时克隆它们,因为它更快,并使用片段来保存它们并尽可能少地对DOM进行更改,限制回流。我做了很多(简化很多):
var div = document.createElement('div'),
anchor = document.createElement('a'),
span = document.createElement('span'),
frag = document.createDocumentFragment();
anchor.className = 'link';
span.style.height = '20px';
for (var i=0; i<something; i++) {
var wrapper = div.cloneNode(false),
link = anchor.cloneNode(true),
child = span.cloneNode(true);
wrapper.id = 'myWrapper-'+i;
wrapper.setAttribute('data-somevalue', 'myValue'+i);
child.appendChild(link);
wrapper.appendChild(child);
frag.appendChild(wrapper);
}
document.body.appendChild(frag);
根据我的经验,这是最快的,任何模板库只会增加很多开销和低效率,因为它会检查这个等等。
答案 1 :(得分:0)
我的解决方案有点像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>
s。
var data = [['test1', 'text', 'test value'], ['test2', 'checkbox', 'true']]
for (var i = 0; i < data.length; i++)
ul.appendChild(tpl.generate(data[i]));
当需要更新一个实例时,您可以这样做:
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;
}
};