Interattività con Alpine.js
In questa pagina
Interattività con Alpine.js
Ogni pagina compilata da BxSites carica già Alpine.js
- è ciò che alimenta l'interruttore modalità scura integrato e il menu a
discesa della lingua in ogni tema integrato. Quella stessa
istanza Alpine è disponibile gratuitamente anche per il contenuto delle
tue pagine: nessuna impostazione di
bxsites.yamlda attivare, nessuna voceextraJsda aggiungere, nessun tag<script>extra da scrivere nel tuo markdown.
Dato che l'HTML grezzo a livello di blocco passa intatto
nel tuo markdown, puoi mettere gli attributi x-data/x-show/@click/ecc.
di Alpine direttamente su qualsiasi blocco HTML e funziona senza altro.
Prima di ricorrere ad Alpine
La maggior parte delle esigenze "interattive" ha già un blocco a direttiva pensato apposta che non richiede di scrivere alcun JS in prima persona - ricorri prima a questi:
- Una sezione comprimibile → Espandibile oppure un'ammonizione comprimibile
- Contenuto alternativo raggruppato dietro schede cliccabili → Schede di contenuto
- Un percorso guidato numerato → Stepper
- Un link di call-to-action con stile predefinito →
Pulsanti (il pulsante copia-negli-appunti
qui sotto è un caso diverso - non ha affatto un
href, solo comportamento lato client - esattamente ciò per cui serve Alpine)
Alpine serve per il contenuto interattivo che questi non coprono - qualsiasi cosa con un proprio stato lato client.
Un pulsante copia-negli-appunti
::: button renderizza sempre e solo un
link vero (oppure un segnaposto inerte) - come il pulsante nativo di
GitBook, non ha alcuna nozione di eseguire JS arbitrario al click. Per un
pulsante che fa qualcosa invece di navigare da qualche parte, applica
le sue classi bxsites-button/bxsites-button--* a un normale
<button> HTML - stesso aspetto, stilizzato in ogni tema integrato,
semplicemente collegato con Alpine invece che con un href. Un caso
comune: un pulsante accanto a un comando di installazione che lo copia e
conferma la copia:
<div x-data="{ copied: false }">
<button type="button" class="bxsites-button bxsites-button--secondary bxsites-button--small"
@click="navigator.clipboard.writeText( 'box install bx-sites' ); copied = true; setTimeout( () => copied = false, 1500 )">
<span x-show="!copied">Copy install command</span>
<span x-show="copied" x-cloak>Copied!</span>
</button>
</div>
Un filtro dal vivo
Filtrare una lista lato client, senza andata e ritorno verso il server:
<div x-data="{ query: '' }">
<input type="text" x-model="query" placeholder="Filter providers...">
<ul>
<li x-show="'local'.includes( query.toLowerCase() )">local (static index, no server)</li>
<li x-show="'algolia'.includes( query.toLowerCase() )">algolia (hosted DocSearch)</li>
<li x-show="'pagefind'.includes( query.toLowerCase() )">pagefind (indexed at build time)</li>
</ul>
</div>
x-model collega il valore dell'input allo stato Alpine; l'x-show di
ogni <li> viene rivalutato a ogni tasto premuto.
Una tabella ordinabile e filtrabile
Una tabella nativa a pipe è statica una volta
costruita - per averne una che il lettore possa davvero ordinare e
filtrare lato client (la cosa più vicina qui alla ricerca/ordinamento
delle tabelle di GitBook), lascia che sia Alpine a possedere le righe:
metti i dati in x-data e renderizzali con x-for, invece di scrivere la
sintassi a pipe | Feature | Status |:
<div x-data="{
query: '',
sortKey: 'name',
sortAsc: true,
rows: [
{ name: 'Bootstrap', type: 'Components', stars: 4 },
{ name: 'GitBook', type: 'SaaS', stars: 5 },
{ name: 'Docusaurus', type: 'React', stars: 4 },
{ name: 'VuePress', type: 'Vue', stars: 3 }
],
sortBy(key) {
this.sortAsc = this.sortKey === key ? !this.sortAsc : true
this.sortKey = key
},
get sorted() {
return [...this.rows]
.filter(r => r.name.toLowerCase().includes(this.query.toLowerCase()))
.sort((a, b) => {
const dir = this.sortAsc ? 1 : -1
return a[this.sortKey] > b[this.sortKey] ? dir : a[this.sortKey] < b[this.sortKey] ? -dir : 0
})
}
}">
<input type="text" x-model="query" placeholder="Filter by name...">
<table class="table">
<thead>
<tr>
<th @click="sortBy('name')" style="cursor:pointer">Name</th>
<th @click="sortBy('type')" style="cursor:pointer">Type</th>
<th @click="sortBy('stars')" style="cursor:pointer">Stars</th>
</tr>
</thead>
<tbody>
<template x-for="row in sorted" :key="row.name">
<tr>
<td x-text="row.name"></td>
<td x-text="row.type"></td>
<td x-text="row.stars"></td>
</tr>
</template>
</tbody>
</table>
</div>
Che viene renderizzato così (scrivi nella casella, clicca un'intestazione di colonna):
| Name | Type | Stars |
|---|---|---|
rows è un semplice array JS incorporato direttamente nella pagina - va
bene per il tipo di piccola tabella di riferimento che i docs hanno
davvero. sorted è un getter di Alpine, quindi rifiltra e riordina a
ogni tasto premuto/clic senza cablaggio aggiuntivo; sortBy() inverte la
direzione al secondo clic sulla stessa colonna. Il <table> qui è un vero
tag <table> scritto a mano (non esiste una sintassi per tabelle a pipe
che passi le righe direttamente ad Alpine), quindi viene comunque
racchiuso in .bxsites-table-wrap e riceve il trattamento di scorrimento
responsive/intestazione
fissa
automaticamente, esattamente come qualsiasi tabella renderizzata da
bx-markdown stesso.
Le basi di x-data, se sei nuovo ad Alpine
x-data dichiara lo stato reattivo proprio di uno scope come un semplice
oggetto JS; qualsiasi cosa dentro quell'elemento può leggerlo/scriverlo, e
x-show/x-text/x-model/@click (forma abbreviata di x-on:click)
reagiscono tutti al suo cambiamento:
<div x-data="{ count: 0 }">
<button type="button" @click="count++">Clicked <span x-text="count"></span> times</button>
</div>
Vedi la documentazione ufficiale di Alpine
per l'elenco completo delle direttive (x-if, x-for, x-transition, e
altre).
Cose da sapere
- È fondamentale, non opzionale. Gli elementi di contorno del tema
(modalità scura, cambio lingua) dipendono da Alpine, quindi non può
essere disattivato in
bxsites.yamlcome invece si può fare permermaid/math. - Versione. Attualmente
alpinejs@3.14.1, incluso con questo modulo e servito dasite/assets/vendor/alpine/- nessuna CDN coinvolta. Controlla illayout.bxmproprio di un tema per il tag<script>esatto se ti serve sapere con precisione cosa viene caricato. - CSP rigida. La build predefinita di Alpine valuta le espressioni JS
dentro
x-data/@clickecc. direttamente, il che richiedeunsafe-evalsotto una Content-Security-Policy rigida. Se la tua distribuzione non può permetterlo, non affidarti ad Alpine nel contenuto delle tue pagine. - Tienilo leggero. Una pagina di documentazione dovrebbe restare veloce e semplice - piccoli widget autonomi (un pulsante di copia, un filtro, un interruttore) sono adatti; una vera applicazione lato client non è ciò per cui questo esiste.