· documentation · 5 min read
Approfondimento sul template AstroWind
Sebbene sia facile iniziare, AstroWind è abbastanza complesso internamente. Questa pagina fornisce la documentazione su alcune delle parti più intricate.
Panoramica
Può essere un compito piuttosto imponente cercare di capire le componenti interne di AstroWind, e in particolare vari punti di utilizzo.
Questa pagina descrive e chiarisce alcune delle tecniche trovate in AstroWind. Utilizzala come guida per ulteriori modifiche o come istruzione per le tecniche da utilizzare nei tuoi progetti.
Stile
Come suggerisce il nome, AstroWind si basa su TailWind per lo stile. Inoltre, AstroWind definisce impostazioni di stile personalizzate a basso livello, che vengono incorporate in TailWind in modo uniforme, fornendo coerenza per le costruzioni di stile di livello superiore e consentendo anche la modalità scura.
Il meccanismo di stile è composto dai seguenti file (tutti i percorsi sono preceduti da /src/):
assets/styles/tailwind.css
Questo file è essenzialmente un’estensione di base.css di TailWind. Gli stili dei componenti di alto livello sono definiti qui. Nota anche lo stile sugli elementi selezionati dai selettori ‘attributo’ alla fine dei file, in particolare quelli selezionati da attributi ‘data’.
components/CustomStyles.astro
Definisce colori e caratteri personalizzati. Per far sì che questi abbiano effetto nel file ‘base.css’, devono essere caricati nella sezione dell’intestazione html. Vedi sotto.
layouts/Layout.astro
Questo layout è utilizzato per tutte le pagine renderizzate da AstroWind. I contenuti di tailwind.css e del componente CustomStyles.astro, descritti sopra, vengono iniettati nell’intestazione html.
Modalità scura
La Modalità scura viene attivata dall’icona del ‘sole’: nell’intestazione della pagina. È definita in components/common/ToggleTheme.astro, ma l’evento è collegato e l’azione è definita in components/common/BasicScripts.astro nel seguente snippet:
attachEvent('[data-aw-toggle-color-scheme]', 'click', function () {
if (defaultTheme.endsWith(':only')) {
return;
}
document.documentElement.classList.toggle('dark');
localStorage.theme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
});Nota che questo è un evento lato client. BasicScripts.astro definisce anche diverse altre funzionalità lato client oltre a questa.
Utilizzo avanzato degli slot
Gli slot fanno parte dell’implementazione del componente, che è un concetto comune in molti framework, inclusi Astrojs. La tipica definizione di uno slot in un componente appare così:
---
// (file: MyComponent.astro)
const { title } = Astro.props;
export interface Props {
title: string;
}
---
<div>
<h2>{title}</h2>
<slot />
<!-- qui verranno iniettati i contenuti dello slot -->
<div></div>
</div>E nell’uso altrove:
import MyComponent from "~/components/MyComponent"; ...
<MyComponent someArg="Un esempio di slot">
<p>Questo contenuto verrà visualizzato nello slot</p>
</MyComponent>Utilizzo alternativo
C’è un altro modo in cui possiamo utilizzare gli slot, particolarmente utile quando un componente può contenere del contenuto in markdown, come segue (studiare attentamente…):
---
// (file: MyComponent.astro)
const { title } = Astro.props;
export interface Props {
title: string;
}
const content: string = await Astro.props.render('default');
---
// renderizza l'HTML nella variabile 'content'
<div>
<h2>{title}</h2>
<div set:html={content} />
<!-- qui verranno iniettati i contenuti dello slot -->
<div></div>
</div>Whoa!! Cosa sta succendendo qui?
Nota che non c’è una definizione di slot nella parte HTML del componente. Invece, quello che facciamo è far sì che Astro renda il contenuto dello slot (qui, il contenuto ‘default’, ma è possibile anche rendere slot con nomi) in una variabile e quindi utilizzare quel contenuto in un div (ad esempio).
Pertanto, se l’uso è in un file markdown, come segue:
import MyComponent from '../../components/MyComponent';
# Utilizzando il componente sopra in un file .mdx (che può accettare componenti)
{' '}
<MyComponent title="Questo è un implementatore di slot">### Ecco un po' di contenuto in markdown - Con un elemento elenco.</MyComponent>MyComponent rende il markdown in HTML e poi lo inietta nel div.
Questo ha effettivamente un grande vantaggio: considera che con l’uso normale non hai accesso ai contenuti dello slot: Astro semplicemente posiziona il contenuto nel tag <slot/>. Utilizzando questo metodo, tuttavia, puoi accedere al contenuto e manipolarlo ulteriormente prima che venga inserito nell’HTML.
Ciò permette una grande flessibilità nella progettazione dei componenti.
Un Altro Passo Avanti
Ora, arriviamo alle tecniche utilizzate in AstroWind, useremo il file pages/index.astro per illustrare.
Noterai che il file index importa molti componenti, ciascuno approssimativamente analogo a un pannello nella pagina index. Ciascuno di questi componenti, a sua volta, viene istanziato sequenzialmente in tutta la pagina. Ma noterai che alcuni di essi usano questa struttura (useremo l’ultima sezione, CallToAction, poiché è la più illustrativa della tecnica):
<CallToAction
callToAction={{
text: 'Ottieni il template',
href: 'https://github.com/onwidget/astrowind',
icon: 'tabler:download',
}}
>
<Fragment slot="title">
Astro + <br class="block sm:hidden" /><span class="sm:whitespace-nowrap">Tailwind CSS</span>
</Fragment>
<Fragment slot="subtitle">
Sorprenditi molto da questi enormi numeri falsi che stai vedendo in questa pagina. <br class="hidden md:inline" />Non perdere
altro tempo! :P
</Fragment>
</CallToAction>Alcuni punti da notare qui:
L'argomento callToAction
Questo argomento viene effettivamente passato come un oggetto JavaScript, non come una stringa. (Tuttavia, nella definizione in TS, potrebbe essere una stringa…)
Ci sono diversi elementi Fragment figli
Inoltre, questi elementi <Fragment/> hanno ciascuno uno specificatore slot=“(valore)”.
Quest’ultimo sembra strano, perché <Fragment/> è un componente integrato su cui non hai controllo e non ha una disposizione per il rendering degli slot, di per sé.
La risposta si trova in un paragrafo nella sezione degli slot della documentazione di Astro, che afferma:
Utilizza l’attributo
slot="my-slot"sull’elemento figlio che vuoi far passare a uno slot corrispondentename="my-slot" />nel componente.
È abbastanza conciso e potrebbe sembrare un po’ complicato da comprendere, ma fondamentalmente dice quanto segue:
- Data una componente che definisce uno slot:
- puoi fare riferimento a uno slot da un elemento figlio di quella componente e,
- fornire contenuto allo slot del componente genitore dal figlio nominando lo slot nel figlio con l’assegnazione della proprietà
slot="<nome-slot>", dove il nome-slot è lo slot del genitore.
Quindi, nell’esempio sopra, il componente CallToAction definisce lo slot subtitle, e il seguente <Fragment slot=“subtitle”> popola lo slot con il seguente contenuto:
<Fragment slot="subtitle">
Sorprenditi molto da questi enormi numeri falsi che stai vedendo in questa pagina. <br class="hidden md:inline" />Non perdere
altro tempo! :P
</Fragment>E, il componente CallToAction lo definisce e lo renderizza in questo modo:
---
//...
const { subtitle = await Astro.slots.render('subtitle') } = Astro.props;
---
//...
{subtitle && <p class="text-xl text-muted dark:text-slate-400" set:html={subtitle} />}
//...C’è molto da capire qui.
Nota innanzitutto che subtitle è definito come un argomento prop/argomento, ma viene elaborato come uno slot. È interessante notare che gli argomenti prop/argomenti e gli slot sembrano essere in qualche modo interscambiabili: se subtitle fosse semplicemente una stringa, prenderebbe semplicemente quell’assegnazione. La principale differenza è che se li renderizzi in modo indipendente, devi chiamare il render con un modificatore await.