web-dev-qa-db-ja.com

アンダースコアの外部テンプレート

nderscore template を使用します。 外部ファイルをテンプレートとして添付することが可能です

バックボーンビューには次のものがあります。

 textTemplate: _.template( $('#practice-text-template').html() ),

 initialize: function(){                                            
  this.words = new WordList;            
  this.index = 0;
  this.render();
 },

私のhtmlには:

<script id="practice-text-template" type="text/template">
   <h3>something code</h3>
</script>

うまくいきます。しかし、外部テンプレートが必要です。私が試します:

<script id="practice-text-template" type="text/template" src="templates/tmp.js">

または

textTemplate: _.template( $('#practice-text-template').load('templates/tmp.js') ),

または

$('#practice-text-template').load('templates/tmp.js', function(data){ this.textTemplate = _.template( data ) })

しかし、うまくいきませんでした。

120
Tomáš

編集:この回答は古くて時代遅れです。削除しますが、「受け入れられた」回答です。代わりに意見を注入します。

これをもう支持することはありません。代わりに、すべてのテンプレートを個々のHTMLファイルに分離します。これらを非同期に読み込むことをお勧めします(Require.jsまたは一種のテンプレートキャッシュ)。多くのテンプレートを使用する大規模なプロジェクトでは、ページの読み込み時に非常に嫌いな小さな非同期リクエストが大量に作成されていることに気付きます(うーん... OK、最初の依存関係をプリコンパイルすることでRequire.jsで回避できます) r.js、ただしテンプレートの場合、これはまだ私にとって間違っていると感じています)

私はgruntタスク(grunt-contrib-jst)を使用して、すべてのHTMLテンプレートを単一のtemplates.jsファイルにコンパイルし、それを含めるのが好きです。IMO...ファイル、前述のテンプレートのコンパイルはビルド時(実行時ではなく)に行われ、ページの起動時に100の小さな非同期要求はありません。

以下はすべてジャンクです

私にとっては、テンプレートにJSファイルを含めるシンプルさを好みます。そのため、テンプレートを変数として含むview_template.jsというファイルを作成できます。

app.templates.view = " \
    <h3>something code</h3> \
";

次に、通常のスクリプトファイルのようにスクリプトファイルをインクルードして、ビューで使用するのと同じくらい簡単です。

template: _.template(app.templates.view)

さらに一歩進んで、I実際にcoffeescriptを使用するため、私のコードは実際には次のようになり、行末のエスケープ文字を避けます。

app.templates.view = '''
    <h3>something code</h3>
'''

このアプローチを使用することで、require.jsで実際に必要のない場所を避けることができます。

51
Brian Genisio

簡単な解決策は次のとおりです。

var rendered_html = render('mytemplate', {});

function render(tmpl_name, tmpl_data) {
    if ( !render.tmpl_cache ) { 
        render.tmpl_cache = {};
    }

    if ( ! render.tmpl_cache[tmpl_name] ) {
        var tmpl_dir = '/static/templates';
        var tmpl_url = tmpl_dir + '/' + tmpl_name + '.html';

        var tmpl_string;
        $.ajax({
            url: tmpl_url,
            method: 'GET',
            dataType: 'html', //** Must add 
            async: false,
            success: function(data) {
                tmpl_string = data;
            }
        });

        render.tmpl_cache[tmpl_name] = _.template(tmpl_string);
    }

    return render.tmpl_cache[tmpl_name](tmpl_data);
}

ここで「async:false」を使用しても、テンプレートがロードされるまで待つ必要があるため、悪い方法ではありません。

だから、「レンダリング」機能

  1. 静的ディレクトリの個別のhtmlファイルに各テンプレートを保存できます
  2. 非常に軽量です
  3. テンプレートをコンパイルおよびキャッシュします
  4. テンプレートのロードロジックを抽象化します。たとえば、将来、プリロードされたテンプレートとプリコンパイルされたテンプレートを使用できます。
  5. 使いやすい

[これは重要だと思うので、コメントを残す代わりに回答を編集しています。]

テンプレートがnative appに表示されず、HIERARCHY_REQUEST_ERROR: DOM Exception 3が表示されている場合Dave Robinsonによる 「HIERARCHY_REQUEST_ERR:DOM Exception 3」-Error?の正確な原因は? です。

基本的に、追加する必要があります

dataType: 'html'

$ .ajaxリクエストへ。

107
koorchik

このミックスインを使用すると、Underscoreを使用して外部テンプレートを非常に簡単な方法でレンダリングできます:_.templateFromUrl(url, [data], [settings])。メソッドAPIは、Underscoreの_。template() とほぼ同じです。キャッシングが含まれています。

_.mixin({templateFromUrl: function (url, data, settings) {
    var templateHtml = "";
    this.cache = this.cache || {};

    if (this.cache[url]) {
        templateHtml = this.cache[url];
    } else {
        $.ajax({
            url: url,
            method: "GET",
            async: false,
            success: function(data) {
                templateHtml = data;
            }
        });

        this.cache[url] = templateHtml;
    }

    return _.template(templateHtml, data, settings);
}});

使用法:

var someHtml = _.templateFromUrl("http://example.com/template.html", {"var": "value"});
17
Dmitriy

この単純なタスクにrequire.jsを使用したくなかったため、修正されたkoorchikのソリューションを使用しました。

function require_template(templateName, cb) {
    var template = $('#template_' + templateName);
    if (template.length === 0) {
        var tmpl_dir = './templates';
        var tmpl_url = tmpl_dir + '/' + templateName + '.tmpl';
        var tmpl_string = '';

        $.ajax({
            url: tmpl_url,
            method: 'GET',
            contentType: 'text',
            complete: function (data, text) {
                tmpl_string = data.responseText;
                $('head').append('<script id="template_' + templateName + '" type="text/template">' + tmpl_string + '<\/script>');
                if (typeof cb === 'function')
                    cb('tmpl_added');
            }
        });
    } else {
        callback('tmpl_already_exists');
    }
}

require_template('a', function(resp) {
    if (resp == 'tmpl_added' || 'tmpl_already_exists') {
        // init your template 'a' rendering
    }
});
require_template('b', function(resp) {
    if (resp == 'tmpl_added' || 'tmpl_already_exists') {
        // init your template 'b' rendering
    }
});

テンプレートをjavascriptオブジェクトに保存するのではなく、ドキュメントに追加するのはなぜですか?本番バージョンでは、すべてのテンプレートがすでに含まれているhtmlファイルを生成するため、追加のAjaxリクエストを行う必要はありません。同時に、コードをリファクタリングする必要もありません。

this.template = _.template($('#template_name').html());

私のバックボーンビューで。

17
Tyth

これはトピックから少し外れているかもしれませんが、node.js(http://nodejs.org/、すべての主要なプラットフォームで利用可能)で実行されるGrunt(http://gruntjs.com/)を使用して、コマンドライン。このツールには、テンプレートコンパイラ https://npmjs.org/package/grunt-contrib-jst などのプラグインが多数あります。 GitHubのドキュメントを参照してください https://github.com/gruntjs/grunt-contrib-jst 。 (また、ノードパッケージマネージャーの実行方法を理解する必要があります。 https://npmjs.org/

その後、すべてのテンプレートを個別のhtmlファイルに保持し、ツールを実行してアンダースコアを使用してすべてをプリコンパイルできます(これはJSTプラグインの依存関係ですが、心配しないでください。ノードパッケージマネージャーが依存関係を自動的にインストールします)。

これにより、すべてのテンプレートが1つのスクリプトにコンパイルされます。

templates.js

スクリプトをロードすると、グローバル(デフォルトでは「JST」)が設定されます。これは関数の配列であり、次のようにアクセスできます。

JST['templates/listView.html']()

次のようになります

_.template( $('#selector-to-your-script-template'))

そのスクリプトタグのコンテンツを(templates /)listView.htmlに配置した場合

しかし、本当のキッカーはこれです:Gruntには「ウォッチ」と呼ばれるこのタスクが付属しています。これは基本的にローカルのgrunt.jsファイル(基本的にはGruntプロジェクトの設定ファイルであるjavascript)で定義したファイルへの変更を監視します)。次のように入力して、このタスクを開始します。

grunt watch

gruntはコマンドラインから、ファイルに加えたすべての変更を監視し、変更を検出すると、grunt.jsファイルで設定したすべてのタスクを自動実行します-jstなど上記のタスク。ファイルを編集して保存すると、すべてのテンプレートが複数のディレクトリやサブディレクトリに分散している場合でも、すべてのテンプレートが1つのjsファイルに再コンパイルされます。

同様のタスクは、JavaScriptのリント、テストの実行、スクリプトファイルの連結と最小化/不正化のために構成できます。また、すべてを監視タスクに結び付けることができるため、ファイルを変更すると、プロジェクトの新しい「ビルド」が自動的にトリガーされます。

Grunt.jsファイルの設定と設定方法を理解するには少し時間がかかりますが、十分に時間を費やす価値があり、不満のない作業方法に戻ることはないと思います

16
Mansiemans

this があなたを助けるかもしれないと思う。ソリューションのすべては、JavaScriptファイルおよびモジュールローダーであるrequire.jsライブラリを中心に展開します。

上記のリンクのチュートリアルは、バックボーンプロジェクトの編成方法を非常にうまく示しています。 サンプル実装 も提供されます。お役に立てれば。

15
nayaab

データ型を「テキスト」に設定して、機能するようにしなければなりませんでした。

get : function(url) {
    var data = "<h1> failed to load url : " + url + "</h1>";
    $.ajax({
        async: false,
        dataType: "text",
        url: url,
        success: function(response) {
            data = response;
        }
    });
    return data;
}
4
user1828189

Javascriptのテンプレート化に興味を持ち、今ではバックボーンで最初の一歩を踏み出しています。これは私が思いついたものであり、かなりうまくいくようです。

window.App = {

    get : function(url) {
        var data = "<h1> failed to load url : " + url + "</h1>";
        $.ajax({
            async: false,
            url: url,
            success: function(response) {
                data = response;
            }
        });
        return data;
    }
}

App.ChromeView = Backbone.View.extend({
    template: _.template( App.get("tpl/chrome.html") ),
    render: function () {
        $(this.el).html(this.template());
        return this;
    },
});

App.chromeView = new App.ChromeView({ el : document.body });
App.chromeView.render();
4
j040p3d20

JQueryを使用することで、自分に合ったソリューションを見つけました。

JQuery.load()メソッドを使用して、アンダースコアテンプレートコードをメインのHTMLファイルに追加します。

それができたら、テンプレートの生成に使用します。すべてが同期して発生する必要があります!

概念は:

アンダースコアマップテンプレートコードがあります。

<!-- MAP TEMPLATE-->
<script type="text/template" id="game-map-template">
    <% _.each(rc, function(rowItem, index){ %>
      <ul class="map-row" data-row="<%- index %>">
        <li class="map-col <%- colItem.areaType ? 'active-area' : '' %>"></li>
        ...
</script>

そして、そのコードをmap-template.htmlというファイルに入れました

その後、テンプレートファイルのラッパーを作成します。

<div id="templatesPool"></div>

次に、そのようなファイルをメインのhtmlファイルに含めます。

頭の中:

<!-- Template Loader -->
<script> 
    $(function(){
      $("#templatesPool").append($('<div>').load("map-template.html")); 
    });
</script> 

乾杯。

2

私はこの質問が本当に古いことを知っていますが、アンダースコアajaxテンプレートのGoogle検索の最初の結果として出てきました。

私はこれに対する良い解決策を見つけられないことにうんざりしていたので、自分で作成しました:

https://github.com/ziad-saab/underscore-async-templates

AJAXを使用してアンダースコアテンプレートを読み込むことに加えて、<%include%>機能を追加します。それが誰かに役立つことを願っています。

1
ziad-saab

前方警告-ここにドラゴンがいる:

ASP.NETスタック(および同様のフレームワーク)をjs-libsのエコシステムと調和させるために苦労している人々を助けるために、以下に示すアプローチに言及します。これが一般的なソリューションではないことは言うまでもありません。そうは言っても ...

/ endforwardwarning

ASP.NETを使用している場合、テンプレートを1つ以上の独自の部分ビュー内に配置するだけで、テンプレートを外部化できます。 .cshtml内の別名:

  @Html.Partial("path/to/template")

Template.cshtml内:

   // this is razorview and thusly if you ever need to use the @ character in here  
   // you will have to either escape it as @@ or use the html codepoint which is &#64
   // http://stackoverflow.com/questions/3626250/escape-character-in-razor-view-engine
   <script type="text/x-template" id="someId">
        <span class="foo"><%= name %></span>
   </script>

そして今、あなたはいつものようにテンプレートを使用することができます:

  _.template($("#someId").html())({ name: "Foobar" });

このとらえどころのない明白なアプローチが、誰かが1時間分の頭を悩ませるのを助けてくれることを願っています。

0
XDS

JQueryを同期的に機能させるのは少し不安だったので、promiseを使用して前の同期の例を変更しました。ほぼ同じですが、非同期で実行されます。この例では、hbsテンプレートを使用しています。

var asyncRenderHbs= function(template_name, template_data) {
    if (!asyncRenderHbs.template_cache) { 
        asyncRenderHbs.template_cache= {};
    }

    var promise= undefined;

    if (!asyncRenderHbs.template_cache[template_name]) {
        promise= new Promise(function(resolve, reject) {
            var template_url= '/templates/' + template_name;
            $.ajax({
                url: template_url,
                method: 'GET',
                success: function(data) {
                    asyncRenderHbs.template_cache[template_name]= Handlebars.compile(data);
                    resolve(asyncRenderHbs.template_cache[template_name](template_data));
                },
                error: function(err, message) {
                    reject(err);
                }           
            });
        });
    } else {
        promise= Promise.resolve(asyncRenderHbs.template_cache[template_name](template_data));
    }

    return promise;
};

次に、レンダリングされたhtmlを使用するには:

asyncRenderHbs('some_template.hbs', context)
    .then(function(html) {
        applicationMain.append(html);
        // Do other stuff here after html is rendered...
    })
    .catch(function(err) {
        // Handle errors
    });

注:他の人が説明したように、すべてのテンプレートを単一のtemplates.jsファイルにコンパイルし、最初にロードする方が、Webページのロード時にテンプレートを取得する小さな同期AJAX呼び出しを多数持つよりも望ましいでしょう。

0
Megatron