0

JavaScript テンプレート (Mustache、アンダースコア テンプレート) 用のライブラリがいくつかあります。彼らがすることは、新しい DOM ノードを作成することです。

私のアプリでは、メモリ消費を減らすために DOM ノードを再利用しようとしています。例として、ページネーション付きのサムネイル ギャラリーがあります。次の 50 個のサムネイルを読み込むときに、同じ 50 個のノードを再利用します。

テンプレート ライブラリを使用して新しいノードを簡単にレンダリングできますが、新しいノードを作成する代わりに、既存のノードを再利用または更新できるテンプレート ライブラリはありますか?

4

2 に答える 2

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);

私の経験では、これは可能な限り高速であり、テンプレートライブラリは、あれこれチェックするため、多くのオーバーヘッドと非効率性を追加するだけです.

于 2012-12-07T11:41:52.783 に答える
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>ます。

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;
  }
};
于 2012-12-07T12:05:50.980 に答える