Esiste una best practice per la generazione di HTML con javascript


103

Sto chiamando un servizio Web che restituisce un array di oggetti in JSON. Voglio prendere quegli oggetti e popolare un div con HTML. Supponiamo che ogni oggetto contenga un URL e un nome.

Se volessi generare il seguente HTML per ogni oggetto:

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

Esiste una best practice per questo? Posso vedere alcuni modi per farlo:

  1. Stringhe concatenate
  2. Crea elementi
  3. Usa un plugin per la creazione di modelli
  4. Genera l'html sul server, quindi pubblica tramite JSON.

1
Puoi anche controllare il carattere di sottolineatura js: documentcloud.github.com/underscore/#template Suona molto bene con backbone.js
luacassus

La scelta può variare da 1 a 4: dipende dalla quantità di contenuto da iniettare (preferisci 4 per maggiori) quante parti html diverse dovranno essere aggiunte in totale (3 o 4). ciò che Sai Baba conosce. (Influenza nel tempo di sviluppo). Se non conosci nessuno strumento è solo un piccolo modale che verrà iniettato una volta che non conosco un modo migliore del puro js per farlo (1-2)
partizanos

Risposte:


68

Le opzioni n. 1 e n. 2 saranno le tue opzioni più immediate, tuttavia, per entrambe le opzioni, sentirai l'impatto sulle prestazioni e sulla manutenzione costruendo stringhe o creando oggetti DOM.

I modelli non sono poi così immaturi e li vedi popup nella maggior parte dei principali framework Javascript.

Ecco un esempio in JQuery Template Plugin che ti farà risparmiare il calo delle prestazioni ed è davvero, molto semplice:

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

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

Io dico di seguire la strada giusta (e con prestazioni migliori, più manutenibile) e utilizzare i modelli.


13
Il templating di JQuery sembra essere morto, vedere stackoverflow.com/questions/7911732/…
James McMahon

4
@Jim Fiorato: il collegamento è morto: s
Adrien Be

2
Link è morto, come sottolinea Adrien. Ti suggerisco di aggiornare la tua risposta includendo: Moustache.js
Mr. Polywhirl

1
Qualcuno può spiegare, perché una risposta basata su jQuery è quella accettata? Dubito che questa sia la migliore pratica!
WoIIe

1
@WoIIe Ancora peggio, il plugin jQuery è morto, quindi questa risposta è obsoleta.
Franklin Yu

13

Se devi assolutamente concatenare le stringhe, invece del normale:

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

usa un array temporaneo:

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

L'utilizzo degli array è molto più veloce, specialmente in IE. Ho fatto alcuni test con le stringhe qualche tempo fa con IE7, Opera e FF. Opera ha impiegato solo 0,4 secondi per eseguire il test, ma IE7 non ha terminato dopo 20 MINUTI !!!! (No, non sto scherzando.) Con array IE è stato molto veloce.


Ho cambiato browser molto tempo fa, quindi non soffro più di tanto. IE era un browser orribile ma sta migliorando. Ma dubito che tornerò mai indietro.
alcuni il

1
La prestazione lenta vista nel primo metodo è probabile perché la stringa di risultato deve essere riallocata 200 volte e le allocazioni di memoria possono essere lente. Dopo due iterazioni hai "testingtesting". Dopo tre iterazioni, quella stringa viene eliminata e viene allocata memoria con spazio sufficiente per "testingtestingtesting". E così via 200 volte con lunghezza gradualmente crescente. Tuttavia, s.join () alloca come risultato una nuova stringa che è abbastanza lunga da adattarsi a tutte, quindi copia in ciascuna di esse. Un'allocazione, molto più veloce.
EricP

1
@ JoeCoder, d'accordo, è un algoritmo di Shlemiel The Painter. joelonsoftware.com/articles/fog0000000319.html
Jodrell

8

Una delle prime due opzioni è comune e accettabile.

Fornirò esempi di ciascuno in Prototype .

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

Approccio n. 1:

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

Approccio n. 2:

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

Compilare la generazione dell'HTML in modo esplicito con stringhe anziché con elementi DOM è più performante (supponendo che la concatenazione di stringhe non sia un vero problema) e leggibile.
Rodrick Chapman,

In IE la concatenazione di stringhe è sempre un problema. Usa invece un array.
alcuni

7

Forse un approccio più moderno consiste nell'usare un linguaggio di creazione di modelli come Moustache , che ha implementazioni in molte lingue, incluso javascript. Per esempio:

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

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

Ottieni anche un ulteriore vantaggio: puoi riutilizzare gli stessi modelli in altri luoghi, come il lato server.

Se hai bisogno di modelli più complicati (istruzioni if, loop, ecc.), Puoi utilizzare Handlebars che ha più funzionalità ed è compatibile con Moustache.


6

Ecco un esempio, utilizzando il mio plug-in Simple Templates per jQuery:

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

1
Neat. Avrei potuto usare qualcosa di simile a un grande progetto pochi mesi fa.
Rodrick Chapman,

Sì. Conciso e pulito!
ajitweb

4

Puoi aggiungere il modello HTML alla tua pagina in un div nascosto e quindi utilizzare cloneNode e le funzionalità di query della tua libreria preferita per popolarlo

/* 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

Divulgazione: sono il manutentore di BOB.

C'è una libreria javascript che rende questo processo molto più semplice chiamata BOB .

Per il tuo esempio specifico:

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

Questo può essere generato con BOB dal codice seguente.

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

O con la sintassi più breve

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

Questa libreria è abbastanza potente e può essere utilizzata per creare strutture molto complesse con inserimento dati (simile a d3), es .:

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 attualmente non supporta l'inserimento dei dati nel DOM. Questo è sulla todolist. Per ora puoi semplicemente usare l'output insieme al normale JS, o jQuery, e metterlo dove vuoi.

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

Ho creato questa libreria perché non ero soddisfatto di nessuna delle alternative come jquery e d3. Il codice è molto complicato e difficile da leggere. Lavorare con BOB è secondo me, che ovviamente è di parte, molto più piacevole.

BOB è disponibile su Bower , quindi puoi ottenerlo correndo bower install BOB.


2

Esiste una best practice per questo? Posso vedere alcuni modi per farlo:

  1. Stringhe concatenate
  2. Crea elementi
  3. Usa un plugin per la creazione di modelli
  4. Genera l'html sul server, quindi pubblica tramite JSON.

1) Questa è un'opzione. Crea l'html con JavaScript sul lato client e poi inseriscilo nel DOM nel suo complesso.

Si noti che c'è un paradigma dietro questo approccio: il server emette solo dati e (in caso di interazione) riceve i dati dal client in modo asincrono con le richieste AJAX. Il codice lato client opera come applicazione web JavaScript autonoma.

L'applicazione web può funzionare, rendere l'interfaccia, anche senza che il server sia attivo (ovviamente non mostrerà alcun dato né offrirà alcun tipo di interazione).

Questo paradigma viene adottato spesso ultimamente e interi framework sono costruiti attorno a questo approccio (vedere backbone.js per esempio).

2) Per motivi di prestazioni, quando possibile, è meglio costruire l'html in una stringa e poi iniettarlo nella sua interezza nella pagina.

3) Questa è un'altra opzione, così come l'adozione di un framework per applicazioni Web. Altri utenti hanno pubblicato vari motori di template disponibili. Ho l'impressione che tu abbia le capacità per valutarli e decidere se seguire o meno questa strada.

4) Un'altra opzione. Ma servilo come un semplice testo / html; perché JSON? Non mi piace questo approccio perché mescola PHP (la lingua del tuo server) con Html. Ma lo adotto spesso come un ragionevole compromesso tra l'opzione 1 e 4 .


La mia risposta: stai già guardando nella giusta direzione.

Suggerisco di adottare un approccio compreso tra 1 e 4 come faccio io. Altrimenti, adotta un framework web o un motore di modelli.

Solo la mia opinione basata sulla mia esperienza ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.