Czy jest najlepsza praktyka generowania kodu HTML za pomocą javascript

103

Wywołuję usługę internetową, która zwraca tablicę obiektów w formacie JSON. Chcę wziąć te obiekty i wypełnić div za pomocą HTML. Powiedzmy, że każdy obiekt zawiera adres URL i nazwę.

Gdybym chciał wygenerować następujący kod HTML dla każdego obiektu:

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

Czy istnieje najlepsza praktyka? Widzę kilka sposobów na zrobienie tego:

  1. Połącz ciągi
  2. Twórz elementy
  3. Użyj wtyczki do tworzenia szablonów
  4. Wygeneruj kod HTML na serwerze, a następnie wyświetl go za pomocą formatu JSON.
ckarbass
źródło
1
Możesz też sprawdzić underscore js: documentcloud.github.com/underscore/#template Bardzo ładnie gra z backbone.js
luacassus
Wybór 1-4: zależy od tego, ile treści ma zostać wstrzyknięte. (Najlepiej 4 dla większych), ile różnych części html będzie trzeba w sumie dołączyć (3 lub 4). co ktoś zna. (Wpływ w czasie deweloperskim). Jeśli nie znasz żadnych narzędzi, to tylko mały modal, który zostanie wstrzyknięty, gdy nie znam lepszego sposobu niż czysty js (1-2)
partizanos

Odpowiedzi:

68

Opcje # 1 i # 2 będą twoimi najbardziej bezpośrednimi opcjami, jednak w przypadku obu opcji będziesz odczuwać wpływ na wydajność i konserwację, budując ciągi znaków lub tworząc obiekty DOM.

Tworzenie szablonów nie jest wcale takie niedojrzałe i widzisz je wyskakujące w większości głównych frameworków Javascript.

Oto przykład wtyczki szablonu JQuery , która pozwoli Ci zaoszczędzić wydajność i jest naprawdę, bardzo prosta:

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

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

Mówię, idź fajną drogą (i lepszą wydajnością, łatwiejszą w utrzymaniu) i używaj szablonów.

Jim Fiorato
źródło
13
Wydaje się, że szablony JQuery nie działają, patrz stackoverflow.com/questions/7911732/ ...
James McMahon
4
@Jim Fiorato: link nie żyje: s
Adrien Be
2
Link nie żyje, jak wskazuje Adrien. Zaproponuj zaktualizowanie odpowiedzi tak, aby zawierała: Mustache.js
Mr. Polywhirl,
1
Czy ktoś mógłby wyjaśnić, dlaczego odpowiedź oparta na jQuery jest akceptowana? Wątpię, czy to najlepsza praktyka!
WoIIe
1
@WoIIe Co gorsza, wtyczka jQuery jest martwa, więc ta odpowiedź jest nieaktualna.
Franklin Yu
13

Jeśli absolutnie musisz połączyć ciągi znaków zamiast normalnych:

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

użyj tymczasowej tablicy:

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

Używanie tablic jest znacznie szybsze, szczególnie w IE. Jakiś czas temu przeprowadziłem testy ze stringami w IE7, Opera i FF. Opera zajęła tylko 0,4 sekundy, aby przeprowadzić test, ale IE7 nie skończył po 20 MINUTACH !!!! (Nie, nie żartuję.) Z tablicą IE był bardzo szybki.

trochę
źródło
Dawno temu zmieniłem przeglądarkę, więc nie cierpię tak bardzo. IE była okropną przeglądarką, ale jest coraz lepsza. Ale wątpię, czy kiedykolwiek się zmienię.
jakiś
1
Niska wydajność widoczna w pierwszej metodzie jest prawdopodobna, ponieważ ciąg wynikowy musi zostać ponownie przydzielony 200 razy, a alokacje pamięci mogą być powolne. Po dwóch iteracjach masz „testingtesting”. Po trzech iteracjach ten łańcuch jest wyrzucany i przydzielana jest pamięć z wystarczającą ilością miejsca na „testingtestingtesting”. I tak dalej 200 razy ze stopniowo zwiększającą się długością. Jednak s.join () alokuje jeden nowy ciąg w wyniku, który jest wystarczająco długi, aby zmieścić je wszystkie, a następnie kopiuje każdy z nich. Jedna alokacja, dużo szybciej.
EricP
1
@JoeCoder, zgodził się, to algorytm Shlemiel The Painter. joelonsoftware.com/articles/fog0000000319.html
Jodrell
8

Każda z dwóch pierwszych opcji jest zarówno powszechna, jak i akceptowalna.

Podam przykłady każdego z nich w Prototype .

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

Podejście nr 1:

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

Podejście nr 2:

var div = new Element('div');
div.insert( new Element('img', { src: json.src }) );
div.insert(" " + json.name);
$('container').insert(div); // inserts at bottom
savetheclocktower
źródło
Tworzenie kodu HTML jawnie przy użyciu ciągów znaków zamiast elementów DOM jest bardziej wydajne (zakładając, że łączenie ciągów nie jest prawdziwym problemem) i czytelne.
Rodrick Chapman
W IE zawsze problemem jest konkatenacja ciągów znaków. Zamiast tego użyj tablicy.
jakieś
7

Być może bardziej nowoczesnym podejściem jest użycie języka szablonów, takiego jak Mustache , który ma implementacje w wielu językach, w tym w javascript. Na przykład:

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

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

Otrzymujesz nawet dodatkową korzyść - możesz ponownie użyć tych samych szablonów w innych miejscach, na przykład po stronie serwera.

Jeśli potrzebujesz bardziej skomplikowanych szablonów (instrukcje if, pętle itp.), Możesz użyć Handlebars, który ma więcej funkcji i jest kompatybilny z Mustache.

Tzach
źródło
6

Oto przykład użycia mojej wtyczki Simple Templates dla jQuery:

var tmpl = '<div class="#{classname}">#{content}</div>';
var vals = {
    classname : 'my-class',
    content   : 'This is my content.'
};
var html = $.tmpl(tmpl, vals);
Andrew Hedges
źródło
1
Schludny. Mogłem użyć czegoś podobnego do dużego projektu kilka miesięcy temu.
Rodrick Chapman
Tak. Zwięzłe i schludne!
ajitweb
4

Możesz dodać szablon HTML do swojej strony w ukrytym div, a następnie użyć cloneNode i funkcji zapytań swojej ulubionej biblioteki, aby go wypełnić

/* 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*/})
Lew
źródło
3

Ujawnienie: jestem opiekunem BOB.

Istnieje biblioteka javascript, która znacznie ułatwia ten proces, zwana BOB .

Twój konkretny przykład:

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

Można to wygenerować za pomocą BOB za pomocą następującego kodu.

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

Lub z krótszą składnią

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

Ta biblioteka jest dość potężna i może być używana do tworzenia bardzo złożonych struktur z wprowadzaniem danych (podobnie do d3), np .:

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 obecnie nie obsługuje wprowadzania danych do DOM. To jest na liście rzeczy do zrobienia. Na razie możesz po prostu użyć wyniku razem z normalnym JS lub jQuery i umieścić go w dowolnym miejscu.

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

Zrobiłem tę bibliotekę, ponieważ nie podobała mi się żadna z alternatyw, takich jak jquery i d3. Kod bardzo skomplikowany i trudny do odczytania. Praca z BOBem jest moim zdaniem, co jest oczywiście stronnicze, dużo przyjemniejsza.

BOB jest dostępny na Bower , więc możesz go zdobyć biegając bower install BOB.

Automatico
źródło
2

Czy istnieje najlepsza praktyka? Widzę kilka sposobów na zrobienie tego:

  1. Połącz ciągi
  2. Twórz elementy
  3. Użyj wtyczki do tworzenia szablonów
  4. Wygeneruj kod HTML na serwerze, a następnie wyświetl go za pomocą formatu JSON.

1) To jest opcja. Zbuduj kod HTML za pomocą JavaScript po stronie klienta, a następnie wstaw go do DOM jako całości.

Zauważ, że za tym podejściem kryje się paradygmat: serwer generuje tylko dane i (w przypadku interakcji) otrzymuje dane od klienta asynchronicznie z żądaniami AJAX. Kod po stronie klienta działa jako samodzielna aplikacja internetowa JavaScript.

Aplikacja internetowa może działać, renderować interfejs nawet bez włączonego serwera (oczywiście nie wyświetla żadnych danych ani nie oferuje żadnej interakcji).

Ten paradygmat jest ostatnio często przyjmowany i całe frameworki są budowane wokół tego podejścia (patrz na przykład backbone.js).

2) Ze względu na wydajność, jeśli to możliwe, lepiej jest zbudować kod HTML w ciągu znaków, a następnie wstrzyknąć go jako całość na stronę.

3) Jest to kolejna opcja, poza przyjęciem struktury aplikacji sieci Web. Inni użytkownicy opublikowali różne dostępne silniki szablonów. Mam wrażenie, że masz umiejętności ich oceny i podjęcia decyzji, czy podążać tą ścieżką, czy nie.

4) Inna opcja. Ale podawaj to jako zwykły tekst / html; dlaczego JSON? Nie podoba mi się to podejście, ponieważ łączy PHP (język twojego serwera) z Html. Ale często uważam to za rozsądny kompromis między opcją 1 i 4 .


Moja odpowiedź: już patrzysz we właściwym kierunku.

Proponuję przyjąć podejście od 1 do 4 tak jak ja. W przeciwnym razie zastosuj framework sieciowy lub silnik szablonów.

Tylko moja opinia oparta na moim doświadczeniu ...

Paolo
źródło