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]
。
未宣告狀態的範例
Hello World (哈囉,世界)
<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.dev.org.tw/static/samples/img/image2.jpg", "style": "greenBorder" }, "sushi": { "imageUrl": "https://amp.dev.org.tw/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.dev.org.tw/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
指向網址。
- 可變更的元素具有指向運算式的繫結。
<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.dev.org.tw/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>
元素或包含 CORS URL 的 src
屬性,以指向遠端 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>
由於 amp-state
元素會儲存 JSON 物件常值,因此您也可以使用物件 (如上所示) 或常數來初始化。
<amp-state id="singleton"> <script type="application/json"> 'I am a string' </script> </amp-state>
屬性
src
(選填)
遠端端點的網址,必須傳回 JSON,用於此 amp-state
。這必須是具有網頁適當 CORS 設定的 HTTP 服務。src
屬性允許所有標準網址變數替換。詳情請參閱替換指南。
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 (串連)
- filter (篩選)
- includes (包含)
- indexOf (indexOf)
- join (合併)
- lastIndexOf (lastIndexOf)
- map (map)
- reduce (reduce)
- slice (slice)
- some (some)
- sort (排序)
- splice (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>
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
- charCodeAt
- concat (串連)
- indexOf (indexOf)
- lastIndexOf (lastIndexOf)
- replace (取代)
- slice (slice)
- split (分割)
- substr
- toLowerCase (轉換為小寫)
- toUpperCase (轉換為大寫)
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 (絕對值)
- ceil (無條件進位)
- floor (無條件捨去)
- max (最大值)
- min (最小值)
- pow (次方)
- random (隨機)
- round (四捨五入)
- sign (正負號)
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.dev.org.tw/😉')"> encodeURI: Encode a URI and ignore protocol prefix </p> <p [text]="'encodeURIComponent: ' + encodeURIComponent('https://amp.dev.org.tw/😉')"> 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]
運算式應為布林值運算式。
Hello there! (哈囉!)
<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]
顯示更新網址的文件。[title]
變更文件的標題。
<amp-iframe>
[src]
變更 iframe 的來源網址。
<amp-img>
[alt]
[attribution]
[src]
[srcset]
繫結至 [srcset]
而非 [src]
,以支援回應式圖片。請參閱對應的 amp-img
屬性。
<amp-lightbox>
[open]
切換燈箱的顯示狀態。
on="lightboxClose: AMP.setState(...)"
,在燈箱關閉時更新變數。
<amp-list>
[src]
如果運算式是字串,則會從字串網址擷取並呈現 JSON。如果運算式是物件或陣列,則會呈現運算式資料。
<amp-selector>
[selected]
變更目前選取的子項元素 (由其option
屬性值識別)。支援以逗號分隔的值清單,用於多重選取。請參閱範例。[disabled]
[selected]
沒有非可繫結屬性。如果使用 selected
,AMP 驗證工具會擲回錯誤。
<amp-state>
[src]
從新網址擷取 JSON,並將其合併到現有狀態中。以下更新會忽略 <amp-state>
元素,以防止循環。
<amp-twitter>
[data-tweetid]
變更顯示的推文。
<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:
)進行清理。
偵錯
在開發模式中測試。在網址末尾加入片段 #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