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>
元素的id
为theFood
,以便我们引用定义的数据。但因为<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
表达式。
如果用户点击“设置为寿司”按钮
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 会批量处理对 JSON 端点的 XMLHttpRequests (XHR),也就是说,你可以使用单个 JSON 数据请求作为 AMP 页面上多个消费者(例如,多个 amp-state
元素)的数据源。
例如,如果你的 amp-state
元素向某个端点发出 XHR 请求,在 XHR 请求正在进行时,所有后续对同一端点的 XHR 请求都不会触发,而是会返回第一个 XHR 的结果。
credentials
(可选)
定义由 Fetch API 指定的 credentials
选项。
- 支持的值:
omit
、include
- 默认值:
omit
要发送凭据,请传递值 include
。如果设置了此值,则响应必须遵循 AMP CORS 安全指南。
操作
refresh
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 中查找完整的表达式语法和实现。
允许的函数
Array
单参数箭头函数不能有括号,例如,使用 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: 在索引 2 处放置 “amp-bind”
<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>
Number
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>
String
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>
Math
静态函数没有命名空间,例如,使用 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>
Object
静态函数没有命名空间,例如,使用 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>
Global
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]
表达式必须返回一个空格分隔的字符串。这意味着,如果要绑定多个 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-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]
显示更新的 URL 中的文档。[title]
更改文档的标题。
<amp-iframe>
[src]
更改 iframe 的源 URL。
<amp-img>
[alt]
[attribution]
[src]
[srcset]
绑定到 [srcset]
而不是 [src]
以支持响应式图像。请参阅相应的 amp-img
属性。
<amp-lightbox>
[open]
切换灯箱的显示。
on="lightboxClose: AMP.setState(...)"
在灯箱关闭时更新变量。
<amp-list>
[src]
如果表达式是字符串,则它会从字符串 URL 获取并呈现 JSON。如果表达式是对象或数组,则它会呈现表达式数据。
<amp-selector>
[selected]
更改当前选定的子元素,这些子元素由其option
属性值标识。支持以逗号分隔的值列表进行多项选择。请参阅示例。[disabled]
[selected]
没有不可绑定的属性。如果使用 selected
,AMP 验证器将抛出错误。
<amp-state>
[src]
从新的 URL 获取 JSON 并将其合并到现有状态中。以下更新将忽略 <amp-state>
元素以防止循环。
<amp-twitter>
[data-tweetid]
更改显示的 Tweet。
<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]
[checked]
[disabled]
[height]
[inputmode]
[max]
[maxlength]
[multiple]
[pattern]
[placeholder]
[readonly]
[required]
[selectiondirection]
[size]
[spellcheck]
[step]
[type]
[value]
[width]
请参阅相应的 input 属性。
<option>
[disabled]
[label]
[selected]
[value]
请参阅相应的 option 属性。
<optgroup>
[disabled]
[label]
请参阅相应的 optgroup 属性。
<section>
[data-expand]
更改amp-accordion
中section
的展开。
<select>
[autofocus]
[disabled]
[multiple]
[required]
[size]
请参阅相应的 select 属性。
<source>
[src]
[type]
请参阅相应的 source 属性。
<track>
- [label]
- [src]
- [srclang]
请参阅相应的 track 属性。
<textarea>
[autocomplete]
[autofocus]
[cols]
[disabled]
[defaultText]
[maxlength]
[minlength]
[placeholder]
[readonly]
[required]
[rows]
[selectiondirection]
[selectionend]
[selectionstart]
[spellcheck]
[wrap]
使用 [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