Handlebars.js Tutorial: Templates in JavaScript

27. Oktober 2013 · Kategorien: Internet, JavaScript, Webentwicklung

Handlebars.js

Handlebars.js ist ein leicht zu erlernendes JavaScript-Framework, das Templates in JavaScript ermöglicht. In diesem Tutorial lernst Du nicht nur Handlebars.js kennen, sondern auch, wann Du es am besten einsetzt.

Handlebars.js: Wozu JavaScript Templates?

Durch den Wunsch nach einem interaktiven Web und dem zunehmendem Zusammenfließen von Applikationen und Webseiten wird JavaScript zunehmend eingesetzt.
Hatte JavaScript vor einigen Jahren noch die Aufgabe, Submit-Buttons nach Klick zu deaktivieren und lustige Bildchen dem Mauszeiger folgen zu lassen, trägt es heute oftmals stark der Logik der Webseite bei.
Das erfordert eine bessere Struktur des JavaScript-Codes. Eine wilde Verteilung von Script-Tags quer im HTML-Code würde zum Chaos führen.
Da sich das MVC-Pattern bereits in anderen Sprachen wie PHP bewährt hat, versuchen viele Entwickler, es auf JavaScript zu übertragen. Daraus entstanden diverse JavaScript-Frameworks wie zum Beispiel Backbone.js oder Ember.js.
Letzteres, über das ich ebenfalls einen Artikel geschrieben habe, benutzt für die View-Komponente des MVC-Patterns Handlebars.js.
Kurz gesagt: JavaScript Templates sind notwendig, um Struktur in Deinem JavaScript-Code zu ermöglichen.

Ein schlechtes Beispiel – ohne Handlebars.js:

<table id="my-table">
  <tr>
    <td>1<td>
  </tr>
</table>
<input type="button" id="add-button" value="add"/>

<script type="text/javascript">
    $('#add-button').click(function() {
      var table = $('#my-table');
      var trCount = ++table.find('tr').length;
      var tr = $('<tr />').html('<td>'+trCount+'<td');
      table.append(tr);
    });
</script>

Was macht dieser Code? Nach Klick auf den Button mit der ID add-button wird der Tabelle mit der ID my-table eine Zeile hinzugefügt. Die entsprechende Zeile enthält die Anzahl an Zeilen der Tabelle.
Warum ist dieser Code schlecht? Weil der Code, der der Logik der Applikation dient – nämlich das Hinzufügen einer neuen Zeile – mit dem Code, der der Anzeige der Applikation dient – also die Tabellenzeilen und -zellen <tr> und <td> – vermischt ist. Das ist also kein MVC.

Handlebars.js Template – Ein Beispiel

Templates werden in Handlebars.js in einem Script-Tag untergebracht, also genauso wie JavaScript.
Um Script-Tags für JavaScript von Script-Tags für Handlebars.js zu unterscheiden, verwenden wir das type-Attribut. Viele Entwickler lassen dieses Attribut gerne weg, der Ordnung halber solltest Du dir aber angewöhnen, es immer zu benutzen:

<script type="text/javascript">
  ... JavaScript-Code ...
</script>

<script type="text/x-handlebars-template">
  ... Handlebars.js-Code ...
</script>

Mit folgendem Beispiel geben wir Hallo, Welt! mittels Handlebars.js aus. Das Wort Welt ist dabei dynamisch und wird vom JavaScript-Code festgelegt.

<script id="template" type="text/x-handlebars-template">
  <p>
    Hallo, {{placeholder}}!
  </p>
</script>

<div id="wrapper"></div>

<script type="text/javascript">
  var source = $('#template').html(); // Speichere den Inhalt des Templates als String in einer Variable
  var template = Handlebars.compile(source); // Durch Kompilieren des Templateinhalts wird ein Template-Objekt erschaffen
  var data = { placeholder: 'Welt' }; // Daten, die an das Template-Objekt übergeben werden.
  var html = template(data); // Dem Template-Objekt werden nun die variablen Daten übergeben und es wird ein geparster HTML-String zurückgegeben
  $('#wrapper').html(html); // Zuletzt wird der fertig geparste HTML-Code dem HTML DOM hinzugefügt und damit dem Benutzer angezeigt.
</script>

Kurzer Hinweis: Nach dem Deployment ist es ratsam, das Kompilieren einmalig durchzuführen, sodass es nicht mit jedem Seitenaufruf durchgeführt wird. Das soll nicht Teil dieses Tutorials sein. Weitere Informationen hier.

Helper in Handlebars.js

Neben den Verwenden von Platzhaltern bietet Handlebars.js noch Helper, die oft benötigte Sprachkonstrukte ermöglichen oder vereinfachen.
Zum Beispiel ist es mit {{$each}} möglich, über ein JavaScript-Array zu iterieren.
Folgender Code ist das anfängliche Beispiel, das einer Tabelle eine neue Zeile hinzufügt, mit Handlebars.js nachprogrammiert. Es verdeutlicht, wie {{$each}} funktioniert.

<script id="table-template" type="text/x-handlebars-template">
  <table>
    {{#each lines}}
      <tr>
        <td>{{nr}}</td>
      </tr>
    {{/each}}
  </table>
</script>

<div id="table-wrapper"></div>
<input type="button" id="add-button" value="add" />

<script type="text/javascript">
  lines = [
    { nr: 1 }
   ];
  
  source = $('#table-template').html();
  template = Handlebars.compile(source);
 
  function renderTableTemplate()
  {
    var data = { lines: lines };
    var html = template(data);
    $('#table-wrapper').html(html);
  }
 
  $('#add-button').click(function() {
    var nr = lines.length+1;
    var line = { nr: nr };
    lines.push(line);
    renderTableTemplate();
  });
  
  renderTableTemplate();
</script>

Warum ist dieser Code nun besser? Auf den ersten Blick scheint dieser Code zugegebenermaßen um einiges komplexer. Für dieses einfache Beispiel sind die Vorteile nicht sofort ersichtlich.
Der große Vorteil besteht darin, dass das View ausschließlich im Handlebars.js-Template – also in dem dafür vorgesehenen Script-Tag – untergebracht ist. Im JavaScript-Code musst Du Dich nicht mit HTML-Tags rumplagen. Und im View-Code eben nicht mit JavaScript.
Als weiterer Schritt bietet es sich an, den JavaScript-sowie den Handlebars-Code komplett in eine eigene .js-Datei auszulagern.

{{#each}} ist natürlich nicht der einzige Helper, den Handlebars.js implementiert hat. Auf der offiziellen Webseite können weitere nützliche Helper eingesehen werden.
Auch ist es möglich, eigene Helper zu implementieren.

Für weitere Fragen stehe ich Dir gerne in der Kommentarfunktion zur Verfügung.

Autor: | Kategorien: Internet, JavaScript, Webentwicklung

Keine Kommentare zu Handlebars.js Tutorial: Templates in JavaScript

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *