- Descripción general
- Un ejemplo muy sencillo
- Información detallada
- País
- Inicializar el estado mediante amp-state
- Actualizar el estado
- Actualizar el estado mediante AMP.setState()
- Modificar el historial mediante AMP.pushState()
- Expresiones
- Diferencias con respecto a JavaScript
- Ejemplos
- Funciones incluidas en la lista blanca
- Definir macros mediante amp-bind-macro
- Bindings
- Atributos específicos de los elementos
- Depuración
- Advertencias
- Errores
- Estado de depuración
- Apéndice
- Especificación de <amp-state>
- Procesamiento por lotes de XHR
- Atributos
- Combinar con deepmerge mediante AMP.setState()
- Eliminar una variable
- Gramática de las expresiones
amp-bind
Description
Permite que los elementos muten como respuesta a las acciones del usuario o a cambios de datos mediante data binding y expresiones simples similares a JS.
Required Scripts
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
Ejemplos
Añade interactividad personalizada utilizando data bindings y expresiones.
| Secuencia de comandos obligatoria | <script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script> |
| Ejemplos | |
| Tutoriales | Crear páginas de AMP interactivas |
Descripción general
El componente amp-bind te permite añadir interactividad personalizada con reconocimiento de estado a tus páginas de AMP mediante el uso de data binding y expresiones similares a JS.
Un ejemplo muy sencillo
En el siguiente ejemplo, si tocas el botón, el texto del elemento <p> pasará de ser "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 no evalúa las expresiones al cargar la página. Esto quiere decir que los elementos visuales deben tener un estado predeterminado y no depender de amp-bind para el renderizado inicial. ¿Cómo funciona?
amp-bind tiene tres componentes principales:
- Estado: un estado JSON mutable que afecta al documento. En el ejemplo que aparece más arriba, el estado está vacío antes de tocar el botón. Después de tocar el botón, el estado es
{foo: 'amp-bind'}. - Expresiones: son expresiones similares a JavaScript que pueden hacer referencia al estado. El ejemplo que aparece más arriba tiene una única expresión,
'Hello ' + foo, que concatena el literal de cadena'Hello 'y la variable de estadofoo. Una expresión puede contener un máximo de 100 operandos. - Bindings: son atributos especiales de la forma
[property]que enlazan la propiedad de un elemento con una expresión. El ejemplo anterior tiene un único binding,[text], que actualiza el texto del elemento<p>cada vez que cambia el valor de la expresión.
amp-bind pone un especial énfasis en garantizar la velocidad, la seguridad y el rendimiento de las páginas de AMP.
Veamos un ejemplo ligeramente más complejo:
<!-- Se pueden almacenar datos JSON complejos anidados en elementos <amp-state> -->
<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 + '.'">Esto es un perro.</p>
<!-- También se pueden añadir o eliminar clases de CSS mediante [class]. -->
<p class="greenBackground" [class]="myAnimals[currentAnimal].style">
Cada animal tiene un color de fondo diferente.
</p>
<!-- O bien cambia el src de una imagen por el binding [src]. -->
<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>
Cuando se pulsa el botón:
- El estado se actualiza con
currentAnimal, que se ha definido como'cat'. -
Se evalúan las expresiones que dependen de
currentAnimal:'This is a ' + currentAnimal + '.'=>'This is a cat.'myAnimals[currentAnimal].style=>'redBackground'myAnimals[currentAnimal].imageUrl=>/img/cat.jpg
-
Se actualizan los bindings que dependen de las expresiones modificadas:
- El texto del primer elemento
<p>será "This is a cat". - El atributo
classdel segundo elemento<p>será" "redBackground". - El elemento
amp-imghará que se muestre la imagen de un gato.
- El texto del primer elemento
Información detallada
País
Cada documento AMP que utiliza amp-bind contiene datos JSON mutables que afectan a dicho documento, a los que llamamos estado.
Inicializar el estado mediante amp-state
El estado de amp-bind se puede inicializar mediante el componente amp-state:
<amp-state id="myState">
<script type="application/json">
{
"foo": "bar"
}
</script>
</amp-state>
Las expresiones pueden hacer referencia a variables de estado mediante la sintaxis de puntos. En este ejemplo, myState.foo dará como resultado "bar".
- El JSON secundario de un elemento
<amp-state>puede tener un tamaño máximo de 100 KB. - También se puede especificar una URL de CORS para un elemento
<amp-state>en lugar de una secuencia de comandos JSON secundaria. Para obtener más información, consulta el Anexo.
Actualizar el estado
La acción refresh es compatible con este componente y se puede utilizar para actualizar el contenido del 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>
Actualizar el estado mediante AMP.setState()
La acción AMP.setState() combina una literal de objeto con el estado. Por ejemplo, cuando se pulsa el botón que aparece más abajo, AMP.setState() combinará mediante deepmerge la literal de objeto con el 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>
En general, los objetos anidados se combinarán con hasta 10 objetos por debajo. Se pueden omitir todas las variables, incluidas las que introduce amp-state.
Cuando se activa debido a determinados eventos, AMP.setState() también puede acceder a datos relacionados con los eventos de la propiedad 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 el historial mediante AMP.pushState()
La acción AMP.pushState() es similar a AMP.setState(), con la diferencia de que también añade una entrada a la pila del historial de navegación. Al deshacer esta entrada del historial (por ejemplo, volviendo a la página anterior), se restaura el valor anterior de las variables que define AMP.pushState().
Por ejemplo:
<button on="tap:AMP.pushState({foo: '123'})">Set 'foo' to 123</button>
- Al tocar el botón, se define la variable
fooen 123 y se envía una nueva entrada al historial. - Al volver a la página anterior, se restaurará el valor previo de
foo, es decir, "bar" (equivale a hacer una llamada aAMP.setState({foo: 'bar'}).
Expresiones
Las expresiones son similares a JavaScript, con algunas diferencias importantes.
Diferencias con respecto a JavaScript
- Las expresiones solo pueden acceder al estado del documento al que pertenecen.
- Las expresiones ****no tienen acceso a variables globales como
windowodocument. - Solo se pueden utilizar los operadores y las funciones incluidos en la lista blanca.
- Por lo general, no se admiten las funciones, las clases ni los bucles personalizados. Se admiten las funciones de flecha como parámetros; por ejemplo,
Array.prototype.map. - Las variables no definidas y los índices de matriz fuera de límites devuelven
nullen lugar deundefinedo de generar errores. - Actualmente, una expresión puede tener un máximo de 50 operandos por cuestiones de rendimiento. Ponte en contacto con nosotros si esta cantidad no te resulta suficiente.
Encontrarás la expresión gramatical completa y la implementación en bind-expr-impl.jison y bind-expression.js.
Ejemplos
Las expresiones que aparecen a continuación son válidas:
1 + '1' // 11
1 + (+'1') // 2
!0 // true
null || 'default' // 'default'
Funciones incluidas en la lista blanca
| Tipo de objeto | Funciones | Ejemplo |
|---|---|---|
Matriz1 | concatfilterincludesindexOfjoinlastIndexOfmapreduceslicesomesort (no es in-place)splice (no es 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) |
Número | toExponentialtoFixedtoPrecisiontoString | // Returns 3.
(3.14).toFixed() // Returns '3.14'.
(3.14).toString() |
Cadena | charAtcharCodeAtconcatindexOflastIndexOfslicesplitsubstrsubstringtoLowerCasetoUpperCase | // Returns 'abcdef'.
abc'.concat('def') |
Operación matemática2 | absceilfloormaxminrandomroundsign | // Returns 1.
abs(-1) |
Objeto2 | keysvalues | // Returns ['a', 'b'].
keys({a: 1, b: 2}) // Returns [1, 2].
values({a: 1, b: 2} |
Global2 | encodeURIencodeURIComponent | // Returns 'Hello%20world'.
encodeURIComponent('Hello world') |
1 Las funciones de flecha de un solo parámetro no pueden tener paréntesis. Por ejemplo, utiliza x => x + 1 en lugar de (x) => x + 1. Además, sort() y splice() devuelven copias modificadas en lugar de funcionar in situ.
2 Las funciones estáticas no llevan espacios de nombre. Por ejemplo, utiliza abs(-1) en lugar de Math.abs(-1).
Definir macros mediante amp-bind-macro
Los fragmentos de expresión de amp-bind se pueden reutilizar definiendo un amp-bind-macro. Este elemento` permite definir una expresión que utiliza cero o más argumentos y hace referencia al estado actual. Se puede invocar una macro como si fuera una función haciendo referencia en cualquier parte del documento al valor de su atributoid`.
<amp-bind-macro id="circleArea" arguments="radius" expression="3.14 * radius * radius"></amp-bind-macro>
<div>
El círculo tiene un área de <span [text]="circleArea(myCircle.radius)">0</span>.
</div>
Una macro también puede llamar a otras macros que se han definido antes que a sí misma. Una macro no puede hacerse llamadas a sí misma de forma recursiva.
Bindings
Un binding es un atributo especial del formulario [property] que vincula la propiedad de un elemento con una expresión. También se puede utilizar una sintaxis alternativa compatible con XML mediante data-amp-bind-property.
Cuando el estado cambia, las expresiones se vuelven a evaluar y las propiedades de los elementos vinculados se actualizan con los resultados de la nueva expresión.
amp-bind admite data bindings para cuatro tipos de estado de elemento:
| Tipo | Atributos | Información detallada |
|---|---|---|
Node.textContent | [text] | Compatible con la mayoría de los elementos de texto. |
| Clases de CSS | [class] | El resultado de la expresión debe ser una cadena delimitada por espacios. |
Atributo hidden | [hidden] | Debe ser una expresión booleana. |
| Tamaño de los elementos AMP | [width][height] | Cambia la anchura o la altura del elemento AMP. |
| Atributos específicos de elementos | Varios |
Notas sobre los bindings:
- Por motivos de seguridad, no se permite hacer bindings con
innerHTML. - Todos los bindings de atributo se depuran para eliminar los valores que no son seguros (p. ej.,
javascript:). - Los resultados de las expresiones booleanas habilitan o inhabilitan los atributos booleanos. Por ejemplo:
<amp-video [controls]="expr"...>. Cuandoexprda como resultadotrue, el elemento<amp-video>tiene el atributocontrols. Cuandoexprda como resultadofalse, se elimina el atributocontrols. - Incluir caracteres de corchetes
[y]en nombres de atributos puede dar problemas al escribir XML (p. ej., XHTML o JSX) o atributos a través de las API de DOM. En estos casos, utiliza la sintaxis alternativadata-amp-bind-x="foo"en lugar de[x]="foo".
Atributos específicos de los elementos
Solo se admiten los bindings a los siguientes componentes y atributos:
| Componente | Atributos | Comportamiento |
|---|---|---|
<amp-brightcove> | [data-account][data-embed][data-player][data-player-id][data-playlist-id][data-video-id] | Cambia el vídeo de Brightcove que se muestra. |
<amp-carousel type=slides> | [slide]* | Cambia el índice de diapositiva que se muestra actualmente. Ver un ejemplo |
<amp-date-picker> | [min][max] | Define la fecha más temprana que se puede seleccionar. Define la fecha más tardía que se puede seleccionar. |
<amp-google-document-embed> | [src][title] | Muestra el documento en la URL actualizada. Cambia el título del documento. |
<amp-iframe> | [src] | Cambia la URL de origen del iframe. |
<amp-img> | [alt][attribution][src][srcset] | Al hacer un binding a [src], asegúrate de hacerlo también a [srcset] para que el funcione en caché.Consulta los atributos de "amp-img" correspondientes. |
<amp-lightbox> | [open]* | Muestra u oculta el lightbox. Consejo: Utiliza on="lightboxClose: AMP.setState(...)" para actualizar las variables cuando el lightbox esté cerrado. |
<amp-list> | [src] | Si la expresión es una cadena, recupera y renderiza un JSON de la URL de la cadena; si es un objeto o una matriz, renderiza los datos de la expresión. |
<amp-selector> | [selected]*[disabled] | Cambia los elementos secundarios seleccionados actualmente identificados por sus valores de atributo option. Admite una lista de valores separados por comas si hay varios elementos seleccionados. Ver un ejemplo |
<amp-state> | [src] | Recupera un JSON de la nueva URL y lo combina con el estado que ya existe. Ten en cuenta que la siguiente actualización ignorará los elementos <amp-state> para evitar los ciclos. |
<amp-video> | [alt][attribution][controls][loop][poster][preload][src] | Consulta los atributos de "amp-video" correspondientes. |
<amp-youtube> | [data-videoid] | Cambia el vídeo de YouTube que se muestra. |