- Visão geral
- Um exemplo simples
- Detalhes
- Estado
- Inicializar o estado com amp-state
- Estado de atualização
- Atualizar o estado com AMP.setState()
- Modificar o histórico com AMP.pushState()
- Expressões
- Diferenças em relação ao JavaScript
- Exemplos
- Funções da lista de permissões
- Definir macros com amp-bind-macro
- Vinculações
- Atributos específicos de elementos
- Depuração
- Avisos
- Erros
- Estado de depuração
- Apêndice
- Especificação <amp-state>
- Criação de lote XHR
- Atributos
- Mesclagem com AMP.setState()
- Remover uma variável
- Gramática de expressões
Important: this documentation is not applicable to your currently selected format stories!
amp-bind
Description
Permite que os elementos se alterem em resposta às ações do usuário ou a mudanças nos dados por meio de expressões simples semelhantes às do JavaScript e vinculação de dados.
Required Scripts
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
Adiciona interatividade personalizada com expressões e vinculação de dados.
Script obrigatório | <script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script> |
Exemplos | |
Tutoriais | Criação de páginas AMP interativas |
Visão geral
O componente amp-bind
permite que você adicione interatividade personalizada com estado às suas páginas AMP por meio de vinculação de dados e expressões semelhantes às do JavaScript.
Um exemplo simples
No exemplo a seguir, o toque no botão altera o texto do elemento <p>
de “Hello World” para “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
não avalia expressões durante o carregamento da página. Isso significa que os elementos visuais precisam receber um estado padrão e não depender de amp-bind
para a renderização inicial. Como funciona?
amp-bind
tem três componentes principais:
- Estado: um estado JSON mutável com escopo de documento. No exemplo acima, o estado está vazio antes do toque no botão. Depois de tocar no botão, o estado é
{foo: 'amp-bind'}
. - Expressões: são expressões semelhantes às do JavaScript que podem fazer referência ao estado. O exemplo acima tem uma única expressão,
Hello ' + foo
, que concatena a string literalHello
e a variável de estadofoo
. Há um limite de 100 operandos que podem ser usados em uma expressão. - Vinculações: são atributos especiais da forma
[property]
que vinculam a propriedade de um elemento a uma expressão. O exemplo acima tem uma única vinculação,[text]
, que atualiza o texto do elemento<p>
toda vez que o valor da expressão é alterado.
O amp-bind
tem um cuidado especial para garantir velocidade, segurança e desempenho para as páginas AMP.
Um exemplo um pouco mais complexo
<!-- 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>
<button on="tap:AMP.setState({currentAnimal: 'cat'})">Set to Cat</button>
Quando o botão é pressionado:
- O estado é atualizado com
currentAnimal
definido como'cat'
. -
As expressões que dependem de
currentAnimal
são avaliadas:'This is a ' + currentAnimal + '.'
=>'This is a cat.'
myAnimals[currentAnimal].style
=>'redBackground'
myAnimals[currentAnimal].imageUrl
=>/img/cat.jpg
-
As vinculações que dependem das expressões alteradas são atualizadas:
- O texto do primeiro elemento
<p>
será "This is a cat". - O atributo
class
do segundo elemento<p>
será "redBackground". - O elemento
amp-img
mostrará a imagem de um gato.
- O texto do primeiro elemento
Detalhes
Estado
Cada documento AMP que usa o amp-bind
tem dados JSON mutáveis com escopo de documento, ou estado.
Inicializar o estado com amp-state
O estado do amp-bind
pode ser inicializado com o componente amp-state
:
<amp-state id="myState">
<script type="application/json">
{
"foo": "bar"
}
</script>
</amp-state>
As expressões podem referenciar variáveis de estado com a sintaxe de dot. Neste exemplo, myState.foo
será avaliado como "bar"
.
- O JSON filho de um elemento
<amp-state>
tem o tamanho máximo de 100 KB. - Um elemento
<amp-state>
também pode especificar um URL CORS em vez de um script JSON filho. Consulte o Apêndice para ver mais detalhes.
Estado de atualização
A ação refresh
é compatível com este componente e pode ser usada para atualizar o conteúdo do estado.
<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>
Atualizar o estado com AMP.setState()
A ação AMP.setState()
mescla o literal de um objeto ao estado. Por exemplo, quando o botão abaixo for pressionado, o AMP.setState()
mesclará o literal do objeto com o estado.
<!-- 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>
Em geral, os objetos aninhados são mesclados com uma profundidade máxima de 10. Todas as variáveis, incluindo as introduzidas pelo amp-state
, podem ser modificadas.
Quando acionado por determinados eventos, o AMP.setState()
também pode acessar dados relacionados a eventos na propriedade 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})">
Modificar o histórico com AMP.pushState()
A ação AMP.pushState()
é semelhante à AMP.setState()
, mas também envia uma nova entrada para a pilha do histórico do navegador. Abrir essa entrada do histórico (por exemplo, navegando de volta) restaura o valor anterior de variáveis definidas por AMP.pushState()
.
Por exemplo:
<button on="tap:AMP.pushState({foo: '123'})">Set 'foo' to 123</button>
- Tocar no botão configura a variável
foo
como 123 e envia uma nova entrada de histórico. - Navegar de volta restaura
foo
para o valor anterior, "bar" (o que é equivalente a chamarAMP.setState({foo: 'bar'})
.
Expressões
As expressões são semelhantes às do JavaScript, mas têm algumas diferenças importantes.
Diferenças em relação ao JavaScript
- As expressões só podem acessar o estado do documento que as contém.
- As expressões não têm acesso a globais, como
window
oudocument
. - Apenas operadores e funções da lista de permissões podem ser usados.
- Funções, classes e loops personalizados geralmente não são permitidos. As funções de seta são permitidas como parâmetros, por exemplo,
Array.prototype.map
. - Variáveis indefinidas e array-index-out-of-bounds retornam
null
, em vez deundefined
ou de gerar erros. - Uma expressão única atualmente está limitada a 50 operandos, por motivos de desempenho. Fale conosco se esse número for insuficiente para seu caso de uso.
A gramática e a implementação completas da expressão podem ser encontradas em bind-expr-impl.jison e bind-expression.js.
Exemplos
Todas as expressões a seguir são válidas:
1 + '1' // 11
1 + (+'1') // 2
!0 // true
null || 'default' // 'default'
Funções da lista de permissões
Tipo de objeto | Funções | Exemplo |
---|---|---|
Array 1 | concat filter includes indexOf join lastIndexOf map reduce slice some sort (não em vigor)splice (não em vigor) | // 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') |
1As funções de seta com um único parâmetro não podem ter parênteses. Por exemplo, use x => x + 1
, em vez de (x) => x + 1
. Além disso, sort()
e splice()
retornam cópias modificadas em vez de operar no local.
2Funções estáticas não contêm namespaces. Por exemplo, use abs(-1)
em vez de Math.abs(-1)
.
Definir macros com amp-bind-macro
Fragmentos da expressão amp-bind
podem ser reutilizados definindo uma amp-bind-macro
. O elemento amp-bind-macro
permite que você defina uma expressão que use zero ou mais argumentos e faça referência ao estado atual. Uma macro pode ser invocada da mesma forma que uma função, referenciando o valor do atributo id
em qualquer lugar no seu documento.
<amp-bind-macro id="circleArea" arguments="radius" expression="3.14 * radius * radius"></amp-bind-macro>
<div>
The circle has an area of <span [text]="circleArea(myCircle.radius)">0</span>.
</div>
Uma macro também pode chamar outras macros definidas antes dela mesma. Uma macro não pode chamar a si mesma recorrentemente.
Vinculações
Uma vinculação é um atributo especial da forma [property]
que vincula a propriedade de um elemento a uma expressão. Como alternativa, uma sintaxe compatível com XML também pode ser usada na forma de data-amp-bind-property
.
Quando o estado é alterado, as expressões são reavaliadas e as propriedades dos elementos vinculados são atualizadas com os resultados da nova expressão.
amp-bind
é compatível com vinculações de dados em quatro tipos de estados de elementos:
Tipo | Atributos | Detalhes |
---|---|---|
Node.textContent | [text] | Compatível com a maioria dos elementos de texto. |
Classes CSS | [class] | O resultado da expressão precisa ser uma string delimitada por espaços. |
Atributo hidden | [hidden] | Precisa ser uma expressão booleana. |
Tamanho dos elementos AMP | [width] [height] | Altera a largura e/ou altura do elemento AMP. |
Atributos específicos de elementos | Vários |
Observações sobre vinculações:
- Por motivos de segurança, a vinculação a
innerHTML
não é permitida. - Todas as vinculações de atributo são verificadas em busca de valores não seguros (por exemplo,
javascript:
). - Resultados de expressão booleana alternam atributos booleanos. Por exemplo:
<amp-video [controls]="expr"...>
. Quandoexpr
é avaliado comotrue
, o elemento<amp-video>
tem o atributocontrols
. Quandoexpr
é avaliado comofalse
, o atributocontrols
é removido. - Os caracteres de colchete
[
e]
em nomes de atributos podem ser problemáticos quando se escreve em XML (por exemplo, XHTML, JSX) ou ao escrever atributos por meio de APIs DOM. Nesses casos, use a sintaxe alternativadata-amp-bind-x="foo"
, em vez de[x]="foo"
.
Atributos específicos de elementos
Apenas a vinculação aos seguintes componentes e atributos é permitida:
Componente | Atributos | Comportamento |
---|---|---|
<amp-brightcove> | [data-account] [data-embed] [data-player] [data-player-id] [data-playlist-id] [data-video-id] | Altera o vídeo Brightcove exibido. |
<amp-carousel type=slides> | [slide] * | Altera o índice do slide exibido no momento. Veja um exemplo. |
<amp-date-picker> | [min] [max] | Define a data selecionável mais antiga. Define a data selecionável mais recente. |
<amp-google-document-embed> | [src] [title] | Exibe o documento no URL atualizado. Altera o título do documento. |
<amp-iframe> | [src] | Altera o URL de origem do iframe. |
<amp-img> | [alt] [attribution] [src] [srcset] | Ao vincular a [src] , vincule também a [srcset] para que a vinculação funcione no cache.Veja os atributos amp-img correspondentes. |
<amp-lightbox> | [open] * | Alterna a exibição do lightbox. Dica: use on="lightboxClose: AMP.setState(...)" para atualizar variáveis quando o lightbox estiver fechado. |
<amp-list> | [src] | Se a expressão for uma string, o atributo buscará e renderizará JSON a partir do URL da string. Se a expressão for um objeto ou matriz, o atributo renderizará os dados da expressão. |
<amp-selector> | [selected] *[disabled] | Altera os elementos filhos selecionados atualmente identificados pelos valores do atributo option . Aceita uma lista separada por vírgulas de valores para seleção múltipla. Veja um exemplo. |
<amp-state> | [src] | Busca JSON a partir do novo URL e mescla-o com o estado existente. Observe que a atualização seguinte ignorará os elementos <amp-state> para evitar ciclos. |
<amp-video> | [alt] [attribution] [controls] [loop] [poster] [preload] [src] | Veja os atributos amp-video correspondentes. |
<amp-youtube> | [data-videoid] | Altera o vídeo do YouTube exibido. |
<a> | [href] | Altera o link. |
<button> | [disabled] [type] [value] | Veja os atributos de button correspondentes. |
<details> | [open] | Veja os atributos de details correspondentes. |
<fieldset> | [disabled] | Ativa ou desativa o conjunto de campos. |
<image> | [xlink:href] | Veja os atributos de image correspondentes. |
<input> | [accept] [accessKey] [autocomplete] [checked] [disabled] [height] [inputmode] [max] [maxlength] [min] [minlength] [multiple] [pattern] [placeholder] [readonly] [required] [selectiondirection] [size] [spellcheck] [step] [type] [value] [width] | Veja os atributos de input correspondentes. |
<option> | [disabled] [label] [selected] [value] | Veja os atributos de option correspondentes. |
<optgroup> | [disabled] [label] | Veja os atributos de optgroup correspondentes. |
<select> | [autofocus] [disabled] [multiple] [required] [size] | Veja os atributos de select correspondentes. |
<source> | [src] [type] | Veja os atributos de source correspondentes. |
<track> | [label] [src] [srclang] | Veja os atributos de track correspondentes. |
<textarea> | [autocomplete] [autofocus] [cols] [disabled] [maxlength] [minlength] [placeholder] [readonly] [required] [rows] [selectiondirection] [selectionend] [selectionstart] [spellcheck] [wrap] | Veja os atributos de textarea correspondentes. |
*Indica atributos vinculáveis que não têm uma contraparte não vinculável.
Depuração
Teste no modo de desenvolvimento (com o fragmento de URL #development=1
) para destacar avisos e erros durante o desenvolvimento e para acessar funções especiais de depuração.
Avisos
No modo de desenvolvimento, o amp-bind
emite um aviso quando o valor padrão de um atributo vinculado não corresponde ao resultado inicial da expressão correspondente. Isso pode ajudar a evitar mutações não intencionais causadas por alterações em outras variáveis de estado. Exemplo:
<!-- The element's default class value ('def') doesn't match the expression result for [class] ('abc'),
so a warning will be issued in development mode. -->
<p class="def" [class]="'abc'"></p>
No modo de desenvolvimento, o amp-bind
também emite um aviso ao desreferenciar variáveis ou propriedades indefinidas. Isso também pode ajudar a evitar mutações não intencionais devido a resultados de expressão null
. Exemplo:
<amp-state id="myAmpState">
<script type="application/json">
{ "foo": 123 }
</script>
</amp-state></p>
<!-- 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>
Erros
Há vários tipos de erros de tempo de execução que podem ser encontrados ao trabalhar com o amp-bind
.
Tipo | Mensagem | Sugestão |
---|---|---|
Vinculação inválida | A vinculação a [someBogusAttribute] em <P> não é permitida. | Use somente vinculações da lista de permissões. |
Erro de sintaxe | Erro de compilação de expressão em… | Verifique se há erros de digitação na expressão. |
Funções não permitidas | alert não é uma função compatível. | Use somente funções da lista de permissões. |
Resultado corrigido | "javascript:alert(1)" não é um resultado válido para [href]. | Evite protocolos ou expressões de URL banidos que possam ser reprovados pelo Validador de AMP. |
Violação da CSP | Criação de um worker a partir de 'blob:...' recusada porque isso viola a seguinte diretiva da Política de Segurança de Conteúdo… | Adicione default-src blob: à Política de Segurança de Conteúdo da sua origem. O amp-bind delega o trabalho dispendioso a um worker da Web dedicado para garantir um bom desempenho. |
Estado de depuração
Use o AMP.printState()
para imprimir o estado atual no console.
Apêndice
Especificação <amp-state>
Um elemento amp-state
pode conter um elemento <script>
filho OU um atributo src
contendo um URL CORS para um endpoint JSON remoto, mas não ambos.
<amp-state id="myLocalState">
<script type="application/json">
{
"foo": "bar"
}
</script>
</amp-state>
<amp-state id="myRemoteState" src="https://data.com/articles.json">
</amp-state>
Criação de lote XHR
O AMP cria lotes XMLHttpRequests (XHRs) em endpoints JSON, ou seja, você pode usar uma única solicitação de dados JSON como uma fonte de dados para vários consumidores (por exemplo, vários elementos <amp-state>
) em uma página AMP. Por exemplo, se seu elemento <amp-state>
fizer um XHR para um endpoint durante o período de veiculação do XHR, todos os XHRs subsequentes para o mesmo endpoint não serão acionados e, em vez disso, retornarão os resultados do primeiro XHR.
Atributos
src | O URL do endpoint remoto que retornará o JSON que atualizará esse amp-state . Ele precisa ser um serviço HTTP CORS. O atributo src permite todas as substituições de variáveis de URL padrão. Consulte o Guia de substituições (em inglês) para ver mais informações. o endpoint precisa implementar os requisitos definidos nas especificações de Solicitações CORS nas AMP (link em inglês).
|
credentials (opcional) | Define uma opção de credentials conforme especificado pela API Fetch.
include . Se esse valor estiver configurado, a resposta precisará seguir as diretrizes de segurança do CORS AMP (link em inglês). |
Mesclagem com AMP.setState()
Quando o AMP.setState()
é chamado de amp-bind
, ele mescla o literal do objeto fornecido com o estado atual. Todas as variáveis do literal do objeto são escritas diretamente no estado, exceto para objetos aninhados, que são mesclados de modo recorrente. Primitivas e matrizes que estão no estado são sempre substituídas por variáveis com o mesmo nome do literal do objeto.
Veja o exemplo a seguir:
{
<!-- 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 o primeiro botão é pressionado, o estado muda para:
{
employee: {
name: 'John Smith',
age: 47,
vehicle: 'Car',
}
}
Quando o segundo botão for pressionado, o amp-bind
mesclará recursivamente o argumento do literal do objeto, {employee: {age: 64}}
, com o estado existente.
{
employee: {
name: 'John Smith',
age: 64,
vehicle: 'Car',
}
}
employee.age
foi atualizado, mas as chaves employee.name
e employee.vehicle
não foram alteradas.
O amp-bind
gerará um erro se você chamar AMP.setState()
com um literal de objeto que contenha referências circulares.
Remover uma variável
Remova uma variável de estado existente definindo o valor dela como null
em AMP.setState()
. Começando com o estado do exemplo anterior, pressionar:
<button on="tap:AMP.setState({employee: {vehicle: null}})"...></button>
Mudará o estado para:
{
employee: {
name: 'John Smith',
age: 48,
}
}
Da mesma forma:
<button on="tap:AMP.setState({employee: null})"...></button>
Mudará o estado para:
{
<!-- State is empty -->
}
Gramática de expressões
A gramática semelhante a BNF para expressões 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 ')'
;
member_access:
expr member
;
member:
'.' NAME
| '[' expr ']'
variable:
NAME
;
literal:
STRING
| NUMBER
| TRUE
| FALSE
| NULL
| object_literal
| array_literal
array_literal:
'[' ']'
| '[' array ']'
array:
expr
| array ',' expr
object_literal:
'{' '}'
| '{' object '}'
object:
key_value
| object ',' key_value
key_value:
expr ':' expr
Você já leu este documento várias vezes, mas ainda ficou com dúvidas sem respostas? Talvez outras pessoas pensem da mesma forma. Procure entrar em contato com elas no Stack Overflow.
Ir para o Stack Overflow Encontrou um bug ou sente falta de um recurso?O projeto AMP incentiva fortemente sua participação e contribuições! Esperamos que você se torne um participante assíduo de nossa comunidade de código aberto, mas também agradecemos contribuições pontuais para problemas que você tenha particular interesse.
Ir para o GitHub