web-dev-qa-db-ger.com

Externe Vorlage im Unterstrich

Ich benutze nterstreichungsvorlage . Ist es möglich, eine externe Datei als Vorlage anzuhängen ?

In der Backbone-Ansicht habe ich:

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

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

In meinem HTML ist:

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

Es läuft gut. Aber Ich brauche eine externe Vorlage . Ich versuche:

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

oder

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

oder

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

aber es hat nicht funktioniert.

120
Tomáš

BEARBEITEN: Diese Antwort ist alt und veraltet. Ich würde sie löschen, aber es ist die "akzeptierte" Antwort. Ich werde stattdessen meine Meinung einbringen.

Ich würde dies nicht mehr befürworten. Stattdessen würde ich alle Vorlagen in einzelne HTML-Dateien aufteilen. Einige würden vorschlagen, diese asynchron zu laden (Require.js oder eine Art Vorlagen-Cache). Das funktioniert aber gut bei kleinen Projekten Bei großen Projekten mit vielen Vorlagen stellen Sie fest, dass Sie beim Laden von Seiten eine Menge kleiner asynchroner Anforderungen stellen, die ich nicht mag. (ugh ... ok, Sie können dies mit Require.js umgehen, indem Sie Ihre anfänglichen Abhängigkeiten mit vorkompilieren r.js, aber für Vorlagen fühlt sich das für mich immer noch falsch an)

Ich benutze gerne eine Grunt-Aufgabe (grunt-contrib-jst), um alle HTML-Vorlagen in eine einzige templates.js-Datei zu kompilieren und diese einzuschließen. Sie erhalten das Beste aus allen Welten, IMO ... Vorlagen leben in einer Datei, Kompilierung der genannten Vorlagen erfolgt zum Zeitpunkt der Erstellung (nicht zur Laufzeit), und Sie haben keine hundert winzigen asynchronen Anforderungen, wenn die Seite gestartet wird.

Alles unten ist Müll

Ich bevorzuge die Einfachheit, eine JS-Datei in meine Vorlage aufzunehmen. Ich könnte also eine Datei namens view_template.js erstellen, die die Vorlage als Variable enthält:

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

Dann ist es ganz einfach, die Skriptdatei wie eine normale einzuschließen und sie dann in Ihrer Ansicht zu verwenden:

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

Wenn ich noch einen Schritt weiter gehe, verwende ich tatsächlich Kaffeeskript, sodass mein Code eher so aussieht und die Escape-Zeichen am Zeilenende vermieden werden:

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

Mit diesem Ansatz vermeiden Sie das Einspielen von require.js, wenn dies wirklich nicht erforderlich ist.

51
Brian Genisio

Hier ist eine einfache Lösung:

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

Die Verwendung von "async: false" ist hier kein schlechter Weg, da Sie auf jeden Fall warten müssen, bis die Vorlage geladen wird.

Also "rendern" Funktion

  1. damit können Sie jede Vorlage in einer separaten HTML-Datei im statischen Verzeichnis speichern
  2. ist sehr leicht
  3. kompiliert und speichert Vorlagen
  4. ladelogik für Abstracts-Vorlagen. Beispielsweise können Sie in Zukunft vorinstallierte und vorkompilierte Vorlagen verwenden.
  5. ist einfach zu bedienen

[Ich bearbeite die Antwort, anstatt einen Kommentar zu hinterlassen, weil ich dies für wichtig halte.]

wenn Vorlagen in native App nicht angezeigt werden und Sie HIERARCHY_REQUEST_ERROR: DOM Exception 3, siehe Antwort von Dave Robinson auf Was genau kann einen "HIERARCHY_REQUEST_ERR: DOM Exception 3" -Fehler verursachen? .

Grundsätzlich müssen Sie hinzufügen

dataType: 'html'

auf die $ .ajax-Anfrage.

107
koorchik

Mit diesem Mixin können Sie externe Vorlagen mithilfe von Unterstrich auf sehr einfache Weise rendern: _.templateFromUrl(url, [data], [settings]). Die Methoden-API entspricht fast der Unterstreichung _. Template () . Caching inklusive.

_.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);
}});

Verwendung:

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

Ich wollte require.js nicht für diese einfache Aufgabe verwenden, also habe ich die modifizierte koorchik-Lösung verwendet.

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

Warum Vorlagen an ein Dokument anhängen, anstatt sie in einem Javascript-Objekt zu speichern? Da ich in der Produktionsversion eine HTML-Datei mit allen bereits enthaltenen Vorlagen generieren möchte, muss ich keine zusätzlichen Ajax-Anforderungen stellen. Und in der gleichen Zeit muss ich in meinem Code kein Refactoring vornehmen, wie ich es benutze

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

in meinen Backbone-Ansichten.

17
Tyth

Dies ist möglicherweise ein wenig ungewöhnlich, aber Sie können Grunt (http://gruntjs.com/) verwenden, das auf node.js (http://nodejs.org/, verfügbar für alle wichtigen Plattformen) ausgeführt wird, um Aufgaben von der auszuführen Befehlszeile. Es gibt eine Reihe von Plugins für dieses Tool, wie zum Beispiel einen Template-Compiler https://npmjs.org/package/grunt-contrib-jst . Siehe Dokumentation zu GitHub, https://github.com/gruntjs/grunt-contrib-jst . (Sie müssen auch verstehen, wie der Node Package Manager ausgeführt wird, https://npmjs.org/ . Keine Sorge, es ist unglaublich einfach und vielseitig.)

Sie können dann alle Ihre Vorlagen in separaten HTML-Dateien speichern und das Tool ausführen, um sie alle mit einem Unterstrich vorzukompilieren (was meiner Meinung nach eine Abhängigkeit für das JST-Plugin darstellt, aber keine Sorge, der Node Package Manager installiert Abhängigkeiten automatisch für Sie).

So werden beispielsweise alle Ihre Vorlagen zu einem Skript zusammengefasst

templates.js

Durch das Laden des Skripts wird ein globales "JST" festgelegt, das eine Reihe von Funktionen darstellt und wie folgt aufgerufen werden kann:

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

das wäre ähnlich wie

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

wenn Sie den Inhalt dieses Skript-Tags in (templates /) listView.html einfügen

Der eigentliche Kicker ist jedoch: Grunt wird mit der Aufgabe 'watch' ausgeliefert, die im Grunde genommen Änderungen an Dateien überwacht, die Sie in Ihrer lokalen Datei grunt.js definiert haben (im Grunde genommen eine Konfigurationsdatei für Ihr Grunt-Projekt in Javascript) ). Wenn Sie grunzen haben, starten Sie diese Aufgabe für Sie, indem Sie Folgendes eingeben:

grunt watch

über die Befehlszeile überwacht Grunt alle Änderungen, die Sie an den Dateien vornehmen, und führt automatisch alle Aufgaben aus, die Sie in der Datei grunt.js dafür eingerichtet haben, wenn Änderungen festgestellt werden - wie z. B. die jst Aufgabe oben beschrieben. Bearbeiten und speichern Sie Ihre Dateien, und alle Ihre Vorlagen werden in eine einzige js-Datei kompiliert, auch wenn sie auf mehrere Verzeichnisse und Unterverzeichnisse verteilt sind.

Ähnliche Aufgaben können konfiguriert werden, um Ihr Javascript zu löschen, Tests auszuführen, Ihre Skriptdateien zu verketten und zu verkleinern/verkleinern. Und alles kann mit der Überwachungsaufgabe verknüpft werden, sodass Änderungen an Ihren Dateien automatisch einen neuen Build Ihres Projekts auslösen.

Es braucht einige Zeit, um die Dinge einzurichten und zu verstehen, wie die grunt.js-Datei konfiguriert wird, aber es ist die investierte Zeit wert, und ich glaube, Sie werden nie wieder zu einer Arbeitsweise vor dem Grunzen zurückkehren

16
Mansiemans

Ich denke dies ist das, was dir helfen könnte. Alles in der Lösung dreht sich um require.js Bibliothek, die eine JavaScript-Datei und ein Modullader ist.

Das Tutorial unter dem obigen Link zeigt sehr gut, wie ein Backbone-Projekt organisiert werden kann. Ein Beispielimplementierung wird ebenfalls bereitgestellt. Hoffe das hilft.

15
nayaab

Ich musste den Datentyp auf "Text" setzen, damit es für mich funktioniert:

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

Ich habe mich für JavaScript-Vorlagen interessiert und mache jetzt die ersten Schritte mit Backbone. Das habe ich mir ausgedacht und es scheint ziemlich gut zu funktionieren.

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

Ich habe eine Lösung gefunden, die für mich mit jQuery funktioniert.

Ich füge den Unterstrich-Vorlagencode mit der Methode jQuery.load () zur HTML-Hauptdatei hinzu.

Sobald es dort ist, benutze ich es zum Generieren der Vorlagen. Alles muss synchron geschehen!

Das Konzept lautet:

Ich habe einen Kartenvorlagencode mit Unterstrich:

<!-- 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>

Und ich habe diesen Code in eine Datei namens map-template.html geschrieben

Danach erstelle ich einen Wrapper für die Vorlagendateien.

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

Dann füge ich diese Datei wie folgt in meine HTML-Hauptdatei ein.

Im Kopf:

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

Prost.

2

Ich weiß, dass diese Frage wirklich alt ist, aber sie tauchte als erstes Ergebnis einer Google-Suche nach Ajax-Vorlagen mit Unterstreichungszeichen auf.

Ich war es leid, keine gute Lösung dafür zu finden, also habe ich meine eigene erstellt:

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

Zusätzlich zum Laden von Unterstrich-Vorlagen mit AJAX wird die Funktionalität <% include%> hinzugefügt. Ich hoffe, es kann jemandem nützlich sein.

1
ziad-saab

Vorwarnung - Hier seid Drachen:

Ich erwähne den unten gezeigten Ansatz, um denjenigen zu helfen, die Schwierigkeiten haben, ASP.NET-Stacks (und ähnliche Frameworks) in Einklang mit dem Ökosystem von js-libs zu bringen. Es versteht sich von selbst, dass dies keine generische Lösung ist. Davon abgesehen ...

/ endforwardwarning

Wenn Sie ASP.NET verwenden, können Sie Ihre Vorlagen einfach auslagern, indem Sie sie in eine oder mehrere eigene Teilansichten einfügen. Aka in deinem .cshtml:

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

In Ihrer 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>

Und jetzt können Sie die Vorlage wie gewohnt verwenden:

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

Hoffe, dass dieser schwer fassbare Ansatz jemandem hilft, eine Stunde Kopfkratzen zu sparen.

0
XDS

Es war mir ein bisschen unangenehm, jQuery dazu zu zwingen, synchron zu funktionieren, deshalb habe ich das vorherige synchrone Beispiel mit Versprechungen modifiziert. Es ist so ziemlich dasselbe, läuft aber asynchron. In diesem Beispiel verwende ich hbs-Vorlagen:

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

Dann verwenden Sie das gerenderte 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
    });

ANMERKUNG: Wie von anderen beschrieben, ist es vorzuziehen, alle Vorlagen in eine einzige templates.js-Datei zu kompilieren und diese am Anfang zu laden, anstatt viele kleine synchrone AJAX Aufrufe zum Abrufen von Vorlagen zu haben, wenn das Die Webseite wird geladen.

0
Megatron