- Panoramica
- Un esempio semplice
- Dettagli
- Stato
- Inizializzare lo stato con amp-state
- Aggiornare lo stato
- Aggiornare lo stato con AMP.setState()
- Modificare la cronologia con AMP.pushState()
- Espressioni
- Differenze da JavaScript
- Esempi
- Funzioni consentite
- Definire macro con amp-bind-macro
- Associazioni
- Attributi specifici degli elementi
- Debug
- Avvisi
- Errori
- Stato di debug
- Appendice
- Specifica di <amp-state>
- Gruppi di XHR
- Attributi
- Deep-merge con AMP.setState()
- Rimuovere una variabile
- Grammatica delle espressioni
amp-bind
Description
Consente agli elementi di cambiare in base alle azioni dell'utente o alle modifiche dei dati per mezzo di associazione di dati ed espressioni semplici simili a JavaScript.
Required Scripts
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
Aggiunge interattività personalizzata tramite associazione di dati ed espressioni.
Script obbligatorio | <script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script> |
Esempi | |
Tutorial | Creare pagine AMP interattive |
Panoramica
Il componente amp-bind
ti permette di aggiungere dell'interattività stateful personalizzata alle tue pagine AMP tramite associazione di dati ed espressioni simili a JavaScript.
Un esempio semplice
Nell'esempio seguente, toccando il pulsante il testo dell'elemento <p>
cambia da "Hello World" a "Hello amp-bind".
<p [text]="'Hello ' + foo">Hello World</p>
<button on="tap:AMP.setState({foo: 'amp-bind'})">Say "Hello amp-bind"</button>
amp-bind
non valuta le espressioni al caricamento della pagina. Ciò significa che gli elementi visivi dovrebbero avere uno stato predefinito e non fare affidamento su amp-bind
per la visualizzazione iniziale. Come funziona?
amp-bind
ha tre componenti principali:
- Stato. Uno stato JSON mutevole orientato al documento. Nell'esempio precedente, state è vuoto prima che l'utente tocchi il pulsante. Dopo aver toccato il pulsante, state diventa
{foo: 'amp-bind'}
. - Espressioni. Espressioni simili a JavaScript che possono fare riferimento a state. L'esempio precedente contiene una sola espressione,
'Hello ' + foo
, che concatena il valore letterale della stringa'Hello '
e la variabile di statofoo
. All'interno di un'espressione possono essere utilizzati un massimo di 100 operandi. - Associazioni. Attributi speciali del modulo
[property]
che collegano la proprietà di un elemento a una expression. L'esempio precedente contiene una sola associazione,[text]
, che aggiorna il testo dell'elemento<p>
ogni volta che il valore dell'espressione cambia.
amp-bind
fa tutto il possibile per garantire velocità, sicurezza e prestazioni nelle pagine AMP.
Un esempio un po' più complesso
<!-- Store complex nested JSON data in <amp-state> elements. -->
<amp-state id="myAnimals">
<script type="application/json">
{
"dog": {
"imageUrl": "/img/dog.jpg",
"style": "greenBackground"
},
"cat": {
"imageUrl": "/img/cat.jpg",
"style": "redBackground"
}
}
</script>
</amp-state>
<p [text]="'This is a ' + currentAnimal + '.'">This is a dog.</p>
<!-- CSS classes can also be added or removed with [class]. -->
<p class="greenBackground" [class]="myAnimals[currentAnimal].style">
Each animal has a different background color.
</p>
<!-- Or change an image's src with the [src] binding. -->
<amp-img width="300" height="200" src="/img/dog.jpg" [src]="myAnimals[currentAnimal].imageUrl">
</amp-img>
<p><button on="tap:AMP.setState({currentAnimal: 'cat'})">Set to Cat</button>
Quando viene premuto il pulsante:
- Lo stato viene aggiornato con
currentAnimal
, definito come'cat'
. -
Le espressioni che dipendono da
currentAnimal
vengono valutate:'This is a ' + currentAnimal + '.'
=>'This is a cat.'
myAnimals[currentAnimal].style
=>'redBackground'
myAnimals[currentAnimal].imageUrl
=>/img/cat.jpg
-
Le associazioni che dipendono dalle espressioni modificate vengono aggiornate:
- Il testo del primo elemento
<p>
sarà "This is a cat." - L'attributo
class
del secondo elemento<p>
sarà "redBackground". - L'elemento
amp-img
mostrerà l'immagine di un gatto.
- Il testo del primo elemento
Dettagli
Stato
Tutti i documenti AMP che utilizzano amp-bind
presentano dei dati JSON mutevoli orientati al documento, detti state.
Inizializzare lo stato con amp-state
Lo stato di amp-bind
può essere inizializzato con il componente amp-state
:
<amp-state id="myState">
<script type="application/json">
{
"foo": "bar"
}
</script>
</amp-state>
Le espressioni possono fare riferimento a variabili di stato tramite la sintassi dot. In questo esempio, myState.foo
avrà come risultato "bar"
.
- Un elemento secondario JSON di
<amp-state>
ha una dimensione massima di 100 kB. - Un elemento
<amp-state>
può anche specificare un URL CORS anziché uno script JSON secondario. Per ulteriori dettagli, consulta l'appendice.
Aggiornare lo stato
Questo componente supporta l'azione refresh
, che può essere utilizzata per aggiornare
i contenuti dello stato.
<amp-state id="amp-state" ...></amp-state>
<!-- Clicking the button will refresh and refetch the json in amp-state. -->
<button on="tap:amp-state.refresh"></button>
Aggiornare lo stato con AMP.setState()
L'azione AMP.setState()
unisce un valore letterale oggetto allo stato. Ad esempio, quando viene premuto il pulsante in basso, AMP.setState()
unirà forzatamente il valore letterale oggetto allo stato.
<!-- Like JavaScript, you can reference existing
variables in the values of the object literal. -->
<button on="tap:AMP.setState({foo: 'bar', baz: myAmpState.someVariable})"></button>
In generale, gli oggetti nidificati saranno uniti fino a una profondità massima di 10. Tutte le variabili, incluse quelle introdotte da amp-state
, possono essere sostituite.
Quando attivato da certi eventi, AMP.setState()
può anche accedere ai dati correlati agli eventi nella proprietà event
.
<!-- The "change" event of this <input> element contains
a "value" variable that can be referenced via "event.value". -->
<input type="range" on="change:AMP.setState({myRangeValue: event.value})">
Modificare la cronologia con AMP.pushState()
L'azione AMP.pushState()
è simile ad AMP.setState()
, ma in aggiunta inserisce una nuova voce
nell'elenco della cronologia di navigazione. Accedendo a questa voce della cronologia, ad esempio, tornando indietro, viene ripristinato
il valore precedente delle variabili impostate da AMP.pushState()
.
Ad esempio:
<button on="tap:AMP.pushState({foo: '123'})">Set 'foo' to 123</button>
- Se tocchi il pulsante, la variabile
foo
sarà impostata su 123 e si creerà una nuova voce della cronologia. - Se torni indietro,
foo
verrà ripristinato al suo valore precedente, "bar" (equivale a chiamareAMP.setState({foo: 'bar'})
.
Espressioni
Le espressioni sono simili a JavaScript, con alcune differenze importanti.
Differenze da JavaScript
- Le espressioni possono accedere solo allo stato del documento che le contiene.
- Le espressioni non hanno accesso a elementi globali come
window
odocument
. - Puoi utilizzare solo gli operatori e le funzioni consentiti.
- I loop, le classi e le funzioni personalizzate in genere non sono consentiti. Le funzioni a freccia sono consentite come parametri, ad esempio,
Array.prototype.map
. - Le variabili non definite e l'indice della matrice fuori intervallo restituiscono
null
anzichéundefined
o degli errori. - Per garantire buone prestazioni, in una singola espressione possono attualmente essere presenti un massimo di 50 operandi. Nel caso in cui siano insufficienti per il tuo caso d'uso, non esitare a contattarci.
La grammatica completa e l'implementazione delle espressioni sono riportate in bind-expr-impl.jison e bind-expression.js.
Esempi
Di seguito sono riportate tutte le espressioni valide:
1 + '1' // 11
1 + (+'1') // 2
!0 // true
null || 'default' // 'default'
Funzioni consentite
Tipo di oggetto | Funzioni | Esempio |
---|---|---|
Array 1 | concat filter includes indexOf join lastIndexOf map reduce slice some sort (not-in-place)splice (not-in-place) | // Returns [1, 2, 3]. [3, 2, 1].sort() // Returns [1, 3, 5]. [1, 2, 3].map((x, i) => x + i) // Returns 6. [1, 2, 3].reduce((x, y) => x + y) |
Number | toExponential toFixed toPrecision toString | // Returns 3. (3.14).toFixed() // Returns '3.14'. (3.14).toString() |
String | charAt charCodeAt concat indexOf lastIndexOf slice split substr substring toLowerCase toUpperCase | // Returns 'abcdef'. abc'.concat('def') |
Math 2 | abs ceil floor max min random round sign | // Returns 1. abs(-1) |
Object 2 | keys values | // Returns ['a', 'b']. keys({a: 1, b: 2}) // Returns [1, 2]. values({a: 1, b: 2} |
Global 2 | encodeURI encodeURIComponent | // Returns 'Hello%20world'. encodeURIComponent('Hello world') |
1Le funzioni a freccia a parametro singolo non possono presentare parentesi. Ad esempio, utilizza x => x + 1
anziché (x) => x + 1
. Inoltre, sort()
e splice()
restituiscono copie modificate anziché operare sul posto
2Le funzioni statiche non dispongono di spazio dei nomi. Ad esempio, utilizza abs(-1)
anziché Math.abs(-1)
.
Definire macro con amp-bind-macro
I frammenti dell'espressione amp-bind
possono essere riutilizzati definendo una amp-bind-macro
. L'elemento amp-bind-macro
ti permette di definire un'espressione che accetta zero o più argomenti e fa riferimento allo stato corrente. Una macro può essere richiamata come una funzione facendo riferimento al valore del suo attributo id
in qualunque punto del tuo documento.
<amp-bind-macro id="circleArea" arguments="radius" expression="3.14 * radius * radius"></amp-bind-macro></p>
<div>
The circle has an area of <span [text]="circleArea(myCircle.radius)">0</span>.
</div>
Una macro può anche chiamare altre macro definite prima di essa. Una macro non può chiamare se stessa in modo ricorsivo.
Associazioni
Un'associazione è un attributo speciale del modulo [property]
che collega la proprietà di un elemento a un'espressione. Puoi anche utilizzare una sintassi alternativa compatibile con XML per mezzo di data-amp-bind-property
.
Quando lo stato cambia, le espressioni vengono rivalutate e le proprietà degli elementi associati vengono aggiornate con i nuovi risultati delle espressioni.
amp-bind
supporta le associazioni di dati in quattro tipi di stati dell'elemento:
Tipo | Attributi | Dettagli |
---|---|---|
Node.textContent | [text] | Supportato dalla maggior parte degli elementi di testo. |
Classi CSS | [class] | Il risultato dell'espressione deve essere una stringa delimitata da spazi. |
L'attributo hidden | [hidden] | Deve essere un'espressione booleana. |
Dimensione degli elementi AMP | [width] [height] | Modifica la larghezza e/o l'altezza dell'elemento AMP. |
Attributi specifici degli elementi | Vari |
Note sulle associazioni:
- Per motivi di sicurezza, le associazioni a
innerHTML
non sono consentite. - Tutte le associazioni degli attributi sono bonificate da valori non sicuri (ad esempio,
javascript:
). - I risultati delle espressioni booleane attivano o disattivano attributi booleani. Ad esempio,
<amp-video [controls]="expr"...>
. Quandoexpr
ha come risultatotrue
, l'elemento<amp-video>
ha l'attributocontrols
. Quandoexpr
ha come risultatofalse
, l'attributocontrols
viene rimosso. - I caratteri di parentesi quadre
[
e]
nei nomi degli attributi possono essere problematici durante la scrittura di XML (ad esempio, XHTML, JSX) o di attributi tramite API DOM. In questi casi, utilizza la sintassi alternativadata-amp-bind-x="foo"
anziché[x]="foo"
.
Attributi specifici degli elementi
È consentita l'associazione solo ai seguenti componenti e attributi:
Componente | Attributi | Comportamento |
---|---|---|
<amp-brightcove> | [data-account] [data-embed] [data-player] [data-player-id] [data-playlist-id] [data-video-id] | Modifica il video Brightcove visualizzato. |
<amp-carousel type=slides> | [slide] * | Modifica l'indice della diapositiva attualmente visualizzata. Vedi un esempio. |
<amp-date-picker> | [min] [max] | Imposta la data selezionabile meno recente. Imposta la data selezionabile più recente. |
<amp-google-document-embed> | [src] [title] | Mostra il documento all'URL aggiornato. Modifica il titolo del documento. |
<amp-iframe> | [src] | Modifica l'URL di origine dell'iframe. |
<amp-img> | [alt] [attribution] [src] [srcset] | Quando effettui un'associazione a [src] , assicurati di associare anche a [srcset] in modo che l'associazione funzioni su cache.Vedi gli attributi amp-img corrispondenti. |
<amp-lightbox> | [open] * | Attiva o disattiva la visualizzazione della lightbox. Suggerimento: utilizza on="lightboxClose: AMP.setState(...)" per aggiornare le variabili quando la lightbox è chiusa. |
<amp-list> | [src] | Se l'espressione è una stringa, recupera e mostra JSON dall'URL della stringa. Se l'espressione è un oggetto o un array, mostra i dati dell'espressione. |
<amp-selector> | [selected] *[disabled] | Modifica gli elementi secondari attualmente selezionati identificati dai loro valori attributo option . Supporta un elenco di valori separati da virgola per la selezione multipla. Vedi un esempio. |
<amp-state> | [src] | Recupera JSON dal nuovo URL e lo unisce allo stato esistente. Tieni presente che il successivo aggiornamento ignorerà gli elementi <amp-state> per impedire i cicli. |
<amp-video> | [alt] [attribution] [controls] [loop] [poster] [preload] [src] | Vedi gli attributi amp-video corrispondenti. |
<amp-youtube> | [data-videoid] | Cambia il video di YouTube visualizzato. |
<a> | [href] | Cambia il link. |
<button> | [disabled] [type] [value] | Vedi gli attributi button corrispondenti. |
<details> | [open] | Vedi gli attributi details corrispondenti. |
<fieldset> | [disabled] | Attiva o disattiva fieldset. |
<image> | [xlink:href] | Vedi gli attributi image corrispondenti. |
<input> | [accept] [accessKey] [autocomplete] [checked] [disabled] [height] [inputmode] [max] [maxlength] [min] [minlength] [multiple] [pattern] [placeholder] [readonly] [required] [selectiondirection] [size] [spellcheck] [step] [type] [value] [width] | Vedi gli attributi input corrispondenti. |
<option> | [disabled] [label] [selected] [value] | Vedi gli attributi options corrispondenti. |
<optgroup> | [disabled] [label] | Vedi gli attributi optgroup corrispondenti. |
<select> | [autofocus] [disabled] [multiple] [required] [size] | Vedi gli attributi select corrispondenti. |
<source> | [src] [type] | Vedi gli attributi source corrispondenti. |
<track> | [label] [src] [srclang] | Vedi gli attributi track corrispondenti. |
<textarea> | [autocomplete] [autofocus] [cols] [disabled] [maxlength] [minlength] [placeholder] [readonly] [required] [rows] [selectiondirection] [selectionend] [selectionstart] [spellcheck] [wrap] | Vedi gli attributi textarea corrispondenti. |
*Denota degli attributi associabili che non possiedono una controparte non associabile.
Debug
Esegui dei test in modalità sviluppatore (con il frammento dell'URL #development=1
) per identificare avvisi ed errori durante lo sviluppo e per accedere a funzioni speciali di debug.
Avvisi
In modalità sviluppatore, amp-bind
genererà un avviso quando il valore predefinito di un attributo associato non coincide con il risultato iniziale dell'espressione corrispondente. Ciò aiuta a prevenire cambiamenti non intenzionali causati da modifiche in altre variabili di stato. Ad esempio:
<!-- Il valore di classe predefinito dell'elemento ('def') non corrisponde al risultato dell'espressione [class] ('abc'),
quindi verrà generato un avviso in modalità sviluppatore. -->
<p class="def" [class]="'abc'"></p>
In modalità sviluppatore, amp-bind
genererà un avviso anche quando viene tolto il riferimento a variabili o proprietà non definite. Ciò aiuta anche a prevenire cambiamenti non intenzionali causati dai risultati null
delle espressioni. Ad esempio:
<amp-state id="myAmpState">
<script type="application/json">
{ "foo": 123 }
</script>
</amp-state>
<!-- The amp-state#myAmpState does not have a `bar` variable, so a warning
will be issued in development mode. -->
<p [text]="myAmpState.bar">Some placeholder text.</p>
Errori
Esistono diversi tipi di errori di runtime che possono verificarsi quando si utilizza amp-bind
.
Tipo | Messaggio | Suggerimento |
---|---|---|
Associazione non valida | L'associazione a [someBogusAttribute] su <P> non è consentita. | Utilizza solo associazioni consentite. |
Errore di sintassi | Errore nella compilazione dell'espressione in... | Controlla che l'espressione non presenti errori ortografici. |
Funzioni non consentite | alert non è una funzione supportata. | Utilizza solo le funzioni consentite. |
Risultato bonificato | "javascript:alert(1)" non è un risultato valido per [href]. | Evita espressioni o protocolli URL non accettati dallo strumento di convalida AMP. |
Violazione CSP | Impossibile creare un worker da 'blob:...' perché viola la seguente direttiva relativa alle norme sulla sicurezza dei contenuti... | Aggiungi default-src blob: alle norme sulla sicurezza dei contenuti della tua origine. amp-bind delega la porzione più impegnativa dell'elaborazione a un web worker dedicato per garantire buone prestazioni. |
Stato di debug
Utilizza AMP.printState()
per visualizzare lo stato corrente sulla console.
Appendice
Specifica di <amp-state>
Un elemento amp-state
può contenere un elemento secondario <script>
O un attributo src
che contiene a sua volta un URL CORS per un endpoint JSON, ma non entrambi.
<amp-state id="myLocalState">
<script type="application/json">
{
"foo": "bar"
}
</script>
</amp-state></p>
<p><amp-state id="myRemoteState" src="https://data.com/articles.json">
</amp-state>
Gruppi di XHR
AMP raggruppa le XMLHttpRequests (XHR) negli endpoint JSON, ovvero puoi utilizzare una singola richiesta di dati JSON come origine dati per più consumatori (ad esempio, più elementi amp-state
) in una pagina AMP. Ad esempio, se l'elemento amp-state
crea un XHR per un endpoint, mentre l'XHR è in esecuzione tutti i successivi XHR per lo stesso endpoint non si attiveranno e restituiranno invece i risultati del primo XHR.
Attributi
src | L'URL dell'endpoint remoto che restituirà il JSON per aggiornare questo amp-state . Deve essere un servizio HTTP CORS. L'attributo src consente tutte le sostituzioni di variabili URL standard. Per ulteriori informazioni, consulta la Guida alle sostituzioni. L'endpoint deve implementare i requisiti specificati nella specifica Richieste CORS in AMP.
|
credentials (facoltativo) | Definisce un'opzione credentials come specificato dall'API Fetch.
include . Se questo valore è impostato, la risposta deve rispettare le norme sulla sicurezza AMP CORS. |
Deep-merge con AMP.setState()
Quando AMP.setState()
viene chiamato, amp-bind
effettua il deep-merge il valore letterale oggetto fornito con lo stato corrente. Tutte le variabili del valore letterale oggetto sono scritte direttamente nello stato, eccetto per gli oggetti nidificati, che vengono uniti in modo ricorsivo. Le primitive e gli array nello stato vengono sempre sostituite da variabili con lo stesso nome nel valore letterale oggetto.
Considera l'esempio seguente:
{
<!-- State is empty -->
}
<button on="tap:AMP.setState({employee: {name: 'John Smith', age: 47, vehicle: 'Car'}})"...></button>
<button on="tap:AMP.setState({employee: {age: 64}})"...></button>
Quando viene premuto il primo pulsante, lo stato cambia in:
{
employee: {
name: 'John Smith',
age: 47,
vehicle: 'Car',
}
}
Quando viene premuto il secondo pulsante, amp-bind
unisce in modo ricorsivo l'argomento letterale oggetto {employee: {age: 64}}
nello stato esistente.
{
employee: {
name: 'John Smith',
age: 64,
vehicle: 'Car',
}
}
employee.age
è stato aggiornato; tuttavia, le chiavi employee.name
ed employee.vehicle
non sono cambiate.
Tieni presente che amp-bind
genererà un errore se chiami AMP.setState()
con un valore letterale oggetto che contiene riferimenti circolari.
Rimuovere una variabile
Per rimuovere una variabile di stato esistente, imposta il suo valore su null
in AMP.setState()
. Partendo dallo stato dell'esempio precedente, premi:
<button on="tap:AMP.setState({employee: {vehicle: null}})"...></button>
Lo stato verrà modificato in:
{
employee: {
name: 'John Smith',
age: 48,
}
}
Analogamente:
<button on="tap:AMP.setState({employee: null})"...></button>
Lo stato verrà modificato in:
{
<!-- State is empty -->
}
Grammatica delle espressioni
La grammatica simile a BNF per le espressioni amp-bind
:
expr:
operation
| invocation
| member_access
| '(' expr ')'
| variable
| literal
operation:
!' expr
| '-' expr
| '+' expr
| expr '+' expr
| expr '-' expr
| expr '*' expr
| expr '/' expr
| expr '%' expr
| expr '&&' expr
| expr '||' expr
| expr '<=' expr
| expr '<' expr
| expr '>=' expr
| expr '>' expr
| expr '!=' expr
| expr '==' expr
| expr '?' expr ':' expr
invocation:
expr '.' NAME args
args:
(' ')'
| '(' array ')'
;
<p>member_access:
expr member
;
<p>member:
.' NAME
| '[' expr ']'
<p>variable:
NAME
;
literal:
STRING
| NUMBER
| TRUE
| FALSE
| NULL
| object_literal
| array_literal
array_literal:
[' ']'
| '[' array ']'
array:
expr
| array ',' expr
object_literal:
{' '}'
| '{' object '}'</p>
object:
key_value
| object ',' key_value</p>
key_value:
expr ':' expr
Hai letto questo documento decine di volte ma non risponde a tutte le tue domande? Forse ci sono altre persone col tuo stesso problema: entra in contatto con loro su Stack Overflow.
Vai a Stack Overflow Hai trovato un bug o una funzione mancante?Il progetto AMP invita tutti a partecipare e dare il proprio contributo! Ci auguriamo che tu possa partecipare regolarmente alla nostra community open source, ma saremo anche lieti di ricevere eventuali contributi una-tantum sulle questioni che ti interessano.
Vai a GitHub