web-dev-qa-db-ja.com

効率的なJavaScript文字列の置換

こんにちは、私は繰り返し使用するHTMLのブロックを取得しました(一度にではなく、ユーザーのアクセス中にさまざまなタイミングで)。これを達成するための最良の方法は、HTML divを作成して非表示にし、必要に応じてinnerHTMLを取得して、いくつかのキーワードでreplace()を実行することだと思います。 HTMLブロックの例として...

<div id='sample'>
  <h4>%TITLE%</h4>
  <p>Text text %KEYWORD% text</p>
  <p>%CONTENT%</p>
  <img src="images/%ID%/1.jpg" />
</div>

これらのキーワードを動的データに置き換える最善の方法は、実行することです...

template = document.getElementById('sample');
template = template.replace(/%TITLE%/, some_var_with_title);
template = template.replace(/%KEYWORD%/, some_var_with_keyword);
template = template.replace(/%CONTENT%/, some_var_with_content);
template = template.replace(/%ID%/, some_var_with_id);

私はこれをするために愚かな方法を選んだように感じます。誰かがこれをより速く、よりスマートに、またはより良くする方法について何か提案はありますか?このコードは、ユーザーのアクセス中にかなり頻繁に、時には3〜4秒ごとに実行されます。

前もって感謝します。

31
Josh

もっと効率的なものがあるとは思えません。別の方法は、それを部分に分割してから連結することですが、それはそれほど効率的ではないと思います。すべての連結の結果、オペランドと同じサイズの新しい文字列が生成されることを考えると、おそらくさらに少なくなります。

追加: これはおそらくこれを書く最もエレガントな方法です。その上-あなたは何を心配していますか?メモリ使用量?それは豊富で、JavaScriptはまともなメモリマネージャーを持っています。実行速度は?次に、巨大な文字列が必要です。私見これは良いです。

12
Vilx-

テンプレートを使用したいようです。

//Updated 28 October 2011: Now allows 0, NaN, false, null and undefined in output. 
function template( templateid, data ){
    return document.getElementById( templateid ).innerHTML
      .replace(
        /%(\w*)%/g, // or /{(\w*)}/g for "{this} instead of %this%"
        function( m, key ){
          return data.hasOwnProperty( key ) ? data[ key ] : "";
        }
      );
}

コードの説明:

  • templateidが既存の要素のIDであることを期待しています。
  • dataがデータを持つオブジェクトであることが期待されます。
  • 2つのパラメーターを使用して置換を行います。
  • 1つ目は、すべての%keys%(代替バージョンを使用している場合は{keys})を検索する正規表現です。キーは、A-Z、a-z、0-9、およびアンダースコア_の組み合わせにすることができます。
  • 2番目は、すべての一致に対して呼び出される無名関数です。
  • 無名関数は、正規表現が見つけたキーをデータオブジェクトで検索します。キーがデータで見つかった場合、キーの値が返され、その値が最終出力のキーを置き換えます。キーが見つからない場合は、空の文字列が返されます。

テンプレートの例:

<div id="mytemplate">
  <p>%test%</p>
  <p>%Word%</p>
</div>

呼び出しの例:

document.getElementById("my").innerHTML=template("mytemplate",{test:"MYTEST",Word:"MYWORD"});
80
some

あなたはおそらくあなたが望むことをするためにこのコードを適応させることができます:

var user = {
    "firstName": "John",
    "login": "john_doe",
    "password": "test",
};

var textbody = ""
+"Hey {firstName},\n"
+"\n"
+"You recently requested your password.\n"
+"login: {login}\n"
+"password: {password}\n"
+"\n"
+"If you did not request your password, please disregard this message.\n"
+"";

textbody = textbody.replace(/{[^{}]+}/g, function(key){
    return user[key.replace(/[{}]+/g, "")] || "";
});

JavaScriptTemplates も調べてみてください。

18

テンプレートの置き換え

すばやく簡単な解決策は、 String.prototype.replace メソッドを使用することです。
これは、値または関数のいずれかである可能性がある2番目のパラメーターを取ります。

function replaceMe(template, data) {
    const pattern = /{\s*(\w+?)\s*}/g; // {property}
    return template.replace(pattern, (_, token) => data[token]||'');
}

const html = `
    <div>
        <h4>{title}</h4>
        <p>My name is {name}</p>
        <img src="{url}" />
    </div>
`;

const data = {
    title: 'My Profile',
    name: 'John Smith',
    url: 'http://images/john.jpeg'
};

そしてそれを次のように呼び出します:

replaceMe(html, data);
8
Lior Elrom

あなたの方法は貧乏人のテンプレートシステムを実装する標準的な方法なので、問題ありません。

[〜#〜] jst [〜#〜] のようないくつかのJavaScriptテンプレートライブラリをチェックアウトするのは時間の価値があります。

2
orip

このアプローチは、キャ​​ッシュできる関数テンプレートを生成します。

function compileMessage (message) {

  return new Function('obj', 'with(obj){ return \'' +
    message.replace(/\n/g, '\\n').split(/{{([^{}]+)}}/g).map(function (expression, i) {
      return i%2 ? ( '\'+(' + expression.trim() + ')+\'' ) : expression;
    }).join('') + 
  '\'; }');

}

var renderMessage = compileMessage('Hi {{ recipient.first_name }},\n\n' +

'Lorem ipsum dolor sit amet...\n\n' +

'Best Regarts,\n\n' +

'{{ sender.first_name }}');


renderMessage({
  recipient: {
    first_name: 'John'
  },
  sender: {
    first_name: 'William'
  }
});

戻り値:

"Hi John,

Lorem ipsum dolor sit amet...

Best Regarts,

William"
1
Jesús Germade

これらすべての暫定的な割り当てを行う代わりに、置換をチェーンすることにより、より効率的にすることができます。

つまり.

with(document.getElementById('sample'))
{
  innerHTML = innerHTML.replace(a, A).replace(b, B).replace(c, C); //etc
}
1
annakata

プロトタイプライブラリ を使用する場合は、ニースにテンプレート機能が組み込まれています。

それは次のようになります:

element.innerHTML = (new Template(element.innerHTML)).evaluate({
    title: 'a title',
    keyword: 'some keyword',
    content: 'A bunch of content',
    id: 'id here'
})

JSONオブジェクト/ JavaScriptオブジェクトリテラルを簡単に作成できるため、ループでコードを実行している場合、これは特に便利です。

それでも、速度の向上は期待できません。

また、区切り記号のスタイルを#{keyword}ではなく%keyword%に変更する必要があります。

1
Triptych

これを試してください: http://json2html.com/

複雑なJSONオブジェクトもサポートします。

0
sura2k

Mustachejsは本当にエレガントなテンプレートに最適です:

_<div id='sample'>
  <h4>{{TITLE}}</h4>
  <p>Text text {{KEYWORD}} text</p>
  <p>{{CONTENT}}</p>
  <img src="images/{{ID}}/1.jpg" />
</div>
_

その後、次のようなテンプレートを使用できます。

_var template = document.getElementById(templateid).innerHTML;
var newHtml = Mustache.render(template, {
    TITLE: some_var_with_title,
    KEYWORD: some_var_with_keyword,
    CONTENT: some_var_with_content,
    ID: some_var_with_id
});
document.getElementById('sample').innerHTML = newHtml;
_

これは、Ajax呼び出しからJSONを取得する場合に特にうまく機能します-Mustache.render()呼び出しに直接渡すだけです。

わずかなバリエーションにより、各ブラウザーまたはサーバーで同じテンプレートを実行できます。詳細は https://github.com/janl/mustache.js を参照してください。

0