- Обзор
- Простой пример
- Описание
- Состояние
- Инициализация состояния с помощью amp-state
- Обновление состояния
- Обновление состояния с помощью AMP.setState()
- Изменение истории с помощью AMP.pushState()
- Выражения
- Отличия от JavaScript
- Примеры
- Функции в белом списке
- Определение макросов с помощью amp-bind-macro
- Привязки
- Атрибуты для конкретных элементов
- Отладка
- Предупреждения
- Ошибки
- Состояние отладки
- Приложение
- Спецификация <amp-state>
- Пакетная обработка запросов XHR
- Атрибуты
- Глубокое слияние с применением AMP.setState()
- Удаление переменной
- Грамматика выражения
Important: this documentation is not applicable to your currently selected format stories!
amp-bind
Description
позволяет менять элементы в зависимости от действий пользователя или поступающих данных, поддерживает привязку данных и простые выражения, похожие на JavaScript
Required Scripts
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
Привязка данных и поддержка выражений позволяют добавить интерактивности.
Скрипт | <script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script> |
Примеры | |
Руководства | Как создавать интерактивные AMP-страницы |
Обзор
Компонент amp-bind
позволяет добавлять на AMP-страницы настраиваемые интерактивные функции. Для этого используется привязка данных и простые выражения, похожие на JavaScript.
Простой пример
В примере ниже текст элемента <p>
меняется с Hello World на 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
есть три основных компонента:
- Состояние: изменяемое состояние JSON для всего документа. В примере выше состояние пусто, пока не будет нажата кнопка. После нажатия оно меняется на
{foo: 'amp-bind'}
. - Выражения: похожие на JavaScript выражения, которые могут ссылаться на состояние. В примере выше использовано одно выражение:
'Hello ' + foo
. Оно объединяет постоянную строку'Hello '
и переменную состоянияfoo
. В выражении можно использовать не более 100 операндов. - Привязки: это специальные атрибуты вида
[property]
, которые связывают свойство элемента с выражением. В примере выше есть одна привязка,[text]
, которая обновляет текст элемента<p>
каждый раз, когда меняется значение выражения.
При использовании amp-bind
особое внимание уделяется скорости, безопасности и эффективности AMP-страниц.
Чуть более сложный пример
<!-- Сложные вложенные данные JSON размещены в <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 + '.'">This is a dog.</p>
<!-- Классы CSS также можно добавлять и удалять с помощью [class]. -->
<p class="greenBackground" [class]="myAnimals[currentAnimal].style">
Для каждого животного задан свой цвет фона.
</p>
<!-- Вы также можете изменить источник изображения с помощью привязки [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>
При нажатии кнопки происходит следующее:
- Состояние обновляется, для
currentAnimal
указывается значение'cat'
. -
Выражения, которые зависят от значения
currentAnimal
, оцениваются:'Это ' + currentAnimal + '.'
=>'Это кошка.'
myAnimals[currentAnimal].style
=>'redBackground'
myAnimals[currentAnimal].imageUrl
=>/img/cat.jpg
-
Привязки, которые зависят от измененных выражений, обновляются:
- Текст первого элемента
<p>
выглядит как "Это кошка.". - Во втором элементе
<p>
для атрибутаclass
задается значение "redBackground". - Элемент
amp-img
выводит изображение кошки.
- Текст первого элемента
Описание
Состояние
У каждого AMP-документа, в котором используется amp-bind
, есть общее изменяемое состояние JSON.
Инициализация состояния с помощью amp-state
Состояние amp-bind
может быть инициализировано с помощью компонента amp-state
:
<amp-state id="myState">
<script type="application/json">
{
"foo": "bar"
}
</script>
</amp-state>
Выражения могут ссылаться на переменные состояния через точечный синтаксис. В этом примере myState.foo
оценивается как "bar"
.
- Максимальный размер дочернего скрипта JSON для элемента
<amp-state>
составляет 100 КБ. - Элемент
<amp-state>
также может указывать URL CORS вместо дочернего скрипта JSON. Более подробные сведения см. в Приложении.
Обновление состояния
Этот компонент поддерживает действие refresh
для обновления контента в состоянии.
<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>
Обновление состояния с помощью AMP.setState()
Действие AMP.setState()
объединяет объектный литерал с состоянием. Например, при нажатии кнопки ниже AMP.setState()
выполняется глубокое слияние объектного литерала и состояния.
<!-- 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>
Как правило, вложенные объекты объединяются до максимальной глубины 10. Все переменные, в том числе добавленные amp-state
, могут быть переопределены.
Если действие AMP.setState()
вызывается определенными событиями, то оно также может получить доступ к данным, связанным с событием, в свойстве 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})">
Изменение истории с помощью AMP.pushState()
Действие AMP.pushState()
аналогично AMP.setState()
, но оно также передает новую запись в стек истории браузера. При извлечении этой записи (например, при переходе назад) восстанавливаются предыдущие значения переменных, установленные AMP.pushState()
.
Пример:
<button on="tap:AMP.pushState({foo: '123'})">Set 'foo' to 123</button>
- При нажатии кнопки для переменной
foo
задается значение 123, а также создается новая запись в истории. - При переходе назад восстанавливается прежнее значение переменной
foo
, "bar" (аналогично вызовуAMP.setState({foo: 'bar'})
.
Выражения
Выражения похожи на JavaScript, однако есть ряд важных отличий.
Отличия от JavaScript
- Выражения могут получать только состояние всего документа.
- У выражений нет доступа к глобальным переменным, таким как
window
иdocument
. - Можно использовать только функции и операторы из белого списка.
- Запрещены пользовательские функции, классы и циклы. Стрелочные функции разрешены как параметры, например
Array.prototype.map
. - Неопределенные переменные и индекс, который выходит за границы массива, возвращают значение
null
вместоundefined
или ошибок. - Для повышения эффективности в настоящее время каждое выражение поддерживает не более 50 операндов. Если вам требуется больше, свяжитесь с нами.
Грамматика и реализация полного выражения представлены в bind-expr-impl.jison и bind-expression.js.
Примеры
Ниже приведены все допустимые выражения:
1 + '1' // 11
1 + (+'1') // 2
!0 // true
null || 'default' // 'default'
Функции в белом списке
Тип объекта | Функции | Пример |
---|---|---|
Array 1 | concat filter includes indexOf join lastIndexOf map reduce slice some sort (не по месту)splice (не по месту) | // 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') |
1В стрелочных функциях с одним параметром не должно быть скобок. Используйте x => x + 1
вместо (x) => x + 1
. Функции sort()
и splice()
не работают по месту расположения, а возвращают измененные копии.
2У статических функций нет пространства имен. Используйте abs(-1)
вместо Math.abs(-1)
.
Определение макросов с помощью amp-bind-macro
Фрагменты выражения amp-bind
можно использовать повторно. Для этого потребуется определить amp-bind-macro
. Элемент amp-bind-macro
позволяет определить выражение, которое принимает 0 или более аргументов и ссылается на текущее состояние. Макрос можно вызвать как функцию, если сослаться на значение атрибута id
из любой части документа.
<amp-bind-macro id="circleArea" arguments="radius" expression="3.14 * radius * radius"></amp-bind-macro>
<div>
Площадь круга равна <span [text]="circleArea(myCircle.radius)">0</span>.
</div>
Макрос также может вызывать другие макросы, определенные перед ним. Рекурсивный вызов одного и того же макроса не допускается.
Привязки
Привязка – это специальный атрибут вида [property]
, который связывает свойство элемента с выражением. Можно также использовать альтернативный синтаксис, совместимый с XML, в виде data-amp-bind-property
.
При изменении состояния выражения повторно оцениваются, а свойства связанных элементов обновляются с учетом результатов нового выражения.
Элемент amp-bind
поддерживает привязку данных к четырем типам состояния.
Тип | Атрибуты | Описание |
---|---|---|
Node.textContent | [text] | Поддерживается большинством текстовых элементов. |
Классы CSS | [class] | Результатом выражения должна быть строка, разделенная пробелами. |
Атрибут hidden | [hidden] | Это должно быть логическое выражение. |
Размер элементов AMP | [width] [height] | Меняет ширину и/или высоту AMP-элемента. |
Атрибуты для конкретных элементов | Разные атрибуты |
Примечания о привязках:
- Привязка к
innerHTML
запрещена в целях безопасности. - Все привязки атрибутов очищаются от небезопасных значений (например,
javascript:
). - Результаты логического выражения меняют логические атрибуты. Пример:
<amp-video [controls]="expr"...>
. Еслиexpr
имеет значениеtrue
, в элементе<amp-video>
есть атрибутcontrols
. Еслиexpr
имеет значениеfalse
, атрибутcontrols
удаляется. - Квадратные скобки
[
и]
в названиях атрибутов могут вызывать проблемы при записи XML (XHTML, JSX) или при записи атрибутов с помощью DOM API. В таких случаях используйте альтернативный синтаксис:data-amp-bind-x="foo"
вместо[x]="foo"
.
Атрибуты для конкретных элементов
Ниже перечислены все компоненты и атрибуты, к которым разрешена привязка.
Компонент | Атрибуты | Действия |
---|---|---|
<amp-brightcove> | [data-account] [data-embed] [data-player] [data-player-id] [data-playlist-id] [data-video-id] | Меняет отображаемое видео Brightcove. |
<amp-carousel type=slides> | [slide] * | Меняет текущий отображаемый индекс слайдов. См. пример. |
<amp-date-picker> | [min] [max] | Устанавливает самую раннюю дату для выбора. Устанавливает самую позднюю дату для выбора. |
<amp-google-document-embed> | [src] [title] | Отображает документ по обновленному URL. Меняет заголовок документа. |
<amp-iframe> | [src] | Меняет исходный URL окна iframe. |
<amp-img> | [alt] [attribution] [src] [srcset] | При связывании с [src] убедитесь, что выполняется также привязка к [srcset] . Это необходимо для поддержки кеша.См. соответствующие атрибуты amp-img. |
<amp-lightbox> | [open] * | Переключает отображение окна просмотра. Совет: используйте on="lightboxClose: AMP.setState(...)" для обновления переменных, когда окно просмотра закрыто. |
<amp-list> | [src] | Для строковых выражений извлекает и отображает JSON из URL строки. Для объектов и массивов отображает данные выражения. |
<amp-selector> | [selected] *[disabled] | Изменяет выбранные в данный момент дочерние элементы, определяя их по значению атрибута option . Поддерживает список значений, разделенный запятыми, для множественного выбора. См. пример. |
<amp-state> | [src] | Извлекает JSON из нового URL и объединяет его с существующим состоянием. Учтите, что в следующем обновлении элементы <amp-state> будут игнорироваться для предотвращения циклов. |
<amp-video> | [alt] [attribution] [controls] [loop] [poster] [preload] [src] | См. соответствующие атрибуты amp-video. |
<amp-youtube> | [data-videoid] | Меняет отображаемое видео YouTube. |
<a> | [href] | Меняет ссылку. |
<button> | [disabled] [type] [value] | См. соответствующие атрибуты button. |
<details> | [open] | См. соответствующие атрибуты details. |
<fieldset> | [disabled] | Включает или отключает набор полей. |
<image> | [xlink:href] | См. соответствующие атрибуты image. |
<input> | [accept] [accessKey] [autocomplete] [checked] [disabled] [height] [inputmode] [max] [maxlength] [min] [minlength] [multiple] [pattern] [placeholder] [readonly] [required] [selectiondirection] [size] [spellcheck] [step] [type] [value] [width] | См. соответствующие атрибуты input. |
<option> | [disabled] [label] [selected] [value] | См. соответствующие атрибуты option. |
<optgroup> | [disabled] [label] | См. соответствующие атрибуты optgroup. |
<select> | [autofocus] [disabled] [multiple] [required] [size] | См. соответствующие атрибуты select. |
<source> | [src] [type] | См. соответствующие атрибуты source. |
<track> | [label] [src] [srclang] | См. соответствующие атрибуты track. |
<textarea> | [autocomplete] [autofocus] [cols] [disabled] [maxlength] [minlength] [placeholder] [readonly] [required] [rows] [selectiondirection] [selectionend] [selectionstart] [spellcheck] [wrap] | См. соответствующие атрибуты textarea. |
*Привязываемые атрибуты, у которых нет аналогов без привязок.
Отладка
Выполните тест в режиме разработчика (с фрагментом URL #development=1
). Вы увидите предупреждения и ошибки, а также сможете воспользоваться специальными функциями отладки.
Предупреждения
В режиме разработчика amp-bind
выдает предупреждение, если значение по умолчанию для связанного атрибута не соответствует начальному результату соответствующего выражения. Это помогает предотвратить непреднамеренные мутации, вызванные изменениями в других переменных состояния. Пример:
<!-- 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>
В режиме разработчика amp-bind
также выдает предупреждение при разыменовании неопределенных переменных или свойств. Это также помогает предотвратить непреднамеренные мутации из-за результатов выражения null
. Пример:
<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">Текст в теге.</p>
Ошибки
При работе с amp-bind
в среде выполнения возникает несколько типов ошибок.
Тип | Сообщение | Подсказка |
---|---|---|
Неверная привязка | Привязка к атрибуту [НазваниеАтрибута] в теге <P> не допускается. | Используйте только привязки из белого списка. |
Синтаксическая ошибка | Ошибка компиляции выражения: … | Убедитесь, что в выражении нет опечаток. |
Функции, не входящие в белый список | Функция оповещения не поддерживается. | Используйте только функции из белого списка. |
Недопустимый результат | Результат "javascript:alert(1)" недопустим для [href]. | Избегайте запрещенных URL-протоколов или выражений, которые не поддерживаются валидатором AMP. |
Нарушение CSP | Нельзя создать рабочий процесс для 'blob:...', поскольку это нарушает следующую директиву Политики безопасности контента:… | Добавьте default-src blob: в свою Политику безопасности контента. Чтобы обеспечить высокую эффективность, компонент amp-bind передает дорогостоящую работу специальному процессу Web Worker. |
Состояние отладки
Чтобы вывести текущее состояние на консоль, воспользуйтесь AMP.printState()
.
Приложение
Спецификация <amp-state>
Элемент amp-state
может содержать дочерний элемент <script>
ИЛИ атрибут src
с URL CORS для удаленной конечной точки JSON. Сочетать эти функции нельзя.
<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>
Пакетная обработка запросов XHR
AMP объединяет запросы XHR для конечных точек JSON. Поэтому ы можете использовать один запрос данных JSON как источник для нескольких покупателей (то есть нескольких элементов amp-state
) на AMP-странице. Например, если элемент amp-state
отправляет запрос XHR to an в конечную точку, в процессе отправки все последующие запросы XHR к этой же конечной точке не будут отправляться. Результаты придут в ответе на первый запрос.
Атрибуты
src | URL удаленной конечной точки, которая будет возвращать JSON для обновления состояния amp-state . Это должна быть служба CORS HTTP. Атрибут src поддерживает все стандартные замены переменных URL. Подробная информация приведена в этом руководстве. Конечная точка должна соответствовать требованиям, указанным в Спецификации CORS для запросов на AMP-страницах.
|
credentials (необязательно) | Определяет параметр credentials в соответствии с Fetch API.
include . Если это значение установлено, ответ будет соответствовать требованиям по безопасности CORS для AMP. |
Глубокое слияние с применением AMP.setState()
При вызове AMP.setState()
компонент amp-bind
выполняет глубокое слияние объектного литерала с текущим состоянием. Все переменные из литерала записываются непосредственно в состояние, кроме вложенных объектов, которые рекурсивно объединяются. Примитивы и массивы в состоянии всегда переопределяются переменными с теми же именами из объектного литерала.
Пример:
{
<!-- 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>
При нажатии первой кнопки состояние меняется:
{
employee: {
name: 'John Smith',
age: 47,
vehicle: 'Car',
}
}
При нажатии второй кнопки amp-bind
выполняет рекурсивное слияние аргумента объектного литерала ({employee: {age: 64}}
) с текущим состоянием.
{
employee: {
name: 'John Smith',
age: 64,
vehicle: 'Car',
}
}
Значение employee.age
удалось обновить, но employee.name
и employee.vehicle
не изменились.
Учтите, что amp-bind
выдаст ошибку, если вы обратитесь к AMP.setState()
с объектным литералом, в котором есть циклические ссылки.
Удаление переменной
Чтобы удалить существующую переменную состояния, задайте для нее значение null
в AMP.setState()
. Рассмотрим состояние из предыдущего примера. При нажатии кнопки:
<button on="tap:AMP.setState({employee: {vehicle: null}})"...></button>
Состояние меняется на следующее:
{
employee: {
name: 'John Smith',
age: 48,
}
}
Аналогично при использовании такого кода:
<button on="tap:AMP.setState({employee: null})"...></button>
Состояние меняется на следующее:
{
<!-- State is empty -->
}
Грамматика выражения
Грамматика выражений amp-bind
похожа на BNF:
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
Вы читали этот документ десятки раз, но так и не нашли ответов на все свои вопросы? Возможно, другие люди столкнулись с такой же проблемой — обратитесь к ним на Stack Overflow.
Перейти на Stack Overflow Нашли ошибку или недостающую функцию?Проект AMP активно поощряет ваше участие и сотрудничество! Мы надеемся, что вы станете постоянным участником нашего открытого сообщества, но разовые вклады в работу над задачами, которые вам особенно интересны, также приветствуются.
Перейти на GitHub