amp-bind
描述
允许元素通过数据绑定和简单的类似 JS 的表达式响应用户操作或数据更改进行更改。
必需的脚本
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
用法
amp-bind
组件在 AMP 页面上启用自定义的有状态交互。
为了性能并避免意外的内容跳动风险,amp-bind
不会在页面加载时评估表达式。这意味着视觉元素应被赋予默认状态,而不是依赖 amp-bind
进行初始渲染。
amp-bind
有三个主要概念
- 状态:文档范围内的可变 JSON 状态。状态变量响应用户操作而更新。
amp-bind
不会在页面加载时评估表达式。视觉元素应具有其默认的“状态”定义,而不是依赖amp-bind
进行初始渲染。 - 表达式:可以引用状态的类似 JavaScript 的表达式。
- 绑定:特殊属性,通过表达式将元素的属性链接到状态。通过将属性包装在方括号内,以
[property]
的形式绑定属性。
未声明状态的示例
你好世界
<p [text]="'Hello ' + foo">Hello World</p> <button on="tap:AMP.setState({foo: 'Interactivity'})"> Say "Hello Interactivity" </button>
在上面的示例中
- 状态开始为空。
- 它在
<p>
元素上与[text]
(节点的文本内容)具有单个绑定。 [text]
值包含表达式'Hello ' + foo
。此表达式连接字符串“Hello ”和状态变量 foo 的值。
当用户点击/单击按钮时
- 它会触发
tap
事件。 tap
事件调用AMP.setState()
方法。AMP.setState()
方法将foo
状态变量设置为Interactivity
的值。- 状态不再为空,因此页面将绑定的属性更新为其状态。
AMP.setState()
可能会设置或更改页面上其他示例的状态。刷新此页面以查看 AMP.setState()
之前的示例。已声明状态的示例
<head> <style amp-custom> .greenBorder { border: 5px solid green; } .redBorder { border: 5px solid red; } .defaultBorder { border: 5px solid transparent; } </style> </head> <body> <amp-state id="theFood"> <script type="application/json"> { "cupcakes": { "imageUrl": "https://amp.org.cn/static/samples/img/image2.jpg", "style": "greenBorder" }, "sushi": { "imageUrl": "https://amp.org.cn/static/samples/img/image3.jpg", "style": "redBorder" } } </script> </amp-state> <div class="defaultBorder" [class]="theFood[currentMeal].style || 'defaultBorder'"> <p>Each food has a different border color.</p> <p [text]="'I want to eat ' + currentMeal + '.'">I want to eat cupcakes.</p> <amp-img width="300" height="200" src="https://amp.org.cn/static/samples/img/image2.jpg" [src]="theFood[currentMeal].imageUrl" > </amp-img> <button on="tap:AMP.setState({currentMeal: 'sushi'})">Set to sushi</button> <button on="tap:AMP.setState({currentMeal: 'cupcakes'})"> Set to cupcakes </button> </div> </body>
在上面的示例中
<amp-state>
组件使用 JSON 声明状态。<amp-state>
元素具有theFood
的id
,以便我们引用定义的数据。但是由于<amp-bind>
不会在页面加载时评估<amp-state>
,因此状态为空。- 页面加载时带有视觉默认值。
<div>
元素定义了class="greenBorder"
。- 第二个
<p>
元素在标签中定义了“I want cupcakes.”。 <amp-img>
的src
指向一个 URL。
- 可更改的元素具有指向表达式的绑定。
<div>
上的[class]
属性绑定到theFood[currentMeal].style
表达式。- 第二个
<p>
上的[text]
属性绑定到'I want to eat ' + currentMeal + '.'
表达式。 [src]
属性绑定到theFood[currentMeal].imageUrl
表达式。
如果用户单击“Set to sushi”按钮
tap
事件触发AMP.setState
操作。- setState 操作将
currentMeal
转换为状态并将其设置为sushi
。 - AMP 使用包含状态
currentMeal
的表达式评估绑定。 [class]="theFood[currentMeal].style"
将class
更新为redBorder
。[text]="'I want to eat ' + currentMeal + '.'"
将第二个<p>
元素的内部文本更新为“I want to eat sushi”。[src]="theFood[currentMeal].imageUrl
将<amp-img>
的src
更新为https://amp.org.cn/static/samples/img/image3.jpg
以 [class]="theFood[currentMeal].style"
为例,说明表达式语法评估
[class]
是要更新的属性。theFood
是<amp-state>
组件的 ID。currentMeal
是状态名称。在theFood
的情况下,它将是cupcakes
或sushi
。style
是状态变量。它对应于匹配的 JSON 键,并将绑定的属性设置为该键的值。
<amp-state>
规范
amp-state
元素可以包含子 <script>
元素或包含到远程 JSON 端点的 CORS URL 的 src
属性,但不能同时包含两者。
<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>
由于 amp-state
元素存储 JSON 对象字面量,因此您还可以像上面一样使用对象或常量对其进行初始化。
<amp-state id="singleton"> <script type="application/json"> 'I am a string' </script> </amp-state>
属性
src
(可选)
必须返回 JSON 的远程端点的 URL,该 URL 用于此 amp-state
。这必须是具有针对该页面的正确 CORS 配置的 HTTP 服务。src
属性允许所有标准 URL 变量替换。有关详细信息,请参阅 替换指南。
AMP 将 XMLHttpRequests (XHR) 批量处理到 JSON 端点,也就是说,您可以使用单个 JSON 数据请求作为 AMP 页面上多个使用者(例如,多个 amp-state
元素)的数据源。
例如,如果您的 amp-state
元素向端点发出 XHR,当 XHR 正在飞行时,对同一端点的所有后续 XHR 将不会触发,而是返回第一个 XHR 的结果。
credentials
(可选)
定义由 Fetch API 指定的 credentials
选项。
- 支持的值:
omit
、include
- 默认值:
omit
要发送凭据,请传递值 include
。如果设置了此值,则响应必须遵循 AMP CORS 安全指南。
操作
刷新
refresh
操作从 src
属性指向的数据点重新提取数据。此操作将发出网络请求,绕过浏览器的缓存机制。
<amp-state id="currentTime" src="/documentation/examples/api/time"></amp-state> <button on="tap:currentTime.refresh"> Refresh </button> <div [text]="currentTime.time"></div>
我们建议将 amp-script
用于大多数使用实时内容的情况。在少数情况下,amp-bind
的 refresh
将会起作用。
状态
每个使用 amp-bind
的 AMP 文档都具有文档范围内的可变 JSON 数据,或状态。
大小
<amp-state>
元素的 JSON 数据最大大小为 100KB。
使用 <amp-state>
定义和初始化状态
表达式不会在页面加载时进行评估,但您可以定义初始状态。<amp-state>
组件包含不同的状态及其状态变量。虽然这定义了状态,但在用户进行交互之后才会反映在页面上。
<amp-state id="myDefinedState"> <script type="application/json"> { "foo": "bar" } </script> </amp-state> <p [text]="myDefinedState.foo"></p> <button on="tap:AMP.setState({})">See value of initialized state</button>
使用表达式来引用状态变量。如果 JSON 数据未嵌套在 <amp-state>
组件中,则通过点语法引用状态。在上面的示例中,myState.foo
的求值结果为 "bar"。
<amp-state>
元素还可以指定 CORS URL 而不是子 JSON 脚本。有关详细信息,请参阅 <amp-state>
规范。
<amp-state id="myRemoteState" src="/static/samples/json/websites.json"> </amp-state>
使用 AMP.setState()
更新状态变量
AMP.setState()
操作将一个对象字面量合并到状态中。这意味着您可以更新已定义的状态变量的值。
<amp-state id="myUpdateState"> <script type="application/json"> { "foo": "bar", "baz": "hello" } </script> </amp-state> <p [text]="myUpdateState.foo"></p> <p [text]="myUpdateState.baz"></p> <button on="tap:AMP.setState({})">See value of set state</button> <!-- Like JavaScript, you can reference existing variables in the values of the object literal. --> <button on="tap:AMP.setState({myUpdateState:{baz: myUpdateState.foo}})"> Set value of baz to value of foo </button> <button on="tap:AMP.setState({myUpdateState:{baz: 'world'}})"> Set value of baz to "world" </button>
在上面的示例中,触发第一个按钮上的 AMP.setState({})
操作会计算 [text]
绑定表达式。然后,它将定义的状态变量的值插入到 <p>
标签中。
当单击第二个按钮时,定义了 AMP.setState({myState:{baz: myState.foo}})
操作,它会将 “baz” 状态变量值深度合并为与 “foo” 状态变量值相同。两个 <p>
标签都显示 "bar"。
状态变量值可以更新为初始状态中未定义的值。当单击第三个按钮时,定义了 "tap:AMP.setState({myState:{baz: 'world'}})"
操作,它会深度合并 "baz" 状态变量值,并将其覆盖为 "world"。
在其他两个按钮设置当前状态之后,单击第一个按钮不会发生任何更改。
页面刷新时,状态变量会恢复为 <amp-state>
中定义的 JSON。
事件触发和数据
当由某些事件触发时,AMP.setState()
可以访问 event
属性上的事件相关数据。
<!-- The "change" event of this <input> element contains a "value" variable that can be referenced via "event.value". --> <select on="change:AMP.setState({ option: event.value })"> <option value="0">No selection</option> <option value="1">Option 1</option> <option value="2">Option 2</option> </select> <div hidden [hidden]="option != 1"> Option 1 </div> <div hidden [hidden]="option != 2"> Option 2 </div>
更新嵌套变量
嵌套对象通常合并到最大深度 10。所有变量,包括在 <amp-state>
中定义的变量,都可以被覆盖。
<amp-state id="myState"> <script type="application/json"> { "foo": "bar", "first": { "a": "nested once", "ab": { "b": "nested twice", "bc": { "c": "nested three times", "cd": { "d": "nested four times", "de": { "e": "nested five times", "ef": { "f": "nested six times", "fg": { "g": "nested seven times", "gh": { "h": "nested nine times", "hi": { "i": "nested ten times" } } } } } } } } } } </script> </amp-state> <p [text]="myState.foo"></p> <p [text]="myState.first.ab.bc.cd.de.ef.fg.gh.hi.i"></p> <button on="tap:AMP.setState({})">See value of set state</button> <button on="tap:AMP.setState({ myState: {first: {ab: {bc: {cd: {de: {ef: {fg: {gh: {hi: {i:'this is as far as you should merge nested values'} } } } } } } } } } })" > Merge 10th nested object </button>
循环引用
如果 object
包含循环引用,AMP.setState(object)
将抛出错误。
删除变量
通过在 AMP.setState()
中将现有状态变量的值设置为 null
来删除它。
<button on="tap:AMP.setState({removeMe: null})"></button>
使用 AMP.setState()
进行深度合并
调用 AMP.setState()
会将提供的对象字面量与当前状态进行深度合并。amp-bind
会将所有字面量直接写入状态,但嵌套对象除外,嵌套对象会递归合并。状态中的基本类型和数组始终会被对象字面量中同名的变量覆盖。
姓名
年龄
车辆
<p [text]="employee.name">Name</p> <p [text]="employee.age">Age</p> <p [text]="employee.vehicle">Vehicle</p> <!-- Pressing this button changes state to: --> <button on="tap:AMP.setState({ employee: { name: 'John Smith', age: 47, vehicle: 'Car' } })" > Set employee to John Smith </button> <!-- Pressing this button recursively merges the object literal argument, --> <!-- `{employee: {age: 64}}`, into the existing state. --> <button on="tap:AMP.setState({ employee: { age: 64 } })" > Set employee age to 64 </button> <!-- The value updates from 47 to 64 at employee.age. --> <!-- No other values change. -->
使用 AMP.pushState()
修改历史记录
AMP.pushState()
将状态更改写入历史记录。返回导航将恢复以前的状态。要测试这一点,请在下面的示例中增加计数,然后使用浏览器的后退按钮来减少计数。
<amp-state id="count"> <script type="application/json"> 1 </script> </amp-state> <div>Item <span [text]="count">1</span></div> <button on="tap:AMP.pushState({ count: count + 1 })">Increase count</button>
使用 AMP.pushState()
将当前状态设置为最近推送的状态。
表达式
amp-bind
使用类似 JavaScript 的表达式,可以引用状态。
与 JavaScript 的区别
- 表达式只能访问包含文档的状态。
- 表达式不能访问
window
或document
。global
引用顶层状态。 - 只能使用
amp-bind
允许列表函数和运算符。允许使用箭头函数作为函数参数,例如[1, 2, 3].map(x => x + 1)
。- 禁止使用自定义函数、类和循环。
- 未定义的变量和超出数组索引范围的变量返回
null
而不是undefined
或抛出错误。 - 为了性能,单个表达式目前限制为 250 个操作数。如果这不足以满足您的使用场景,请联系我们。
以下都是有效的表达式
<p [text]="myExpressionsState.foo"></p> <!-- 1 + '1'; // 11 --> <button on="tap:AMP.setState({myExpressionsState: {foo: 1 + '1'}})"> foo: 1 + "1" </button> <!-- 1 + +'1'; // 2 --> <button on="tap:AMP.setState({myExpressionsState: {foo: 1 + + '1'}})"> foo: 1 + + "1" </button> <!-- !0; // true --> <button on="tap:AMP.setState({myExpressionsState: {foo: !0}})">foo: !0</button> <!-- null || 'default'; // 'default' --> <button on="tap:AMP.setState({myExpressionsState: {foo: null || 'default'}})"> null || "default" </button> <!-- [1, 2, 3].map(x => x + 1); // 2,3,4 --> <button on="tap:AMP.setState({myExpressionsState: {foo: [1, 2, 3].map(x => x + 1)}})" > [1, 2, 3].map(x => x + 1) </button>
在 bind-expr-impl.jison 和 bind-expression.js 中查找完整的表达式语法和实现。
允许使用的函数
数组
单参数箭头函数不能有括号,例如,使用 x => x + 1
而不是 (x) => x + 1
。sort()
和 splice()
返回修改后的副本,而不是就地操作。
concat: 1, 2, 3
filter: 少于三个字母的单词
includes: "hello" 或 "world"
indexOf: "world"
join: 所有单词用短划线连接
lastIndexOf: "amp-bind"
map: 将每个数字添加到前一个数字
reduce: 将数组中的所有数字相加
slice: 返回索引 1 和 3 处的单词
some: 一些数字小于 2
sort: 按字母顺序排列单词
splice: 将 "amp-bind" 放在索引 2 处
<amp-state id="myArrayState"> <script type="application/json"> { "foo": [1, 2, 3], "bar": ["hello", "world", "bar", "baz"], "baz": "Hello world, welcome to amp-bind" } </script> </amp-state> <p [text]="'concat: ' + myArrayState.foo.concat(4)">concat: 1, 2, 3</p> <p [text]="'filter: ' + myArrayState.bar.filter(word => word.length > 3)"> filter: words with less than three letter </p> <p [text]="'includes: ' + myArrayState.bar.includes('hello' || 'world')"> includes: "hello" or "world" </p> <p [text]="'indexOf: ' + myArrayState.bar.indexOf('world')">indexOf: "world"</p> <p [text]="'join: ' + myArrayState.bar.join('-')"> join: all words with a dash </p> <p [text]="'lastIndexOf: ' + myArrayState.baz.lastIndexOf('amp-bind')"> lastIndexOf: "amp-bind" </p> <p [text]="'map: ' + myArrayState.foo.map((x, i) => x + i)"> map: add each number to previous number </p> <p [text]="'reduce: ' + myArrayState.foo.reduce((x, i) => x + i)"> reduce: add all numbers in array together </p> <p [text]="'slice: ' + myArrayState.bar.slice(1,3)"> slice: return words at index 1 and 3 </p> <p [text]="'some: ' + myArrayState.foo.some(x => x < 2)"> some: some numbers are less than 2 </p> <p [text]="'sort: ' + myArrayState.bar.sort()"> sort: place words in alphabetical order </p> <p [text]="'splice: ' + myArrayState.bar.splice(2, 0, 'amp-bind')"> splice: place "amp-bind" at index 2 </p> <button on="tap:AMP.setState({})">Evaluate</button>
数字
toExponential: 100 的 5 次幂
toFixed: 1.99 四舍五入并固定到第一位小数
toPrecision: 1.234567 作为字符串返回到第三位数字
toString: 3.14 作为字符串返回
<p [text]="'toExponential: ' + (100).toExponential(5)"> toExponential: 100 to the exponent of 5 </p> <p [text]="'toFixed: ' + (1.99).toFixed(1)"> toFixed: 1.99 rounded and fixed to first decimal </p> <p [text]="'toPrecision: ' + (1.234567).toPrecision(3)"> toPrecision: 1.234567 returned as a string to the third digit </p> <p [text]="'toString ' + (3.14).toString()"> toString: 3.14 returned as a string </p> <button on="tap:AMP.setState({})">Evaluate</button>
字符串
charAt: 索引 6 处的字符
charCodeAt: 索引 6 处字符的 UTF-16 代码单元
concat: 合并 foo 和 bar
lastIndexOf: "w" 的索引
replace: 将 "world" 替换为 "amp-bind"
slice: 提取前 5 个字符
split: 在空格处拆分单词并作为数组返回
toLowerCase: 将所有字母转换为小写
toUpperCase: 将所有字母转换为大写
<amp-state id="myStringState"> <script type="application/json"> { "foo": "Hello world", "bar": ", welcome to amp-bind" } </script> </amp-state> <p [text]="'charAt: ' + myStringState.foo.charAt(6)"> charAt: The character at index 6 </p> <p [text]="'charCodeAt: ' + myStringState.foo.charCodeAt(6)"> charCodeAt: The UTF-16 code unit of the character at index 6 </p> <p [text]="'concat: ' + myStringState.foo.concat(myState.bar)"> concat: Combine foo and bar </p> <p [text]="'lastIndexOf: ' + myStringState.foo.lastIndexOf('w')"> lastIndexOf: The index of "w" </p> <p [text]="'replace: ' + myStringState.foo.replace('world', 'amp-bind')"> replace: Replace "world" with "amp-bind" </p> <p [text]="'slice: ' + myStringState.foo.slice(5)"> slice: Extract the first 5 characters </p> <p [text]="'split: ' + myStringState.foo.split(' ')"> split: Split words at space and return as array </p> <p [text]="'toLowerCase: ' + myStringState.foo.toLowerCase()"> toLowerCase: Make all letters lower case </p> <p [text]="'toUpperCase: ' + myStringState.foo.toUpperCase()"> toUpperCase: Make all letters upper case </p> <button on="tap:AMP.setState({})">Evaluate</button>
数学
静态函数不是命名空间的,例如,使用 abs(-1)
而不是 Math.abs(-1)
abs: 5 - 9 的绝对值
abs: 将 1.01 向上舍入到下一个最大的整数
floor: 将 1.99 向下舍入到整数
max: 返回最大数字
min: 返回最小数字
pow: 返回 5 的 3 次方
random: 返回大于 0 且小于 1 的数字
round: 舍入 1.51
sign: 评估正数还是负数
<p [text]="'abs: ' + abs(5 - 9)">abs: absolute number of 5 - 9</p> <p [text]="'ceil: ' + ceil(1.01)"> abs: round 1.01 up to the next largest whole number </p> <p [text]="'floor: ' + floor(1.99)">floor: round 1.99 down to a whole number</p> <p [text]="'max: ' + max(100, 4, 98)">max: return largest number</p> <p [text]="'min: ' + min(100, 4, 98)">min: return smalled number</p> <p [text]="'pow: ' + pow(5, 3)">pow: return 5 to the power of 3</p> <p [text]="'random: ' + random()"> random: return a number greater than 0 and less than 1 </p> <p [text]="'round: ' + round(1.51)">round: round 1.51</p> <p [text]="'sign: ' + sign(-9)">sign: evaluate if positive or negative</p> <button on="tap:AMP.setState({})">Evaluate</button>
对象
静态函数不是命名空间的,例如,使用 keys(Object)
而不是 Object.abs(Object)
keys: myObjectState JSON 对象键
values: myObjectState JSON 对象值
<amp-state id="myObjectState"> <script type="application/json"> { "hello": "world", "foo": "bar" } </script> </amp-state> <p [text]="'keys: ' + keys(myObjectState)"> keys: myObjectState JSON object keys </p> <p [text]="'values: ' + values(myObjectState)"> values: myObjectState JSON object values </p> <button on="tap:AMP.setState({})">Evaluate</button>
全局
encodeURI: 编码 URI 并忽略协议前缀
encodeURIComponent: 编码 URI
<p [text]="'encodeURI: ' + encodeURI('https://amp.org.cn/😉')"> encodeURI: Encode a URI and ignore protocol prefix </p> <p [text]="'encodeURIComponent: ' + encodeURIComponent('https://amp.org.cn/😉')"> encodeURIComponent: Encode a URI </p> <button on="tap:AMP.setState({})">Evaluate</button>
使用 amp-bind-macro
定义宏
通过定义 amp-bind-macro
来重用 amp-bind
表达式片段。amp-bind-macro
元素允许一个表达式,该表达式接受零个或多个参数并引用当前状态。像调用函数一样调用 amp-bind-macros
,引用文档中任何位置的 id
属性值。
输入半径值
圆的面积为 0。
<amp-bind-macro id="circleArea" arguments="radius" expression="3.14 * radius * radius" ></amp-bind-macro> <p> Input a radius value </p> <input type="number" min="0" max="100" value="0" on="input-throttled:AMP.setState({myCircle:{radius: event.value}})" /> <p> The circle has an area of <span [text]="circleArea(myCircle.radius)">0</span>. </p>
宏还可以调用在其自身之前定义的其他宏。宏不能递归地调用自身。
绑定
绑定是 [property]
形式的特殊属性,它将元素的属性链接到表达式。如果在 XML 中进行开发,请使用替代的与 XML 兼容的语法。
当状态更改时,将计算与该状态绑定的表达式。绑定到状态的元素属性会使用新的表达式结果更新。
布尔表达式结果会切换布尔属性。例如:<amp-video [controls]="expr"...>
。当 expr
的求值结果为 true
时,<amp-video>
元素具有 controls
属性。当 expr
的求值结果为 false
时,将删除 controls
属性。
此浏览器不支持 video 元素。
<amp-video [controls]="controls" width="640" height="360" layout="responsive" poster="/static/inline-examples/images/kitten-playing.png" > <source src="/static/inline-examples/videos/kitten-playing.webm" type="video/webm" /> <source src="/static/inline-examples/videos/kitten-playing.mp4" type="video/mp4" /> <div fallback> <p>This browser does not support the video element.</p> </div> </amp-video> <button on="tap:AMP.setState({ controls: true })"> Controls </button> <button on="tap:AMP.setState({ controls: false })"> No Controls </button>
React 和 XML 兼容性
如果使用 React 或 XML 进行开发,请使用替代的 data-amp-bind-property
语法。属性名称中的 [
和 ]
字符是无效的 XML,因此无法使用 [property]
语法。
将 property
字段替换为您要在 data-amp-bind-property
中定义的属性的名称。
例如,[text]="myState.foo"
将变为 data-amp-bind-text="myState.foo"
。
绑定类型
amp-bind
支持对五种类型的元素状态进行数据绑定。
使用 [text]
属性绑定 Node.textContent
。大多数文本元素都支持 [text]
属性。
<p [text]="'Hello ' + myState.foo">Hello World</p> <p></p>
CSS 类
使用 [class]
属性绑定元素的 class
。[class]
表达式必须生成以空格分隔的字符串。这意味着,如果您要绑定多个类,请在名称之间使用空格。逗号或破折号将被评估为类名。
<head> <style amp-custom> .background-green { background: green; } .background-red { background: red; } .border-red { border-color: red; border-width: 5px; border-style: solid; } </style> </head> <body> <div class="background-red" [class]="myClass">Hello World</div> <!-- This button adds both classes --> <button on="tap:AMP.setState({ myClass: 'background-green border-red' })"> Working: Change Class </button> <!-- String arrays also work --> <button on="tap:AMP.setState({ myClass: ['background-green', 'border-red'] })" > Working string array: Change Class </button> <!-- This expression evaluates to class="background-green,border-red" --> <button on="tap:AMP.setState({ myClass: 'background-green,border-red' })"> Broken: Change Class </button> </body>
使用 [hidden]
属性隐藏和显示元素。[hidden]
表达式应为布尔表达式。
你好!
<p [hidden]="hiddenState">Hello there!</p> <button on="tap:AMP.setState({hiddenState: true})">Hide</button> <button on="tap:AMP.setState({hiddenState: false})">Show</button>
AMP 组件的大小
使用 [width]
和 [height]
属性更改 width
和 height
。
<amp-img src="https://unsplash.it/400/200" width="200" [width]="myImageDimension.width" height="100" [height]="myImageDimension.height" > </amp-img> <button on="tap:AMP.setState({ myImageDimension: { width: 400, height: 200 } })" > Change size </button>
可访问性状态和属性
用于动态更新辅助技术(如屏幕阅读器)可用的信息。所有 [aria-*]
属性都是可绑定的。
AMP 组件特定的和 HTML 属性
一些 AMP 组件和 HTML 元素具有特定的可绑定属性。它们在下面列出。
AMP 组件特定属性
<amp-carousel type=slides>
[slide]
更改当前显示的幻灯片索引。
查看示例.
<amp-img>
[alt]
[attribution]
[src]
[srcset]
绑定到 [srcset]
而不是 [src]
以支持响应式图像。请参阅相应的 amp-img
属性。
<amp-lightbox>
[open]
切换灯箱的显示。
on="lightboxClose: AMP.setState(...)"
在灯箱关闭时更新变量。
<amp-state>
[src]
从新 URL 获取 JSON 并将其合并到现有状态。以下更新将忽略 <amp-state>
元素,以防止循环。
<amp-video>
[alt]
[attribution]
[controls]
[loop]
[poster]
[preload]
[src]
请参阅相应的 amp-video
属性。
<amp-youtube>
[data-videoid]
更改显示的 YouTube 视频。
HTML 属性
<a>
[href]
更改链接。
<button>
[disabled]
[type]
[value]
<details>
[open]
请参阅相应的 details 属性。
<fieldset>
[disabled]
启用或禁用 fieldset。
<image>
[xlink:href]
请参阅相应的 image 属性。
<input>
[accept]
[accessKey]
[autocomplete]
[已选中]
[disabled]
[高度]
[输入模式]
[最大值]
[最大长度]
[多选]
[模式]
[占位符]
[只读]
[必填]
[选择方向]
[尺寸]
[拼写检查]
[步长]
[type]
[value]
[宽度]
请参阅相应的 input 属性。
<option>
[disabled]
[标签]
[已选择]
[value]
请参阅相应的 option 属性。
<optgroup>
[disabled]
[标签]
请参阅相应的 optgroup 属性。
<section>
[data-expand]
更改amp-accordion
中section
的展开状态。
<select>
[自动聚焦]
[disabled]
[多选]
[必填]
[尺寸]
请参阅相应的 select 属性。
<source>
[src]
[type]
请参阅相应的 source 属性。
<track>
- [标签]
- [src]
- [源语言]
请参阅相应的 track 属性。
<textarea>
[autocomplete]
[自动聚焦]
[列数]
[disabled]
[默认文本]
[最大长度]
[最小长度]
[占位符]
[只读]
[必填]
[行数]
[选择方向]
[选择结束位置]
[选择起始位置]
[拼写检查]
[换行]
使用 [defaultText]
更新初始文本,使用 [text]
更新当前文本。请参阅相应的 textarea 属性。
不允许的绑定
出于安全原因,不允许绑定到 innerHTML
。
所有属性绑定都会对不安全的值(例如,javascript:
)进行清理。
调试
在开发模式下进行测试。通过在 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]="'abc'" class="def"></p>
在开发模式下,当取消引用未定义的变量或属性时,amp-bind
也会发出警告。这也有助于防止因 null
表达式结果而导致的意外突变。例如
<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>
错误
下面概述了使用 amp-bind
时可能出现的错误类型。
类型 | 消息 | 建议 |
---|---|---|
无效绑定 | 不允许在 <P> 上绑定到 [foo]. | 仅使用允许的绑定。 |
语法错误 | ... 中的表达式编译错误 | 验证表达式中是否存在拼写错误。 |
不允许的函数 | alert 不是支持的函数。 | 仅使用允许的函数。 |
清理后的结果 | "javascript:alert(1)" 不是 [href] 的有效结果。 | 避免使用被禁止的 URL 协议或会导致 AMP 验证器失败的表达式。 |
CSP 违规 | 拒绝从 'blob:...' 创建 worker,因为它违反了以下内容安全策略指令... | 将 default-src blob: 添加到您来源的内容安全策略。amp-bind 将耗时的任务委托给专用的 Web Worker,以确保良好的性能。 |
调试状态
使用 AMP.printState()
将当前状态打印到控制台。要使其工作,您需要启用开发模式。
表达式语法
amp-bind
表达式的类似 BNF 的语法
expr:
operation
| invocation
| member_access
| '(' expr ')'
| variable
| literal
;
operation:
'!' expr
| '-' expr %prec UMINUS
| '+' expr %prec UPLUS
| 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:
NAME args
| expr '.' NAME args
| expr '.' NAME '(' arrow_function ')'
| expr '.' NAME '(' arrow_function ',' expr ')'
;
arrow_function:
'(' ')' '=>' expr
| NAME '=>' expr
| '(' params ')' '=>' expr
;
params:
NAME ',' NAME
| params ',' NAME
;
args:
'(' ')'
| '(' array ')'
;
member_access:
expr member
;
member:
'.' NAME
| '[' expr ']'
;
variable:
NAME
;
literal:
primitive
| object_literal
| array_literal
;
primitive:
STRING
| NUMBER
| TRUE
| FALSE
| NULL
;
array_literal:
'[' ']'
| '[' array ']'
| '[' array ',' ']'
;
array:
expr
| array ',' expr
;
object_literal:
'{' '}'
| '{' object '}'
| '{' object ',' '}'
;
object:
key_value
| object ',' key_value
;
key_value:
key ':' expr
;
key:
NAME
| primitive
| '[' expr ']'
;
您已经阅读本文档十几次了,但它并没有真正涵盖您所有的问题?也许其他人也有同样的感觉:在 Stack Overflow 上联系他们。
前往 Stack Overflow 发现错误或缺少功能?AMP 项目强烈鼓励您的参与和贡献!我们希望您能成为我们开源社区的持续参与者,但我们也欢迎您为特别感兴趣的问题做出一次性贡献。
前往 GitHub