Vaizdo sluoksnis — layout, home, render
Trys failai kodo stulpelyje kaip skirtukai, priklausomybių tvarka: layout.templ → home.templ → render.go (kevalas, tada puslapis, kuris jį užpildo, tada Go pagalbininkas, kuris atvaizduoja puslapį).
1. internal/web/layout.templ — bendras HTML kevalas, kurį naudoja kiekvienas puslapis. Esminė savybė — { children... }: vieta, kur įsistato puslapio turinys. Jis taip pat susieja CSS ir vietinį htmx.
templ Layout(title string) {
<!DOCTYPE html>
<html lang="en">
<head>
<title>{ title } · SignFlow</title>
<link rel="stylesheet" href="/static/css/style.css"/>
<script src="/static/js/htmx.min.js"></script>
</head>
<body>
<main class="container">{ children... }</main>
</body>
</html>
}
{ title } įterpiamas kaip tekstas, automatiškai ekranuojamas — Templ niekada neleidžia neapdorotai eilutei netyčia tapti žymėjimu (tai XSS apsauga, kurią gauni nemokamai).
2. internal/web/home.templ — pradinis puslapis. Jis kviečia maketą ir paduoda savo turinį kaip vaikus:
templ Home() {
@Layout("Home") {
<section class="hero">
<h1>Sign documents. Keep the receipts.</h1>
...
</section>
}
}
@Layout("Home") { ... } — kompozicija: Home įdeda savo turinį į Layout. Kol kas Home() neima argumentų — 3 pamoka duoda jam userCount int64 parametrą, kad rodytų gyvą įrašų skaičių iš duomenų bazės.
3. internal/handlers/render.go — vienas mažas pagalbininkas, kad apdorotojai liktų glausti:
func render(w http.ResponseWriter, r *http.Request, status int, c templ.Component) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(status)
_ = c.Render(r.Context(), w)
}
Jis nustato turinio tipą, įrašo statusą ir siunčia komponentą srautu. Viena vieta, kurią keisti, jei kada nors pridėsim, tarkim, talpyklos antraštę. (Render klaida sąmoningai atmetama: statuso eilutė jau įrašyta, tad belieka leisti jungčiai užsidaryti.)
Kol kas niekas neatvaizduojama — apdorotojas vis dar rašo 1 pamokos eilutę. Tai — kito žingsnio darbas.