Gibt es eine bewährte Methode zum Generieren von HTML mit Javascript?


103

Ich rufe einen Webdienst auf, der ein Array von Objekten in JSON zurückgibt. Ich möchte diese Objekte nehmen und ein Div mit HTML füllen. Angenommen, jedes Objekt enthält eine URL und einen Namen.

Wenn ich für jedes Objekt den folgenden HTML-Code generieren wollte:

<div><img src="the url" />the name</div>

Gibt es dafür eine bewährte Methode? Ich kann ein paar Möglichkeiten sehen:

  1. Verketten Sie Zeichenfolgen
  2. Elemente erstellen
  3. Verwenden Sie ein Vorlagen-Plugin
  4. Generieren Sie das HTML auf dem Server und stellen Sie es dann über JSON bereit.

1
Sie können auch den Unterstrich js überprüfen: documentcloud.github.com/underscore/#template Es spielt sich sehr gut mit backbone.js
luacassus

Die Auswahl zwischen 1 und 4: hängt davon ab, wie viel Inhalt injiziert werden soll (bevorzugen Sie 4 für größere), wie viele verschiedene HTML-Teile insgesamt angehängt werden müssen (3 oder 4). was jdn vertraut ist. (Einfluss auf die Entwicklungszeit). Wenn Sie keine Werkzeuge kennen, ist es nur ein kleines Modal, das injiziert wird, sobald ich nicht weiß, wie ich es besser machen kann als reine js (1-2)
partizanos

Antworten:


68

Die Optionen 1 und 2 sind Ihre unmittelbarsten Optionen. Bei beiden Optionen werden Sie jedoch die Auswirkungen auf Leistung und Wartung spüren, indem Sie entweder Zeichenfolgen erstellen oder DOM-Objekte erstellen.

Vorlagen sind nicht allzu unausgereift, und Sie sehen, dass sie in den meisten wichtigen Javascript-Frameworks angezeigt werden.

Hier ist ein Beispiel im JQuery Template Plugin , das Ihnen den Leistungseinbruch erspart und wirklich sehr, sehr einfach ist:

var t = $.template('<div><img src="${url}" />${name}</div>');

$(selector).append( t , {
     url: jsonObj.url,
     name: jsonObj.name
});

Ich sage, gehen Sie den coolen Weg (und leistungsfähiger, wartbarer) und verwenden Sie Vorlagen.


13
JQuery Templating scheint tot zu sein, siehe stackoverflow.com/questions/7911732/…
James McMahon

4
@ Jim Fiorato: Der Link ist tot: s
Adrien Be

2
Link ist tot, wie Adrien betont. Schlagen Sie vor, Ihre Antwort so zu aktualisieren, dass sie
Folgendes

1
Kann jemand bitte erklären, warum eine jQuery-basierte Antwort akzeptiert wird? Ich bezweifle, dass dies die beste Vorgehensweise ist!
WoIIe

1
@WoIIe Schlimmer noch, das jQuery-Plugin ist tot, daher ist diese Antwort veraltet.
Franklin Yu

13

Wenn Sie unbedingt Zeichenfolgen anstelle der normalen verketten müssen:

var s="";
for (var i=0; i < 200; ++i) {s += "testing"; }

Verwenden Sie ein temporäres Array:

var s=[];
for (var i=0; i < 200; ++i) { s.push("testing"); }
s = s.join("");

Die Verwendung von Arrays ist viel schneller, insbesondere im IE. Ich habe vor einiger Zeit einige Tests mit Strings mit IE7, Opera und FF durchgeführt. Opera brauchte nur 0,4 Sekunden, um den Test durchzuführen, aber IE7 war nach 20 Minuten noch nicht fertig !!!! (Nein, ich mache keine Witze.) Mit Array war IE sehr schnell.


Ich habe vor langer Zeit den Browser gewechselt, deshalb leide ich nicht so sehr. IE war ein schrecklicher Browser, aber es wird besser. Aber ich bezweifle, dass ich jemals zurückkehren werde.
einige

1
Die langsame Leistung der ersten Methode ist wahrscheinlich darauf zurückzuführen, dass die Ergebniszeichenfolge 200 Mal neu zugewiesen werden muss und die Speicherzuweisungen langsam sein können. Nach zwei Iterationen haben Sie "Testtesting". Nach drei Iterationen wird diese Zeichenfolge weggeworfen und Speicher mit genügend Platz für "testingtestingtesting" zugewiesen. Und so weiter 200 mal mit allmählich zunehmender Länge. An join () wird jedoch eine neue Zeichenfolge zugewiesen, die lang genug ist, um alle zu erfüllen, und dann in jede kopiert. Eine Zuordnung, viel schneller.
EricP

1
@ JoeCoder, stimmte zu, es ist ein Shlemiel The Painter-Algorithmus. joelonsoftware.com/articles/fog0000000319.html
Jodrell

8

Jede der beiden ersten Optionen ist allgemein und akzeptabel.

Ich werde Beispiele für jeden einzelnen in Prototype geben .

// assuming JSON looks like this:
// { 'src': 'foo/bar.jpg', 'name': 'Lorem ipsum' }

Ansatz 1:

var html = "<div><img src='#{src}' /> #{name}</div>".interpolate(json);
$('container').insert(html); // inserts at bottom

Ansatz 2:

var div = new Element('div');
div.insert( new Element('img', { src: json.src }) );
div.insert(" " + json.name);
$('container').insert(div); // inserts at bottom

Das explizite Generieren des HTML-Codes mit Zeichenfolgen anstelle von DOM-Elementen ist leistungsfähiger (vorausgesetzt, die Verkettung von Zeichenfolgen ist kein echtes Problem) und lesbar.
Rodrick Chapman

Im IE ist die Verkettung von Zeichenfolgen immer ein Problem. Verwenden Sie stattdessen ein Array.
einige

7

Ein moderner Ansatz besteht möglicherweise darin, eine Vorlagensprache wie Moustache zu verwenden , die in vielen Sprachen implementiert ist, einschließlich Javascript. Beispielsweise:

var view = {
  url: "/hello",
  name: function () {
    return 'Jo' + 'hn';
  }
};

var output = Mustache.render('<div><img src="{{url}}" />{{name}}</div>', view);

Sie erhalten sogar einen zusätzlichen Vorteil: Sie können dieselben Vorlagen an anderen Stellen, z. B. auf der Serverseite, wiederverwenden.

Wenn Sie kompliziertere Vorlagen benötigen (if-Anweisungen, Schleifen usw.), können Sie Lenker verwenden, die über mehr Funktionen verfügen und mit Moustache kompatibel sind.


6

Hier ist ein Beispiel für die Verwendung meines Plug-Ins für einfache Vorlagen für jQuery:

var tmpl = '<div class="#{classname}">#{content}</div>';
var vals = {
    classname : 'my-class',
    content   : 'This is my content.'
};
var html = $.tmpl(tmpl, vals);

1
Ordentlich. Ich hätte etwas verwenden können, das vor ein paar Monaten für ein großes Projekt geeignet war.
Rodrick Chapman

Ja. Prägnant und ordentlich!
Ajitweb

4

Sie können die HTML-Vorlage in einem ausgeblendeten Div zu Ihrer Seite hinzufügen und dann cloneNode und die Abfragefunktionen Ihrer Lieblingsbibliothek verwenden, um sie zu füllen

/* CSS */
.template {display:none;}

<!--HTML-->
<div class="template">
  <div class="container">
    <h1></h1>
    <img src="" alt="" />
  </div>
</div>

/*Javascript (using Prototype)*/
var copy = $$(".template .container")[0].cloneNode(true);
myElement.appendChild(copy);
$(copy).select("h1").each(function(e) {/*do stuff to h1*/})
$(copy).select("img").each(function(e) {/*do stuff to img*/})

3

Offenlegung: Ich bin der Betreuer von BOB.

Es gibt eine Javascript-Bibliothek namens BOB , die diesen Prozess erheblich vereinfacht .

Für Ihr spezielles Beispiel:

<div><img src="the url" />the name</div>

Dies kann mit BOB durch den folgenden Code generiert werden.

new BOB("div").insert("img",{"src":"the url"}).up().content("the name").toString()
//=> "<div><img src="the url" />the name</div>"

Oder mit der kürzeren Syntax

new BOB("div").i("img",{"src":"the url"}).up().co("the name").s()
//=> "<div><img src="the url" />the name</div>"

Diese Bibliothek ist sehr leistungsfähig und kann verwendet werden, um sehr komplexe Strukturen mit Dateneinfügung (ähnlich wie d3) zu erstellen, z.

data = [1,2,3,4,5,6,7]
new BOB("div").i("ul#count").do(data).i("li.number").co(BOB.d).up().up().a("a",{"href": "www.google.com"}).s()
//=> "<div><ul id="count"><li class="number">1</li><li class="number">2</li><li class="number">3</li><li class="number">4</li><li class="number">5</li><li class="number">6</li><li class="number">7</li></ul></div><a href="www.google.com"></a>"

BOB unterstützt derzeit nicht das Injizieren der Daten in das DOM. Dies ist auf der todolist. Im Moment können Sie die Ausgabe einfach zusammen mit normalem JS oder jQuery verwenden und an einer beliebigen Stelle ablegen.

document.getElementById("parent").innerHTML = new BOB("div").insert("img",{"src":"the url"}).up().content("the name").s();
//Or jquery:
$("#parent").append(new BOB("div").insert("img",{"src":"the url"}).up().content("the name").s());

Ich habe diese Bibliothek erstellt, weil ich mit keiner der Alternativen wie jquery und d3 zufrieden war. Der Code ist sehr kompliziert und schwer zu lesen. Die Arbeit mit BOB ist meiner Meinung nach, was offensichtlich voreingenommen ist, viel angenehmer.

BOB ist auf Bower verfügbar , sodass Sie es durch Ausführen erhalten können bower install BOB.


2

Gibt es dafür eine bewährte Methode? Ich kann ein paar Möglichkeiten sehen:

  1. Verketten Sie Zeichenfolgen
  2. Elemente erstellen
  3. Verwenden Sie ein Vorlagen-Plugin
  4. Generieren Sie das HTML auf dem Server und stellen Sie es dann über JSON bereit.

1) Dies ist eine Option. Erstellen Sie das HTML mit JavaScript auf der Clientseite und fügen Sie es dann in das gesamte DOM ein.

Beachten Sie, dass hinter diesem Ansatz ein Paradigma steckt: Der Server gibt nur Daten aus und empfängt (im Falle einer Interaktion) Daten vom Client asynchron mit AJAX-Anforderungen. Der clientseitige Code wird als eigenständige JavaScript-Webanwendung ausgeführt.

Die Webanwendung kann funktionieren, die Benutzeroberfläche rendern, auch ohne dass der Server aktiv ist (natürlich werden keine Daten angezeigt oder Interaktionen angeboten).

Dieses Paradigma wird in letzter Zeit häufig übernommen, und ganze Frameworks bauen auf diesem Ansatz auf (siehe beispielsweise backbone.js).

2) Aus Leistungsgründen ist es nach Möglichkeit besser, den HTML-Code in einer Zeichenfolge zu erstellen und ihn dann als Ganzes in die Seite einzufügen.

3) Dies ist eine weitere Option sowie die Übernahme eines Webanwendungsframeworks. Andere Benutzer haben verschiedene verfügbare Template-Engines veröffentlicht. Ich habe den Eindruck, dass Sie die Fähigkeiten haben, sie zu bewerten und zu entscheiden, ob Sie diesem Weg folgen oder nicht.

4) Eine weitere Option. Aber dienen Sie es als Klartext / HTML; warum JSON? Ich mag diesen Ansatz nicht, weil er PHP (Ihre Serversprache) mit HTML mischt. Aber ich nehme es oft als vernünftigen Kompromiss zwischen Option 1 und 4 an .


Meine Antwort: Sie schauen bereits in die richtige Richtung.

Ich schlage vor, einen Ansatz zwischen 1 und 4 zu wählen wie ich wählen. Verwenden Sie andernfalls ein Webframework oder eine Template-Engine.

Nur meine Meinung basiert auf meiner Erfahrung ...

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.