AMP

amp-bind

用法

amp-bind 元件可在 AMP 網頁上啟用自訂的狀態互動功能。

為了效能考量,並避免發生非預期的內容跳動風險,amp-bind 不會在網頁載入時評估運算式。這表示視覺元素應具備預設狀態,且不應依賴 amp-bind 進行初始呈現。

觀看這部影片,瞭解 amp-bind 簡介。

amp-bind 具有三個主要概念

  1. 狀態:文件範圍、可變的 JSON 狀態。狀態變數會回應使用者動作而更新。amp-bind 不會在網頁載入時評估運算式。視覺元素應已定義其預設「狀態」,且不應依賴 amp-bind 進行初始呈現。
  2. 運算式:類似 JavaScript 的運算式,可參照狀態
  3. 繫結:特殊屬性,可透過運算式將元素的屬性連結至狀態。屬性繫結的方式是以方括號括住,格式為 [property]

未宣告狀態的範例

Hello World (哈囉,世界)

<p [text]="'Hello ' + foo">Hello World</p>

<button on="tap:AMP.setState({foo: 'Interactivity'})">
  Say "Hello Interactivity"
</button>
在 Playground 中開啟這個程式碼片段

在以上範例中

  • 狀態一開始是空的。
  • 它在 <p> 元素上具有單一的 [text] (節點的文字內容) 繫結
  • [text] 值包含運算式 'Hello ' + foo。這個運算式會串連字串 'Hello ' 和狀態變數 foo 的值。

當使用者輕觸/點擊按鈕時

  1. 會觸發 tap 事件。
  2. tap 事件會叫用 AMP.setState() 方法。
  3. AMP.setState() 方法會將 foo 狀態變數設為 Interactivity 的值。
  4. 狀態不再是空的,因此網頁會將繫結的屬性更新為其狀態。

在某些範例中呼叫 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>
在 Playground 中開啟這個程式碼片段

在以上範例中

  • <amp-state> 元件會使用 JSON 宣告狀態。<amp-state> 元素具有 theFoodid,讓我們可以參照已定義的資料。但由於 <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」(設為壽司) 按鈕

  1. tap 事件會觸發 AMP.setState 動作。
  2. setState 動作會將 currentMeal 轉換為狀態,並將其設為 sushi
  3. AMP 會使用包含狀態 currentMeal運算式評估繫結
  4. [class]="theFood[currentMeal].style" 會將 class 更新為 redBorder
  5. [text]="'I want to eat ' + currentMeal + '.'" 會將第二個 <p> 元素的內部文字更新為「I want to eat sushi」(我想要吃壽司)。
  6. [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 來說,它會是 cupcakessushi
  • 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 的結果。

端點必須實作AMP 中的 CORS 要求規格中指定的規定。

credentials (選填)

定義 Fetch API 規定的 credentials 選項。

  • 支援的值:omitinclude
  • 預設值: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>
在 Playground 中開啟這個程式碼片段

針對處理即時內容的大部分使用案例,我們建議使用 amp-script。在部分情況下,amp-bindrefresh 會有效。

狀態

每個使用 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>
在 Playground 中開啟這個程式碼片段

使用運算式參照狀態變數。如果 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>
在 Playground 中開啟這個程式碼片段

在以上範例中,觸發第一個按鈕上的 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>
在 Playground 中開啟這個程式碼片段

更新巢狀變數

巢狀物件通常會合併至最多 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>
在 Playground 中開啟這個程式碼片段

循環參照

如果 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. -->
在 Playground 中開啟這個程式碼片段

使用 AMP.pushState() 修改歷史記錄

AMP.pushState() 會將狀態變更寫入歷史記錄。返回瀏覽時,將還原先前的狀態。如要測試這個功能,請增加以下範例中的計數,並使用瀏覽器的返回按鈕來減少計數。

項目 1
<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>
在 Playground 中開啟這個程式碼片段

使用 AMP.pushState() 會將目前狀態設為最近推送的狀態。

運算式

amp-bind 使用類似 JavaScript 的運算式,可以參照狀態。

與 JavaScript 的差異

  • 運算式只能存取包含文件的狀態
  • 運算式無法存取 windowdocumentglobal 會參照最上層狀態。
  • 只有 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>
在 Playground 中開啟這個程式碼片段

如要尋找完整的運算式語法和實作方式,請參閱 bind-expr-impl.jisonbind-expression.js

允許清單中的函式

Array (陣列)

單一參數箭頭函式不能有括號,例如,請使用 x => x + 1,而不是 (x) => x + 1sort()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>
在 Playground 中開啟這個程式碼片段

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>
在 Playground 中開啟這個程式碼片段

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>
在 Playground 中開啟這個程式碼片段

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>
在 Playground 中開啟這個程式碼片段

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>
在 Playground 中開啟這個程式碼片段

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>
在 Playground 中開啟這個程式碼片段

使用 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>
在 Playground 中開啟這個程式碼片段

巨集也可以呼叫在自身之前定義的其他巨集。巨集無法以遞迴方式呼叫自身。

繫結

繫結[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>
在 Playground 中開啟這個程式碼片段

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 支援元素五種類型狀態的資料繫結。

Node.textContent

使用 [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>
在 Playground 中開啟這個程式碼片段

hidden 屬性

使用 [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>
在 Playground 中開啟這個程式碼片段

AMP 元件的大小

使用 [width][height] 屬性變更 widthheight

<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>
在 Playground 中開啟這個程式碼片段

無障礙狀態和屬性

用於動態更新輔助技術 (例如螢幕閱讀器) 可用的資訊。所有 [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-accordionsection 的展開狀態。

<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