AMP

amp-bind

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.

Assista a este vídeo de introdução ao amp-bind.

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>

para melhorar o desempenho e evitar o risco de saltos de conteúdo inesperados, o 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:

  1. 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'}.
  2. 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 literal Hello e a variável de estado foo. Há um limite de 100 operandos que podem ser usados em uma expressão.
  3. 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:

  1. O estado é atualizado com currentAnimal definido como 'cat'.
  2. 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
  3. 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.

teste a demonstração ao vivo desse exemplo com anotações de código.

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 chamar AMP.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 ou document.
  • 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 de undefined 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
Array1 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')
Math2 abs
ceil
floor
max
min
random
round
sign
// Returns 1.
                          abs(-1)
Object2 keys
values
// Returns ['a', 'b'].
                            keys({a: 1, b: 2})
// Returns [1, 2].
                              values({a: 1, b: 2}
Global2 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