AMP

建構個人化的互動式體驗

重要事項:本文件不適用於您目前選取的格式 stories

本指南概述高度個人化的互動性選項,可整合至 AMP 網頁中。如同雪花和變數名稱,每個網站都是獨一無二的,而 AMP 的現成元件程式庫可能無法滿足您的所有需求。因此,AMP 提供了可調整的元件,可針對複雜的互動性需求提供個人化的解決方案。使用這些元件來建構選取介面、顯示小工具和處理自訂邏輯。

使用 amp-selector 進行選取狀態管理

許多常見的網路體驗都包括向使用者呈現選項並回應其選取。透過 amp-selector 元件,您可以建構選項選單、指定表單輸入行為及實作分頁。

amp-selector 提供兩個核心功能

  1. 根據使用者選取更新 UI。
  2. 管理單一或多重選取狀態。

透過允許單一或多重選取選項,定義元素在使用者進行選取時的行為方式。您可以根據使用者互動停用或醒目提示選取器選項,並且其會公開選取事件,以便與其他 AMP 元件互動。

<amp-selector layout="container"
  class="sample-selector"
  multiple>
  <amp-img src="/static/samples/img/landscape_sea_300x199.jpg"
    width="90"
    height="60"
    option="1"
    alt="Photo of a sea landscape"></amp-img>
  <amp-img src="/static/samples/img/landscape_desert_300x200.jpg"
    width="90"
    height="60"
    option="2"
    selected
    alt="Photo of a desert landscape"></amp-img>
  <amp-img src="/static/samples/img/landscape_ship_300x200.jpg"
    width="90"
    height="60"
    option="3"
    alt="Photo of a water landscape with ship"></amp-img>
  <amp-img src="/static/samples/img/landscape_village_300x200.jpg"
    width="90"
    height="60"
    option="4"
    disabled
    alt="Photo of a village landscape"></amp-img>
</amp-selector>
在 playground 中開啟此程式碼片段

以下範例示範如何結合 amp-selector 和 SVG 來建立互動式圖表。

<head>
  <style amp-custom>
    .bar[option][selected] {
      fill: red;
      outline: none;
    }
  </style>
</head>
<body>
  <amp-selector>
    <svg class="chart" width="420" height="150" aria-labelledby="title desc" role="img">
      <title id="title">A bar chart showing information</title>
      <desc id="desc">4 apples; 8 bananas; 15 kiwis; 16 oranges; 23 lemons</desc>
      <g class="bar" option>
        <rect width="40" height="19"></rect>
        <text x="45" y="9.5" dy=".35em">4 apples</text>
      </g>
      <g class="bar" option>
        <rect width="80" height="19" y="20"></rect>
        <text x="85" y="28" dy=".35em">8 bananas</text>
      </g>
      <g class="bar" option>
        <rect width="150" height="19" y="40"></rect>
        <text x="150" y="48" dy=".35em">15 kiwis</text>
      </g>
      <g class="bar" option selected>
        <rect width="160" height="19" y="60"></rect>
        <text x="161" y="68" dy=".35em">16 oranges</text>
      </g>
      <g class="bar" option>
        <rect width="230" height="19" y="80"></rect>
        <text x="235" y="88" dy=".35em">23 lemons</text>
      </g>
    </svg>
  </amp-selector>
</body>
在 playground 中開啟此程式碼片段

使用 amp-bind 進行簡單的互動和資料繫結

使用者期望現代網路能夠回應其互動並反映他們所做的變更。amp-bind 元件可啟用狀態設定、讀取、UI 變更,並可處理使用者輸入和簡單邏輯。

<amp-state id="foo">
  <script type="application/json">
    {
        "bar": "State is set."
    }
  </script>
</amp-state>
<p [text]="foo.bar">No state is set</p>
<button on="tap:AMP.setState({})">Set State</button>
在 playground 中開啟此程式碼片段

amp-bind 元件在網頁載入時不會執行評估,但與 amp-list 結合的情況除外。

如要進一步瞭解如何使用 amp-list 在網頁載入時評估狀態,請參閱AMP 中的用戶端轉譯

相反地,它會等到使用者觸發與 amp-bind 互動的動作。這支援 Core Web Vitals,因為不會執行可能會拖慢網頁載入速度的計算,並且不允許網頁版面配置偏移,進而提高首次使用者互動的速度。

amp-bind 使用自己的語法來建構互動性並繫結元素。它運用了三個主要概念:狀態、運算式和繫結。

繫結

繫結是特殊的屬性,可將元素的屬性連結到運算式,從而將所有內容整合在一起。繫結是一種特殊屬性,格式為 [property]。這會將元素的屬性連結到狀態。使用繫結來更新文字、變更圖片大小,或允許使用者指定外觀。

如要進一步瞭解繫結,請參閱此處,並查看 AMP 元件HTML 元素的可繫結屬性完整清單。

狀態

每個使用 amp-bind 的 AMP 網頁都有自己的範圍內、可變的 JSON 資料,大小限制為 100kb。此資料即為狀態。

<amp-state id="todos">
    <script type="application/json">
      [
        "Learn AMP"
      ]
    </script>
  </amp-state>

  <input id="todoInput" type="text" on="input-throttled:AMP.setState({
                           newTodo: event.value
                         })">
  <button on="tap:AMP.setState({
                todos: todos.concat(newTodo)
              })">
    Add Todo
  </button>
 <amp-list [src]="todos" src="amp-state:todos" height="20" items="." [is-layout-container]=true>
<template type="amp-mustache">
      <li>{{.}}</li>
    </template>  </amp-list>
在 playground 中開啟此程式碼片段

amp-bind 支援預先定義的狀態、使用者互動後的狀態初始化,以及狀態更新。您可以使用運算式、繫結、動作和事件,參照、新增或變更定義為鍵值組的任何變數。

有多種宣告和使用狀態的方式。如要進一步瞭解狀態,請參閱 amp-bind 文件

運算式

amp-bind 元件使用類似 JavaScript 的運算式,對來自使用者輸入和狀態變數的資料執行運算。

<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 中開啟此程式碼片段

這些運算式具有支援函式的允許清單,與傳統 JavaScript 相比,其差異和限制稍有不同。如要進一步瞭解運算式,請參閱此處。

運算式可能會很快變得難以維護。請務必保持簡單,並使用 amp-bind-macro 和 amp-action-macro 來封裝常見邏輯。

定義運算式巨集

您可以透過定義 amp-bind-macro 來重複使用 amp-bind 運算式片段。amp-bind-macro 元素允許採用零或多個引數並參照目前狀態的運算式。像函式一樣叫用 amp-bind-macro,從文件中的任何位置參照 id 屬性值。

<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 中開啟此程式碼片段

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

使用 amp-script 進行複雜的互動

某些體驗需要具有自訂邏輯的高度複雜解決方案。在這些情況下,請使用 amp-script 元件將功能嵌入您的 AMP 網頁中。您可以編寫原生 JavaScript,或匯入 Preact 等程式庫,所有這些都不會犧牲效能。使用它來操作 DOM 或匯入個人化小工具。

amp-script 對每個網頁上的自訂 JavaScript 有 150 KB 的限制,在 <amp-script> 的每個執行個體之間共用。它具有 API 的允許清單和一些需要注意的安全性功能

建構自訂小工具

我們相信網路應該是令人愉悅、身歷其境且獨一無二的。獨特的網站將需要專屬於其品牌的功能和樣式。透過 amp-script,您可以在網頁中的任何位置匯入自訂小工具。使用這些小工具來建立美觀的介面,這些介面可在以原生 JavaScript、Preact 或您需要的任何內容編寫的複雜邏輯上執行。查看此處的 Worker DOM Preact 示範

使用狀態管理複雜的互動

您可能需要執行複雜的計算,或從會變更 DOM 的基礎邏輯中擷取和處理資訊。您可以透過將整個網頁包裝在 amp-script 元素中來管理此邏輯,但這樣做會失去 AMP 的一些優點。為了保留這些優點,您可以將複雜的計算卸載到 amp-script,然後將其與 amp-bind 結合以更新和反映新狀態。

在 amp-script 中實作所有互動

在某些情況下,將整個網頁包裝在 <amp-script> 中是使用 AMP 建立高度互動式體驗的最佳方式。

雖然此解決方案可讓您完全掌控網頁,但確實會移除 AMP 提供的一些優點。例如建立新的 AMP 元件。amp-script 元件可以將任何 HTML 元素新增至網頁 DOM,但僅限於 amp-layoutamp-img 元件。

結合 amp-script 和 amp-bind

amp-script 元件可讓您實作複雜的網域邏輯,這會導致 amp-bind 運算式變得過於複雜。您可以將邏輯卸載到 amp-script,並使用 amp-bind 更新包含結果的網頁狀態,而不是將整個網頁包裝在 <amp-script> 標記中。有一個注意事項,使用者必須與觸發計算的元素互動。但是,一旦資訊經過處理,amp-script 就可以透過呼叫 AMP.setState 自行更新網頁的狀態。amp-bind 的強大功能將處理其餘部分以更新 DOM。

<head>
  <meta
    name="amp-script-src"
    content="sha384-qdYQLoj2SRKXBu33BwIoyRKorw0b0nQ8UPIoIMc9wL8KVLcKODSAK52yNGQNS_vN"
  />
  <style amp-custom>
    .clickedButton {
      border: 5px solid green;
    }
  </style>
</head>
<body>
  <amp-script width="200" height="100" script="hello-world" [class]="scriptStyle">
    <button>Hello amp-script!</button>
  </amp-script>
  <script id="hello-world" type="text/plain" target="amp-script">
    const btn = document.querySelector('button');
    btn.addEventListener('click', () => {
      document.body.textContent = 'Hello World!';
      AMP.setState({ scriptStyle: "clickedButton" })
    });
  </script>
</body>
在 playground 中開啟此程式碼片段