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>
元素的id
為theFood
,可讓我們參照已定義的資料。但由於<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 網址的 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,用於此 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 網址,而不是子項 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:將「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:索引 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.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]
運算式應為布林值運算式。
哈囉!
<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]
從新的網址擷取 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]
[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] 的有效結果。 | 避免使用禁止的網址協定或會導致 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