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()
之前的範例。已宣告狀態的範例
<style amp-custom> .greenBorder { border: 5px solid green; } .redBorder { border: 5px solid red; } </style> </head> <body> <amp-state id="theFood"> <script type="application/json"> { "cupcakes": { "style": "greenBorder", "text": "Just kidding, I want to eat cupcakes." }, "sushi": { "style": "redBorder", "text": "Actually, I want to eat sushi." } } </script> </amp-state> <div class="greenBorder" [class]="theFood[currentMeal].style"> <p>Each food has a different border color.</p> <p [text]="theFood[currentMeal].text">I want to eat cupcakes.</p> <button on="tap:AMP.setState({currentMeal: 'sushi'})">Set to sushi</button> <button on="tap:AMP.setState({currentMeal: 'cupcakes'})">Set to cupcakes</button> </div>
<amp-state>
元件會使用 JSON 物件宣告狀態。它具有theFood
的id
,讓我們可以參照已定義的資料。但由於<amp-bind>
不會在電子郵件載入時評估<amp-state>
,因此狀態是空的。- 頁面會載入視覺預設值。
<div>
元素已定義class="greenBorder"
。- 第二個
<p>
元素在標記內已定義「I want cupcakes.」。 <amp-img>
src
指向網址。- 可變更的元素具有指向運算式的繫結。
<div>
上的[class]
屬性已繫結至theFood[currentMeal].style
運算式。- 第二個
<p>
上的[text]
屬性已繫結至theFood[currentMeal].text
運算式。
如果使用者點擊「Set to sushi」(設為壽司) 按鈕
tap
事件會觸發AMP.setState
動作。- setState 動作會將
currentMeal
變成狀態,並將其設為sushi
。 - AMP 會評估具有包含狀態
currentMeal
的運算式的繫結。 [class]="theFood[currentMeal].style
會將class
更新為redBorder
。theFood[currentMeal].text
會將第二個<p>
元素的內部文字更新為「Actually, I want to eat sushi.」。
以 [class]="theFood[currentMeal].style"
作為運算式語法評估的範例
[class]
是要更新的屬性theFood
是<amp-state>
元件的 ID。currentMeal
是狀態名稱。在theFood
的情況下,它會是cupcakes
或sushi
。style
是狀態變數。它對應至相符的 JSON 金鑰,並將繫結屬性設為該金鑰的值。
<amp-state>
規格
amp-state
元素必須包含子 <script>
元素。
<amp-state id="myLocalState"> <script type="application/json"> { "foo": "bar" } </script> </amp-state>
狀態
每個使用 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-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.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-macro
,從文件中的任何位置參照 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
屬性會移除。
此瀏覽器不支援影片元素。
<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]
<amp-lightbox>
[open]
切換燈箱的顯示。
on="lightboxClose: AMP.setState(...)"
在燈箱關閉時更新變數。
<amp-selector>
[selected]
變更目前選取的子元素,這些子元素由其option
屬性值識別。支援以逗號分隔的值清單,以進行多重選取。查看範例。[disabled]
[selected]
沒有不可繫結的屬性。如果使用 selected
,AMP 驗證工具會擲回錯誤。
<button>
[disabled]
[value]
請參閱對應的 button 屬性。
<details>
[open]
請參閱對應的 details 屬性。
<fieldset>
[disabled]
啟用或停用 fieldset。
<image>
[xlink:href]
請參閱對應的 image 屬性。
<input>
[autocomplete]
[disabled]
[height]
[max]
[maxlength]
[multiple]
[pattern]
[placeholder]
[readonly]
[required]
[size]
[spellcheck]
[step]
[value]
[width]
請參閱對應的 input 屬性。
<option>
[disabled]
[label]
[selected]
[value]
請參閱對應的 option 屬性。
<optgroup>
[disabled]
[label]
請參閱對應的 optgroup 屬性。
<section>
[data-expand]
變更amp-accordion
中section
的展開狀態。
<select>
[disabled]
[multiple]
[required]
[size]
請參閱對應的 select 屬性。
<textarea>
[autocomplete]
[cols]
[disabled]
[defaultText]
[maxlength]
[minlength]
[placeholder]
[readonly]
[required]
[rows]
[spellcheck]
[wrap]
使用 [defaultText]
更新初始文字,並使用 [text]
更新目前文字。請參閱對應的 textarea 屬性。
不允許的繫結
基於安全性考量,不允許繫結至 innerHTML
。
所有屬性繫結都會針對不安全的值 (例如,javascript:
) 進行清理。
偵錯
在開發模式中測試,方法是將電子郵件儲存為 HTML 檔案。在瀏覽器中測試,方法是在網址結尾新增片段 #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