Kolejne możliwości Handlebars

Kamil Powroźnik

2019-05-28T22:35+02:00 | 8 min

Hej, jako że ostatnio na blogu panuje moja zajawka na język go seria o Parcelu trochę ucierpiała. Nadszedł jednak czas, żeby nadrobić zaległości. Dziś na tapetę bierzemy zaawansowane możliwości systemu szablonów Handlebars, które do tej pory wykorzystywaliśmy.

Do tej pory dowiedziałeś się, że możemy stworzyć osobne re-używalne części naszego szablonu, a także podstrony z treścią, która jest dynamicznie wstrzykiwana do naszego layoutu. Poznajmy teraz kilka innych opcji, które ułatwią nam pracę przy tworzeniu stron.

Generowanie elementów z pliku JSON

Wyobraźmy sobie, że chcielibyśmy wylistować naszych użytkowników. Przygotowałem w tym celu plik users.json, który umieściłem w folderze src/data - tak jak na początku zdefiniowaliśmy w pliku konfiguracyjnym handlebars.config.js.

{
  "users": [
    { "name": "John Doe", "email": "johndoe@bycfrontendem.blog" },
    {
      "name": "Yoda",
      "email": "yoda@bycfrontendem.blog"
    }
  ]
}

users.json

Chciałbym teraz, aby tych dwoje użytkowników pojawiło się na stronie głównej. W tym celu użyję oferowanego przez system bloku each.

<h2>Who we are</h2>
<ul>
  {{#each users.users}}
  <li>{{name}}</li>
  {{/each}}
</ul>

index.hbs

Hurra! Oni naprawdę pojawili się na stronie

Idąc tym tokiem, równie dobrze zamiast tablicy, moglibyśmy wyświetlić pary klucz-wartość. Wystarczy że przerobimy nasz plik z danymi na taki:

{
  "John Doe": "johndoe@bycfrontende.blog",
  "Yoda": "yoda@bycfrontendem.blog"
}

users.json

<ul>
  {{#each users}}
  <li>{{@key}} - {{this}}</li>
  {{/each}}
</ul>

index.hbs

Efektem końcowym jest taki widok:

Zmienne lokalne

Kolejną ciekawą rzeczą pochodzącą z handlebars są zmienne lokalne. Co to oznacza? Takie zmienne możemy zdefiniować za pomocą YAML, a następnie wykorzystać w różnych miejscach strony.

Zwróćmy uwagę na kod zawarty w dokumentacji pluginu. Autor na początku pliku zdefiniował kilkanaście zmiennych.

---
alternates:
  - language: es
    uri: /es
  - language: fr
    uri: /fr
bodyclass: index
language: en
meta:
  author: Author Name
  description: Some meta description
  keywords: Some, Meta, Keywords
  robots: index, follow
scripts:
  - ../typescript/index.ts
stylesheets:
  - ../scss/index.scss
title: Index | Parcel Bundler With Handlebars
uri: /
---

{{#extend "base"}}
  {{#content "main"}}
    <main>
      <h1>Welcome from index.hbs</h1>
      <a href="./about.hbs">about page</a>
      {{#isnt NODE_ENV "production"}}
      <p>I will disappear on production builds</p>
      {{/isnt}}
      <br />
      {{> states}}
    </main>
  {{/content}}
{{/extend}}

index.hbs - GitHub

Następnie wykorzystał je międzyinnymi w komponencie odpowiadającemu za generowanie tagów meta

{{!-- Set character encoding for the document --}}
<meta charset="utf-8">
{{!-- Instruct Internet Explorer to use its latest rendering engine --}}
<meta http-equiv="x-ua-compatible" content="ie=edge">
{{!-- Viewport for responsive web design --}}
<meta name="viewport" content="width=device-width, initial-scale=1">
{{#if meta}}
{{#if meta.author}}
<meta name="author" content="{{meta.author}}">
{{/if}}
{{#if meta.description}}
<meta name="description" content="{{meta.description}}">
{{/if}}
{{#if meta.keywords}}
<meta name="keywords" content="{{meta.keywords}}">
{{/if}}
{{#if meta.robots}}
<meta name="robots" content="{{meta.robots}}">
{{/if}}
{{/if}}

partials/meta.hbs - GitHub

Dzięki takiemu rozwiązaniu, w łatwy i przyjemny sposób jesteśmy w stanie zdefiniować meta tagi bez ingerencji w markup HTML.

Instrukcje warunkowe

W powyższym kodzie mogłeś zauważyć użycie wyrażenia {{#if }}. Handlebars oferuje nam instrukcje warunkowe, dzięki którym możemy obsługiwać na przykład conditional rendering.

Standardowo w instrukcjach warunkowych nie może zabraknąć wyrażenia else. W Handlebars wygląda to tak:

<div class="entry">
  {{#if author}}
    <h1>{{firstName}} {{lastName}}</h1>
  {{else}}
    <h1>Unknown Author</h1>
  {{/if}}
</div>

Do dyspozycji mamy również wyrażenie {{#unless }}, które jest przeciwieństwem if, czyli zwraca blok, który ma być wyrenderowany jeśli wartość zawarta w wyrażeniu jest nie prawdziwa.

Bloki

Bloki to ostatnia rzecz, którą chcę wam dziś pokazać. Za ich pomocą możemy stworzyć typowe portale, w które będzie wstrzykiwana treść.

Definiujemy je za pomocą wyrażenia {{#block "name"}} tworząc tym samym miejsca, w które będzie wrzucana treść naszych bloków.

W celu zademonstrowania ich możliwości przerobiłem nieznacznie nasz dotychczasowy kod:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>Project with Parcel</title>
  <link rel="stylesheet" href="./styles/main.scss" />
  <link href="https://fonts.googleapis.com/css?family=Roboto|Roboto+Condensed:400,700" rel="stylesheet">
  <link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>

<body>
  {{#block "header"}}
  {{> header}}
  {{/block}}

  {{#block "main"}}

  {{/block}}
  {{#block "footer"}}
  {{> footer}}
  {{/block}}
</body>

</html>

base.hbs

Jak można zauważyć, zdefiniowałem tu trzy bloki, odpowiednio dla headera, treści oraz stopki.

Teraz wypełnijmy te miejsca.

{{#extend "base"}}

{{#content "header"}}
<h1>test</h1>
{{/content}}

{{#content "main"}}
<main class="container">
  <h1>Hello World!</h1>
  <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere id dolorum accusamus totam maxime magnam quam minus
    temporibus laboriosam error.</p>
  <h2>Who we are</h2>
  <ul>
    {{#each users}}
    <li>{{@key}} - {{this}}</li>
    {{/each}}
  </ul>
</main>
{{/content}}
{{/extend}}

index.hbs

Za pomocą wyrażenia {{#content "header"}} podmieniłem domyślną wartość, która znajdowała się w bloku "header", natomiast za pomocą {{#content "main"}} wstrzyknąłem treść, która ma znajdować się na stronie.

Używając bloków, możemy również wstrzykiwać tą samą treść w różne miejsca. Gdybym w pliku base.hbs zdefiniował dwa bloki o tej samej nazwie, nasza treść pojawiła by się w obydwu miejscach.

  {{#block "header"}}
  {{> header}}
  {{/block}}

  {{#block "header"}}
  {{> header}}
  {{/block}}

  {{#block "main"}}

  {{/block}}
  {{#block "footer"}}
  {{> footer}}
  {{/block}}

base.hbs

Jak widzisz na górze naszej strony, pojawiły się dwa headery 😅

Przedstawiłem Ci najpopularniejsze możliwości oferowane przez handlebars.js, zachęcam Cie jednak do przeczytania dokumentacji Handlebars, w której znajdziesz o wiele więcej szczegółów.

z dedykacją dla największego fana - pozdro Pikey


Hej, ta strona wykorzysuje pliki cookies, localStorage, sessionStorage oraz dane osobowe do celów analitycznych.