Eine Einführung in den Lenker
() translation by (you can also view the original English article)
Wenn sich die Daten Ihrer Site regelmäßig ändern, sollten Sie sich Lenker ansehen. Handlebars ist ein Vorlagenprozessor, der Ihre HTML-Seite dynamisch generiert und Ihnen Zeit beim manuellen Aktualisieren spart. In diesem Tutorial werde ich Ihnen die Lenker vorstellen und Ihnen zeigen, wie Sie eine grundlegende Vorlage für Ihre Site erstellen.
Site-Vorlage
Es gibt zwei Hauptgründe, warum Sie eine Vorlage für Ihre Site erstellen möchten. Wenn Sie eine Vorlage erstellen, werden Sie zunächst aufgefordert, den logikbasierten Code von der tatsächlichen Ansicht zu trennen, damit Sie sich an ein Ansichts- / Controller-Muster halten können. Zweitens halten Vorlagen Ihren Code sauber und wartbar, was wiederum die Aktualisierung Ihrer Website zum Kinderspiel macht. Sie erstellen keine Site mit Lenkern. Stattdessen erstellen Sie Richtlinien und Strukturen, die festlegen, wie die Site aussehen soll, ohne sich auf die Daten einer Seite zu konzentrieren. Lassen Sie uns einige der Grundlagen behandeln.
Die Grundlagen
Handlebars generiert Ihren HTML-Code, indem er eine JSON-Struktur verwendet und diese durch eine Vorlage ausführt. Diese Vorlagen sind größtenteils in normalem HTML geschrieben und mit Platzhaltern gespickt, mit denen Sie bei Bedarf Daten einfügen können. Die folgende Vorlage begrüßt den Benutzer beispielsweise beim Anmelden:
1 |
<h1>Welcome back, {{name}}</h1> |
Mit dem Attribut {{name}}
wird der Name des Benutzers in die Seite eingefügt. Dieser Platzhalter entspricht einer Eigenschaft in der JSON-Struktur der Daten. Dies ist das grundlegendste Beispiel, aber Sie werden bald sehen, dass alles andere im Grunde auf dieses einfache Konzept hinausläuft. Fahren wir mit der Behandlung von Arrays fort.
Arrays
Der Lenker verfügt über einige integrierte Helfer, die Sie bei der Arbeit mit komplexeren Daten unterstützen. Einer dieser Helfer ist each
Helfer. Dieser Helfer durchläuft ein Array und ermöglicht Ihnen das Erstellen von dynamischem HTML pro Array-Element. In der folgenden Vorlage werden beispielsweise die Daten eines Arrays angezeigt, die eine Liste der lokalen Konzerte in meiner Region enthalten:
1 |
<table>
|
2 |
<tr>
|
3 |
<th>Local Concerts</th> |
4 |
</tr>
|
5 |
{{#each Concerts}} |
6 |
<tr>
|
7 |
<td>{{this}}</td> |
8 |
</tr>
|
9 |
{{/each}} |
10 |
</table>
|
Wie Sie sehen können, ist dieser Code viel sauberer als herkömmlicher Code, z. B. die Verwendung einer Schleife in PHP oder JavaScript zum Anhängen von HTML an eine Variable. Lenker sind nicht aufdringlich, und das macht Lenker so zugänglich. Möglicherweise stellen Sie auch fest, dass wir den Attributnamen this
verwenden, um das aktuelle Array-Element in each
Schleife abzurufen.
Dieses Beispiel eignet sich für eine Reihe einfacher Werte. Wie gehen Sie jedoch mit komplexeren Daten um? Nun, Sie machen im Wesentlichen das Gleiche. Zum Beispiel werden wir eine Vorlage für die folgenden Daten schreiben:
1 |
[ |
2 |
{ |
3 |
Name : "Band", |
4 |
Date : "Aug 14th, 2012", |
5 |
Albums : [ |
6 |
{ |
7 |
Name : "Generic Name" |
8 |
}, |
9 |
{ |
10 |
Name : "Something Else!!" |
11 |
} |
12 |
] |
13 |
}, |
14 |
{ |
15 |
Name : "Other Guys", |
16 |
Date : "Aug 22nd, 2012" |
17 |
Albums : [ |
18 |
{ |
19 |
Name : "Album One" |
20 |
} |
21 |
] |
22 |
} |
23 |
] |
Wir können diese Informationen mithilfe der folgenden Vorlage problemlos anzeigen:
1 |
<table>
|
2 |
<tr>
|
3 |
<th>Band Name</th> |
4 |
<th>Date</th> |
5 |
<th>Album Name</th> |
6 |
</tr>
|
7 |
{{#each Bands}} |
8 |
<tr>
|
9 |
<td>{{Name}}</td> |
10 |
<td>{{Date}}</td> |
11 |
<td>{{Albums.0.Name}}</td> |
12 |
</tr>
|
13 |
{{/each}} |
14 |
</table>
|
Sie können Ihre Vorlage in einem
<script/>
-Element speichern und mit JavaScript laden.
In Handlebars können Sie sogar auf verschachtelte Eigenschaften zugreifen, wie im obigen Beispiel (Albums.0.Name
), und natürlich hätten Sie andere each
-Schleife verwenden können, um über die Alben einer Band zu iterieren. Beachten Sie, dass Sie neben der Punktnotation für den Zugriff auf verschachtelte Eigenschaften auch "../" verwenden können, um auf die Eigenschaften eines Elternteils zuzugreifen.
Was ist, wenn keine Bands spielen? Sie wollen sicher keinen leeren Tisch, und der Lenker stellt dankenswerterweise if
, else
und unless
Helfer. Die if
- und else
-Anweisungen funktionieren wie die meisten Programmiersprachen: Wenn das übergebene Objekt false
oder falsey ist, wird die else
-Anweisung ausgeführt. Andernfalls wird die if
-Anweisung ausgeführt. Die unless
denn, Aussage ist ziemlich interessant; Es ist im Wesentlichen eine invertierte if
-Anweisung. Wenn der Ausdruck true
ist, wird der Block unless
NICHT ausgeführt. Nehmen wir also diese Helfer in unseren Code auf:
1 |
{{#if Bands}} |
2 |
<table>
|
3 |
<tr>
|
4 |
<th>Band Name</th> |
5 |
<th>Date</th> |
6 |
<th>Album Name</th> |
7 |
</tr>
|
8 |
{{#each Bands}} |
9 |
<tr>
|
10 |
<td>{{Name}}</td> |
11 |
<td>{{Date}}</td> |
12 |
<td>{{Albums.0.Name}}</td> |
13 |
</tr>
|
14 |
{{/each}} |
15 |
</table>
|
16 |
{{else}} |
17 |
<h3>There are no concerts coming up.</h3> |
18 |
{{/if}} |
Benutzerdefinierte Helfer
Mit dem Lenker können Sie Ihren eigenen benutzerdefinierten Helfer erstellen. Registrieren Sie einfach Ihre Funktion im Lenker, und jede Vorlage, die Sie anschließend kompilieren, kann auf Ihren Helfer zugreifen. Es gibt zwei Arten von Helfern, die Sie machen können:
- Funktionshelfer sind im Grunde reguläre Funktionen, die nach ihrer Registrierung an einer beliebigen Stelle in Ihrer Vorlage aufgerufen werden können. Lenker schreibt den Rückgabewert der Funktion in die Vorlage.
- Blockhelfer sind von Natur aus ähnlich wie die Helfer
if
,each
usw. Sie ermöglichen es Ihnen, den Kontext dessen zu ändern, was sich darin befindet.
Lassen Sie mich Ihnen jeweils ein kurzes Beispiel zeigen. Zuerst registriere ich einen Funktionshelfer mit folgendem Code:
1 |
Handlebars.registerHelper("Max", function(A, B){ |
2 |
return (A > B) ? A : B; |
3 |
}); |
Das erste an registerHelper()
übergebene Argument ist der Name meines Kundenhelfers. Ich werde diesen Namen in der Vorlage verwenden. Das zweite Argument ist die diesem Helfer zugeordnete Funktion.
Die Verwendung dieses Hilfsprogramms in einer Vorlage ist äußerst einfach:
1 |
{{Max 12 45}} |
Diese Vorlage verwendet den Max
-Helfer und übergibt die Werte 12 und 45 an die zugehörige Funktion. Helfer-Funktionshilfen unterstützen mehrere Parameter. Sie können Zahlen direkt in die Vorlage selbst einfügen oder Attribute aus einer JSON-Struktur verwenden.
Schauen wir uns nun einen benutzerdefinierten Blockhelfer an. Mit Block-Helfern können Sie den Kontext festlegen, bevor Sie den im Block enthaltenen Code ausführen. Betrachten Sie beispielsweise das folgende Objekt:
1 |
{ |
2 |
Name: "Parent", |
3 |
Sub: { |
4 |
Name: "Child" |
5 |
} |
6 |
} |
Um beide Namen anzuzeigen, können Sie einen Blockhelfer schreiben, der die Vorlage einmal mit dem Kontext des Elternteils und einmal mit dem Kontext des Kindes ausführt. Hier ist der Helfer:
1 |
Handlebars.registerHelper("BothNames", function(context, options){ |
2 |
return options.fn(context) + options.fn(context.Sub); |
3 |
}); |
Und die Vorlage sieht so aus:
1 |
{{#BothNames this}} |
2 |
<h2>{{Name}}</h2> |
3 |
{{/BothName}} |
Das Hash-Tag vor dem Namen des Helfers teilt Handlebars mit, dass dies ein Block-Helfer ist, und Sie schließen den Block ähnlich wie ein HTML-Tag. Die Funktion options.fn
führt den Abschnitt der Vorlage innerhalb des Blocks mit dem von Ihnen angegebenen Kontext aus.
Nachdem wir die Grundlagen verstanden haben, können Sie mit der Erstellung einer vollständigen Demo beginnen.
Erstellen einer Site-Vorlage
Sie erstellen keine Site mit Lenkern.
Die Vorlage, die wir erstellen, ist für eine Rezeptseite. Dies gibt Ihnen ein gutes Verständnis der Lenker, da es das Abrufen von Daten von einer API und das Weiterleiten durch eine Vorlage umfasst.
Einrichten eines Lenkerprojekts
Wir müssen zuerst unser Vorlagenskript laden, aber dazu müssen wir eine neue HTML-Datei erstellen und unsere Lenkerbibliothek einschließen:
1 |
<html>
|
2 |
<head>
|
3 |
<title>Handlebars Demo</title> |
4 |
<script type="text/javascript" src="Handlebars.js"></script> |
5 |
</head>
|
6 |
<body>
|
7 |
<script id="Handlebars-Template" type="text/x-handlebars-template"> |
8 |
</script>
|
9 |
</body>
|
10 |
</html>
|
Der Einfachheit halber können Sie Ihre Vorlage in einem <script/>
-Element speichern und mit JavaScript laden. Dies ist viel sauberer als das direkte Speichern in einer JavaScript-Variablen.
Lassen Sie uns nun diskutieren, wie diese App funktionieren wird. Zunächst stellt die App eine Verbindung zu einer API her (ich verwende Yummly), um Informationen zu einigen Rezepten abzurufen. Als nächstes übergeben wir diese Informationen an den Lenker und führen sie durch die Vorlage. Schließlich ersetzen wir den Body-Abschnitt durch den neu generierten HTML-Code. Es ist ein ziemlich einfacher Prozess; Beginnen wir also damit, einen zweiten script
-Block direkt vor dem schließenden body
-Tag hinzuzufügen und eine Ajax
-Variable zu instanziieren:
1 |
<script>
|
2 |
|
3 |
var Ajax = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"); |
4 |
|
5 |
Ajax.onreadystatechange = function(){ |
6 |
if (Ajax.readyState == 4 && Ajax.status == 200) |
7 |
{
|
8 |
//Parse the JSON data
|
9 |
var RecipeData = JSON.parse(Ajax.responseText); |
10 |
|
11 |
//Get the Template from above
|
12 |
var Source = document.getElementById("Handlebars-Template").textContent; |
13 |
|
14 |
//Compile the actual Template file
|
15 |
var Template = Handlebars.compile(Source); |
16 |
|
17 |
//Generate some HTML code from the compiled Template
|
18 |
var HTML = Template({ Recipes : RecipeData }); |
19 |
|
20 |
//Replace the body section with the new code.
|
21 |
document.body.innerHTML = HTML; |
22 |
}
|
23 |
}
|
24 |
|
25 |
Ajax.open("GET","Recipe.php", true); |
26 |
Ajax.send(); |
27 |
|
28 |
</script>
|
Wenn sich die Daten Ihrer Website regelmäßig ändern, sollten Sie sich Lenker ansehen.
Das ist der vollständige Code zum Kompilieren und Generieren von HTML-Code aus einer Vorlage. Sie können die JSON-Daten von der API technisch direkt an den Lenker übergeben, es treten jedoch Probleme mit unterschiedlichen Ursprüngen auf. Anstatt eine Art Hack durchzuführen oder PHP zu verwenden, um die Daten in eine JavaScript-Variable zu "echoieren", habe ich beschlossen, all dies in eine separate Datei zu schreiben: Recipe.php
. Bevor wir mit dem Erstellen der Vorlage beginnen, schauen wir uns diese PHP-Datei an.
Daten abrufen
Die Yummly API ist ziemlich einfach. Es gibt kein ausgeklügeltes Authentifizierungssystem. Sie müssen sich nur anmelden, einige Anmeldeinformationen abrufen und diese in die URL einfügen. Sie können die Daten direkt wiedergeben, wenn Sie möchten, aber ich möchte ein bisschen detailliertere Informationen zu jedem Rezept. Daher werde ich die Daten aus dem ersten API-Aufruf verarbeiten und für jedes Rezept eine zweite Anfrage stellen. Hier ist das komplette PHP-Skript:
1 |
<?php
|
2 |
//Empty Array to hold all the recipes
|
3 |
$Json = []; |
4 |
|
5 |
$UserID = //Your ID Here; |
6 |
|
7 |
$UserKey = //Your Yummly key; |
8 |
|
9 |
//This searches Yummly for cake recipes
|
10 |
$Recipes = file_get_contents("http://api.yummly.com/v1/api/recipes?_app_id=" . $UserID . "&_app_key=" . $UserKey . "&maxResult=2&requirePictures=true&q=Cake"); |
11 |
|
12 |
//Decode the JSON into a php object
|
13 |
$Recipes = json_decode($Recipes)->matches; |
14 |
|
15 |
|
16 |
//Cycle Through The Recipes and Get full recipe for each
|
17 |
foreach($Recipes as $Recipe) |
18 |
{
|
19 |
$ID = $Recipe->id; |
20 |
$R = json_decode(file_get_contents("http://api.yummly.com/v1/api/recipe/" . $ID . "?_app_id=" . $UserID . "&_app_key=" . $UserKey . "&images=large")); |
21 |
|
22 |
|
23 |
//This is the data we are going to pass to our Template
|
24 |
array_push($Json, array( |
25 |
Name => $R->name, |
26 |
Ingredients => $R->ingredientLines, |
27 |
Image => $R->images[0]->hostedLargeUrl, |
28 |
Yield => $R->yield, |
29 |
Flavors => $R->flavors, |
30 |
Source => array( |
31 |
Name => $R->source->sourceDisplayName, |
32 |
Url => $R->source->sourceRecipeUrl |
33 |
)
|
34 |
));
|
35 |
}
|
36 |
|
37 |
//Print out the final JSON object
|
38 |
echo json_encode($Json); |
39 |
?>
|
Indem Sie Ihre Site mit einer Lenkervorlage erstellen, können Sie den Code einer vollständigen Site in nur wenigen Zeilen erstellen. Hier ist die gesamte Vorlage:
1 |
<script id="Handlebars-Template" type="text/x-handlebars-template"> |
2 |
<div id="Content"> |
3 |
<h1>ΞRecipeCards |
4 |
<span id='BOS'>Recipe search powered by |
5 |
<a id='Logo' href='http://www.yummly.com/recipes'> |
6 |
<img src='http://static.yummly.com/api-logo.png'/> |
7 |
</a> |
8 |
</span> |
9 |
</h1> |
10 |
{{#each Recipes}} |
11 |
<div class='Box'> |
12 |
<img class='Thumb' src="{{{Image}}}" alt="{{Name}}"> |
13 |
<h3>{{Name}} <a id='Logo' href="{{Source.Url}}"> - {{Source.Name}}</a></h3> |
14 |
<h5>{{getFlavor Flavors}}</h5> |
15 |
<h5>{{Yield}}</h5> |
16 |
<p>Ingredients:</p> |
17 |
<ul> |
18 |
{{#each Ingredients}} |
19 |
<li>{{this}}</li> |
20 |
{{/each}} |
21 |
</ul> |
22 |
</div> |
23 |
{{/each}} |
24 |
</div> |
25 |
</script>
|
Lassen Sie uns diesen Code durchgehen. Die ersten sieben Zeilen sind nur das Logo oben auf der Seite. Dann erstellen wir für jedes Rezept eine Rezeptkarte mit einem Bild, einem Namen und Zutaten.
Die Yummly-API gibt eine Liste von Geschmacksdaten (d. H. Wie süß, sauer, würzig usw.) für jeden Artikel zurück. Ich habe einen Funktionshelfer namens getFlavor
geschrieben, der diese Informationen verwendet und den dominantesten Geschmack des Gerichts zurückgibt. Damit diese Vorlage funktioniert, müssen wir den getFlavor
-Helfer in den Lenker laden, bevor wir die Vorlage analysieren. Fügen Sie daher am Anfang des zweiten Skriptabschnitts den folgenden Code vor dem Ajax-Code hinzu:
1 |
Handlebars.registerHelper("getFlavor", function(FlavorsArr){ |
2 |
var H = 0; |
3 |
var Name = ''; |
4 |
for(var F in FlavorsArr) |
5 |
{ |
6 |
if(FlavorsArr[F] > H) |
7 |
{ |
8 |
H = FlavorsArr[F]; |
9 |
Name = F; |
10 |
} |
11 |
} |
12 |
return "This Dish has a " + Name + " Flavor"; |
13 |
}); |
Immer wenn der Lenker getFlavor
sieht, ruft er die zugehörige Funktion auf und ruft die Geschmacksinformationen ab.
An diesem Punkt können Sie frei herumspielen und die Vorlage entwerfen, wie Sie möchten, aber Sie werden höchstwahrscheinlich feststellen, dass dieser Prozess langsam ist. Dies ist hauptsächlich auf die drei API-Aufrufe zurückzuführen, bevor Handlebars die Seite lädt. Dies ist natürlich nicht ideal, aber das Vorkompilieren Ihrer Vorlage kann hilfreich sein.



Vorkompilieren
Sie haben zwei verschiedene Möglichkeiten, wenn es um Lenker geht. Die erste besteht darin, nur die eigentliche Vorlage vorkompilieren. Dies reduziert die Ladezeit und Sie müssen den Lenker-Compiler nicht in Ihre Seite aufnehmen.
Dies führt auch zu einer kleineren Dateigröße, was in unserem Szenario jedoch nicht wirklich hilft.
Unser Problem ist die Kommunikation zwischen dem Browser und der API. Wenn Sie Ihre Vorlage vorkompilieren möchten, können Sie das Node.js-Paket mit dem folgenden Befehl über npm
herunterladen:
1 |
npm install handlebars -g |
Möglicherweise müssen Sie dies als root tun (d. H. Vor dem Befehl 'sudo' hinzufügen). Nach der Installation können Sie eine Datei für Ihre Vorlage erstellen und wie folgt kompilieren:
1 |
handlebars demo.handlebars -f demo.js |
Sie sollten Ihrer Vorlagendatei die Erweiterung .handlebars
geben. Dies ist nicht obligatorisch, aber wenn Sie es so etwas wie demo.html
nennen, lautet der Name der Vorlage "demo.html", nur "demo". Fügen Sie nach dem Benennen Ihrer Vorlage einfach die Ausgabedatei zusammen mit der Laufzeitversion von Handlebars hinzu (Sie können die reguläre Version verwenden, diese ist jedoch größer) und geben Sie Folgendes ein:
1 |
var template = Handlebars.templates['demo']; |
2 |
var html = template({ Your Json Data Here }); |
Die
unless
-Anweisung ist...im Wesentlichen eine invertierteif
-Anweisung.
Aber wie ich bereits erwähnt habe, hilft uns dies in diesem Szenario nicht wirklich. Was können wir dann tun? Nun, wir können die gesamte Datei vorkompilieren und ausgeben. Auf diese Weise können wir die Vorlage mit Daten ausführen und die endgültige HTML-Ausgabe speichern, dh das Caching. Dies beschleunigt die Ladezeit Ihrer Anwendung drastisch. Leider verfügt clientseitiges JavaScript nicht über Datei-E / A-Funktionen. Der einfachste Weg, dies zu erreichen, besteht darin, den HTML-Code einfach in ein Textfeld auszugeben und manuell zu speichern. Beachten Sie die Richtlinien einer API zum Zwischenspeichern. Die meisten APIs haben eine maximale Zeitspanne, für die Daten zwischengespeichert werden können. Stellen Sie sicher, dass Sie diese Informationen finden, bevor Sie statische Seiten speichern.
Abschluss
Das war eine kurze Einführung in den Lenker. In Zukunft können Sie sich "Partials" ansehen - kleine Vorlagen, die wie Funktionen verwendet werden können. Wie immer können Sie im Kommentarbereich unten einen Kommentar oder eine Frage hinterlassen.