JQueryを使用して追加するHTMLテンプレートを定義する


125

私はループしている配列を持っています。条件がtrueになるたびに、HTML以下のコードのコピーをいくつかの値を持つコンテナー要素に追加したいと思います。

このHTMLをスマートな方法で再利用するにはどこに置くことができますか?

<a href="#" class="list-group-item">
    <div class="image">
         <img src="" />
    </div>
    <p class="list-group-item-text"></p>
</a>

jQuery

$('.search').keyup(function() {
    $('.list-items').html(null);

    $.each(items, function(index) {
        // APPENDING CODE HERE
    });
});

2
スマートな方法を探している場合は、すべての情報を1つのDIVに入れてスタイルを設定します。2つのセルのみで多数のテーブルを作成しないでください。それらをアンカーにラップしないでください。
Sergey Snegirev 2013

3
OPは明らかに適切なコーディング方法(kudos!)に関心があるので、私は手助けしたいと思いました。実際の問題に貢献したい場合は、回答を投稿します。私は、誰でも位置に本格的な2セルのテーブルを使用すると、画像やテキストがかろうじていくつかの本当にエキゾチックな要件(?IE4)を除いて正当化されることに同意確信している
セルゲイSnegirev

1
@BrianG。コメントを投稿することは、実際に接することを意味するわけではありません。コメントはそれらに適切な場所であることに同意しますが(それらがまだ関連している限り)、コメントを回答に展開する時間がまだない人によるドライブバイヒントにも適しています。OPが何をしているのかを明確にすることは役に立ちます。
ミリムース2013

誰もあなたの質問に答えませんでした、パトリック?
Sebastian Neira 2013

回答:


164

次のようなテンプレートエンジンをプロジェクトで使用することを決定できます。

別のライブラリを含めたくない場合は、John Resigが以下のようなjQueryソリューションを提供します。


ブラウザとスクリーンリーダーは、認識されないスクリプトタイプを無視します。

<script id="hidden-template" type="text/x-custom-template">
    <tr>
        <td>Foo</td>
        <td>Bar</td>
    <tr>
</script>

jQueryを使用して、テンプレートに基づいて行を追加すると、次のようになります。

var template = $('#hidden-template').html();

$('button.addRow').click(function() {
    $('#targetTable').append(template);
});

@MaksimLuzikは正しいです。Moustache(商標のスペルに注意)は軽量で、OPのコードにプラグインされますが、ハンドルバーには配列を処理するための機能が多く、最終的にはより十分なソリューションを提供する可能性があります。ここで素敵な比較記事です:blog.cubettech.com/...
マイケルScheper

13
ここでテンプレートを編集する方法の例:jsfiddle.net/meehanman/7vw8bc84
Dean Meehan

175

古い質問ですが、「jQueryを使用する」という質問なので、ベンダーに依存せずにこれを実行できるオプションを提供したいと思いました。

多くのテンプレートエンジンが世の中にありますが、それらの機能の多くは最近好評を博しており<% for、イテレーション()、条件文(<% if)、変換(<%= myString | uppercase %>)は、せいぜいマイクロ言語と見なされ、最悪の場合はアンチパターンと見なされています。最新のテンプレートプラクティスでは、オブジェクトをDOM(または他の)表現に単純にマッピングすることを奨励しています。

HTML内のテンプレート

あなたがHTMLの残りの部分の横にテンプレートのHTMLを維持するために頼ることができます1つの特性は、非実行用いることで<script> type、例えば<script type="text/template">。あなたの場合:

<script type="text/template" data-template="listitem">
    <a href="${url}" class="list-group-item">
        <table>
            <tr>
                <td><img src="${img}"></td>
                <td><p class="list-group-item-text">${title}</p></td>
            </tr>
        </table>
    </a>
</script>

ドキュメントの読み込み時に、テンプレートを読み取り、単純な String#split

var itemTpl = $('script[data-template="listitem"]').text().split(/\$\{(.+?)\}/g);

トークンを使用すると、代替[text, property, text, property]形式で取得できることに注意してください。これによりArray#map、マッピング関数とともに、を使用してうまくマッピングできます。

function render(props) {
  return function(tok, i) { return (i % 2) ? props[tok] : tok; };
}

どこにprops見えるでしょう{ url: 'http://foo.com', img: '/images/bar.png', title: 'Lorem Ipsum' }

itemTpl上記のように解析してロードし、items範囲内に配列があると仮定して、すべてをまとめます。

$('.search').keyup(function () {
  $('.list-items').append(items.map(function (item) {
    return itemTpl.map(render(item)).join('');
  }));
});

このアプローチも、かろうじてjQueryにすぎません- document.querySelectorおよびでバニラJavaScriptを使用して同じアプローチをとることができるはず.innerHTMLです。

jsfiddle

JS内のテンプレート

自問する質問は次のとおりです。テンプレートをHTMLファイルとして定義することを本当に望んでいますか?テンプレートはいつでもコンポーネント化して、繰り返したいほとんどのことを再利用するのと同じ方法で、関数を使用してテンプレートを再利用できます。

es7-landでは、分解、テンプレート文字列、および矢印関数を使用して、$.fn.html上記のメソッドを使用して簡単にロードできる実に見栄えのよいコンポーネント関数を記述できます。

const Item = ({ url, img, title }) => `
  <a href="${url}" class="list-group-item">
    <div class="image">
      <img src="${img}" />
    </div>
    <p class="list-group-item-text">${title}</p>
  </a>
`;

その後、次のように、配列からマッピングされた場合でも、簡単にレンダリングできます。

$('.list-items').html([
  { url: '/foo', img: 'foo.png', title: 'Foo item' },
  { url: '/bar', img: 'bar.png', title: 'Bar item' },
].map(Item).join(''));

最後に、DBから読み取った場合や、誰かがページからHTMLを渡して(スクリプトを実行した場合など)、テンプレートに渡されたプロパティをサニタイズすることを忘れないでください。


1
素敵なテンプレートエンジン。
アーサーカストロ

40
あなたのJSの内部のテンプレートセクションでは、爆弾です
BigRon

2
「HTML内のテンプレート」アプローチのデモ/フィドルを追加していただけませんか?
LCJ 2017年

1
うわー!JS内のテンプレート...考えたことはありません!すごい!
ロマンロペス

2
うわー、これは本当にとてもいいです。各テンプレートにdata-url属性を追加しています。そして、それぞれのajaxデータをフェッチします。これはとてもいいことで、私は多くの時間を節約できました!ありがとうございました。
Davey

42

代わりにHTMLテンプレートを使用してください!

受け入れられた回答はオーバーロードスクリプトメソッドを表すので、私の意見では、オーバーロードスクリプトに伴うXSSリスクにより、はるかにクリーンで安全な別の方法を提案したいと思います。

私が作っデモをどのように行動に、どのように、他に1つのテンプレートを注入編集し、文書のDOMに追加し、それを使用する方法を紹介します。

HTMLの例

<template id="mytemplate">
  <style>
     .image{
        width: 100%;
        height: auto;
     }
  </style>
  <a href="#" class="list-group-item">
    <div class="image">
      <img src="" />
    </div>
    <p class="list-group-item-text"></p>
  </a>
</template>

jsの例

// select
var t = document.querySelector('#mytemplate');

// set
t.content.querySelector('img').src = 'demo.png';
t.content.querySelector('p').textContent= 'demo text';

// add to document DOM
var clone = document.importNode(t.content, true); // where true means deep copy
document.body.appendChild(clone);

HTML <テンプレート>

  • +そのコンテンツは、アクティブになるまで効果的に不活性です。基本的に、マークアップは非表示のDOMであり、レンダリングされません。

  • +テンプレート内のコンテンツには副作用がありません。テンプレートが使用されるまで、スクリプトは実行されず、画像は読み込まれず、オーディオは再生されません。

  • +コンテンツはドキュメントに含まれていないと見なされます。メインページでdocument.getElementById()またはquerySelector()を使用しても、テンプレートの子ノードは返されません。

  • +テンプレートはどこでも内部の配置することができ<head><body>または<frameset>、それらの要素に許可されているコンテンツの任意のタイプを含むことができます。「どこでも」とは<template>、HTMLパーサーが許可しない場所でも安全に使用できることを意味します。

後退する

ブラウザのサポートは問題ではありませんが、すべての可能性をカバーしたい場合は、簡単に確認できます。

機能を検出<template>するには、DOM要素を作成し、.contentプロパティが存在することを確認します。

function supportsTemplate() {
  return 'content' in document.createElement('template');
}

if (supportsTemplate()) {
  // Good to go!
} else {
  // Use old templating techniques or libraries.
}

スクリプトメソッドのオーバーロードに関するいくつかの洞察

  • +何もレンダリングされない- デフォルトで<script>タグが付いているため、ブラウザはこのブロックをレンダリングしませんdisplay:none
  • +不活性-タイプが以外に設定されているため、ブラウザはスクリプトコンテンツをJSとして解析しません"text/javascript"
  • -セキュリティ問題-の使用を推奨します.innerHTML。ユーザー提供のデータの実行時の文字列解析は、XSSの脆弱性に簡単につながる可能性があります。

完全な記事:https : //www.html5rocks.com/en/tutorials/webcomponents/template/#toc-old

便利なリファレンス:https : //developer.mozilla.org/en-US/docs/Web/API/Document/importNode http://caniuse.com/#feat=queryselector

Web コンポーネントの作成Trawersy MediaによるHTMLテンプレートを使用したカスタムWeb コンポーネントの作成チュートリアル:https ://youtu.be/PCWaFLy3VUo


4
このtemplate要素はInternet Explorerではサポートされていません(2018年現在、IE11)。w3c.github.io/html/single-page.htmlの例580でテストされています。
ローランド

私はが好きですが<template>、クラスを自由に使用することをお勧めします。したがって、どの小道具が何に設定されているのかは明らかです。データをテンプレートに適切にマップするには、特にコンポーネントスタイルのアプローチを使用して大量のデータセットをマッピングするには、まだjsスキルが必要です。個人的には、関数でHTMLを作成すること、または理想的にはJS自体で直接DOMを作成し、HTMLを完全に無視すること(例:Reactがそれを行う方法)が好きです。
カリブのジョシュ、18

テンプレートのアプローチは私にはうまくいきました。私が持っている1つの推奨事項は、テンプレートを(最後ではなく)最初に複製し、複製されたオブジェクトを操作することです。それ以外の場合、行っている変更はテンプレート自体に発生しています。一部のプロパティ/コンテンツを時々のみ設定する条件付きロジックがある場合、それらのプロパティはテンプレートの次回の使用時に存在します。毎回使用する前にクローンを作成することで、常に一貫した作業の基盤を確保できます。
jt。

13

体のどこかに追加

<div class="hide">
<a href="#" class="list-group-item">
    <table>
        <tr>
            <td><img src=""></td>
            <td><p class="list-group-item-text"></p></td>
        </tr>
    </table>
</a>
</div>

次にCSSを作成します

.hide { display: none; }

そしてあなたのjsに追加

$('#output').append( $('.hide').html() );

1
OPにはJSONがあり、その配列をデータソースとして使用してHTMLをレンダリングしたいと考えています。この回答はどのように問題に対処していますか?あなたの答えはhtmlノードを取り、それを複製/複製し、データバインディングに関連するものは何もありません。
Adrian Iftode 2013

だから私は誰が反対票を投じているのですか。
Adrian Iftode 2013

あなたはより良い答えを得るための助けにはなっていないと思います。なぜなら、私たちの答えによって扱われていることよりもポイントが広いということを思い出させることから始めることができたからです。
Sebastian Neira 2013

1
これは機能しますが.children().clone()、実行するよりも実行する方が効率的です.html()。速度は、<tr/>このコードを使用してページ上でランダムに取得した場合、約3:1 ですi=10000; time=performance.now(); while (--i) {$a.clone().append(0 ? $b.html() : $b.children().clone())} performance.now()-time。$ a.clone()を使用しているため、比率は実際には少し誇張されていますが、各反復を空にしようとすると、クローン作成よりもパフォーマンスに影響が出ます。タイミング関数には独自のコストがあります。
Chinoto Vokro

1
このアプローチは悪いです。主に、使用していなくてもテンプレートコンテンツをダウンロードして解析するためです。これは、これを有効な回答と見なすには大きすぎる問題です。また、上記の他の誰かとして、少なくとも.html()の代わりにクローンを使用する必要がある場合
DevWL

3

その他の代替:純粋

私はそれを使用し、それは私に多くの助けをしてくれました。彼らのウェブサイトに示されている例:

HTML

<div class="who">
</div>

JSON

{
  "who": "Hello Wrrrld"
}

結果

<div class="who">
  Hello Wrrrld
</div>

2

この問題を解決するために、私は2つの解決策を認識しています。

  • 1つ目はAJAXに対応しており、別のファイルからテンプレートをロードして、必要なときにを追加するだけです.clone()

    $.get('url/to/template', function(data) {
        temp = data
        $('.search').keyup(function() {
            $('.list-items').html(null);
    
            $.each(items, function(index) {
                 $(this).append(temp.clone())
            });
    
        });
    });

    データが利用可能であることを確認するために、ajaxが完了したらイベントを追加する必要があることを考慮してください!

  • 2つ目は、元のhtmlの任意の場所に直接追加し、それを選択してjQueryで非表示にすることです。

    temp = $('.list_group_item').hide()

    テンプレートの新しいインスタンスを追加した後、

    $('.search').keyup(function() {
        $('.list-items').html(null);
    
        $.each(items, function(index) {
            $(this).append(temp.clone())
        });
    });
  • 以前のものと同じですが、テンプレートをそこに残したくない場合は、JavaScriptだけで、.detach()非表示の代わりに使用できます(テストしていません!)

    temp = $('.list_group_item').detach()

    .detach() データとイベントを存続させながらDOMから要素を削除します(.remove()はそうではありません!)


-問題ありません!-
iConnor

opにはJSONがあり、その配列をデータソースとして使用してHTMLをレンダリングしたいと考えています。この回答はどのように問題に対処していますか?あなたの答えはhtmlノードを取り、それを複製/複製し、データバインディングに関連するものは何もありません。
Adrian Iftode 2013

1
私はopから引用します以下のHTMLコードのコピーを、いくつかの値を持つコンテナー要素に追加したいと思います。 これで彼の問題は解決したと思います。
Sebastian Neira 2013

そして、「いくつかの値」の部分はどのように扱われますか?
Adrian Iftode 2013

まあ、それはそれが問題に対処しないという意味ではありません。私はあなたが、私はどのように私は私も知っていない場合は、それらの値を挿入する方法を知っています、とにかくポイント:)のいずれかを欠落していた私に言ってきたことを理解するどのような私たちが話している値は?この部分をご覧ください。このHTMLをスマートな方法で再利用するにはどこに配置すればよいですか?。何が本当に求められているのですか?JSONまたはHTMLのインクルードについて
Sebastian Neira 2013

1

ネイティブHTML5 テンプレート要素の使用に関するDevWLからの非常に良い回答。OPからのこの良い質問に貢献するために、jQuery を使用してこの要素を使用する方法を追加したいと思います。次に例を示します。template

$($('template').html()).insertAfter( $('#somewhere_else') );

のコンテンツはtemplatehtmlではなく、単にデータとして扱われるため、コンテンツをjQueryオブジェクトにラップして、jQueryのメソッドにアクセスする必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.