Accelerated Mobile Pages (AMP) 是一項開放原始碼計劃,有助製作快速、精美且成效卓越的網站和廣告。
如果您剛開始使用 AMP,建議您瀏覽下列資源快速介紹:
動機
AMP 支援使用使用者介面元件 (例如圖片輪轉介面和燈箱) 來豐富動態內容。AMP 也支援透過 AMP 動作,讓元件在另一個元件中觸發動作。
但是:
- 要自訂 AMP 元件嗎?
- 例如,顯示自訂標籤,顯示目前輪轉介面中的投影片以及投影片總數。
- 要新增有狀態的行為嗎?
- 舉例來說,如果使用者選擇的產品數量超過目前供應情形,則停用「加入購物車」按鈕。
在過去,由於使用者介面元件缺少穩固的通訊管道,而且無法使用可變動的共用狀態,因此在 AMP 中實作這類功能並不容易。為瞭解決這些用途,我們在 AMP 中打造了強大的新元件。
<amp-bind>
<amp-bind>
是新的 AMP 元件,可透過資料繫結和 JS 式運算式提供自訂互動功能。本程式碼研究室將逐步引導您使用 <amp-bind>
建立內容豐富的自訂網頁。
建構目標
在這個程式碼研究室中,您將建立電子商務產品詳細資料頁面:
|
您將會瞭解的內容
- 如何使用
<amp-bind>
建立資料繫結和運算式,打造精彩的互動式 AMP 網頁!
軟硬體需求
- 您選擇的瀏覽器
- 您選擇的文字編輯器
- Node.js 和 NPM
- 範例程式碼
- HTML、CSS 和 JavaScript 基礎知識
下載程式碼
首先,取得 ZIP 檔案的下載程式碼:
或透過 git:
git clone https://github.com/googlecodelabs/advanced-interactivity-in-amp.git
安裝依附元件
視需要解壓縮封存檔案,並瀏覽至該目錄。執行 npm install
以安裝依附元件。
cd advanced-interactivity-in-amp-codelab npm install
執行開發伺服器
使用 node.js 啟動開發伺服器:
node app.js
在網路瀏覽器中瀏覽至 http://localhost:3000,即可查看 AMP 網頁執行成功!
AMP 公式更新
AMP 網頁是 HTML 網頁,其中有一些限制的穩定性。AMP 網頁含有一些特殊標記,可視為 Google 搜尋中的 AMP 網頁。
大腦 AMP 網頁看起來如下:
<!doctype html>
<html amp>
<head>
<meta charset="utf-8">
<link rel="canonical" href="hello-world.html">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
<script async src="https://cdn.ampproject.org/v0.js"></script>
</head>
<body>Hello World!</body>
</html>
AMP 元件
我們的範例程式碼 (static/index.html
) 以巴基斯坦的 AMP 網頁為基礎,呈現出網頁內容 (圖片、文字等) 以及一些 AMP 元件:
<script async custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js"></script>
<script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.1.js"></script>
<script async custom-element="amp-form" src="https://cdn.ampproject.org/v0/amp-form-0.1.js"></script>
<script async custom-element="amp-selector" src="https://cdn.ampproject.org/v0/amp-selector-0.1.js"></script>
AMP 元件提供更多功能和 UI 元件,為 AMP 網頁增添豐富的互動功能。範例程式碼使用以下 AMP 元件:
<amp-carousel>
- 顯示多項產品視圖的圖片圖片輪轉介面。
<amp-mustache>
- 用於轉譯 amp 表單伺服器回應的範本系統。
<amp-form>
- 為 AMP 網頁所需的
<form>
元素新增特殊功能。 <amp-selector>
- 提供語意化方法,可選取一組元素中的一或多個元素。可做為 amp 格式的輸入來源。
基本互動功能
範例程式碼提供了一些基本互動方式:
- 圖片輪轉介面 (
<amp-carousel>
) 會顯示多項產品檢視畫面。 - 如想將產品加入使用者的購物車 (透過
<amp-form>
),請輕觸頁面底部的 [新增至購物車] 按鈕。
請試著滑動圖片輪轉介面,然後輕觸 [加入購物車] 按鈕。
改善體驗
範例程式碼為使用者體驗提供極佳體驗。有幾種方法可以改善這個問題:
- 新增顯示目前投影片和投影片總數的指標。
- 當使用者選取其他襯衫顏色時,可以將圖片輪轉介面改為所選圖片的襯衫。
在導入 <amp-bind>
元件之前,您無法新增這類功能。讓我們來實際體驗 <amp-bind>
功能,並將這些新功能加入我們的程式碼範例中!
安裝<amp-bind>
擴充功能
<amp-bind>
是新的 AMP 元件,可透過資料繫結和 JS 式運算式提供自訂互動功能。如要使用 <amp-bind>
,您必須在網頁中安裝。
開啟 static/index.html
檔案,並將下列指令碼加到 AMP 元件清單中 (位於網頁的 <head>
部分):
<script async custom-element="amp-bind"
src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
新增投影片指標
<amp-bind>
的運作方式是將元素屬性繫結至自訂運算式。這些運算式可以參照「狀態」(JSON 資料可變動)。我們可以透過包含 <amp-bind>
的 <amp-state>
元件來初始化此狀態。
我們來初始化狀態變數,以追蹤圖片輪轉介面中目前顯示的投影片的索引。開啟 static/index.html
,然後將以下內容加到網頁的 <body>
頂端 (在標頭之前):
<amp-state id="selected">
<script type="application/json">
{
"slide": 0
}
</script>
</amp-state>
<amp-state>
元素的資料可透過相關聯的 ID 存取。舉例來說,我們可以使用下列運算式片段來參照這個變數:
selected.slide // Evaluates to 0.
然後,當使用者在輪轉介面上變更投影片時,只要新增「on-amp-carousel>」元素,即可更新這個變數。
<amp-carousel type="slides" layout="fixed-height" height=250 id="carousel"
on="slideChange:AMP.setState({selected: {slide: event.index}})">
現在,只要 <amp-carousel>
的投影片變更,系統將使用以下引數呼叫 AMP.setState
動作:
{
selected: {
slide: event.index
}
}
event.index
運算式會評估新的投影片索引,而 AMP.setState()
動作會將此物件常值合併為目前狀態。這會將目前的值 selected.slide
替換為 event.index
的值。
接著,我們來利用這個狀態變數來追蹤目前顯示的投影片,並建立投影片指標。找到投影片指標元素 (尋找 <!-- TODO: "Add a slide indicator" -->
) 並將下列繫結新增至子項:
<!-- TODO: "Add a slide indicator" -->
<p class="dots">
<!-- The <span> element corresponding to the current displayed slide
will have the 'current' CSS class. -->
<span [class]="selected.slide == 0 ? 'current' : ''" class="current"></span>
<span [class]="selected.slide == 1 ? 'current' : ''"></span>
<span [class]="selected.slide == 2 ? 'current' : ''"></span>
</p>
[class]
是會變更 class
屬性的繫結,可讓您利用這項屬性為任何元素新增或移除 CSS 類別。
現在,請重新整理頁面,然後試試看吧!只要變更輪轉介面上的投影片,就能:
- 觸發
slideChange
事件... - 哪些操作會呼叫
AMP.setState
... - 這會更新狀態變數
selected.slide
... - 這會更新指標
<span>
元素的[class]
繫結!
太好了!現在,我們加入了投影片投影片指標。
變更「<amp-carousel>
」中的圖片
我們可以在更改所選顏色時看到不同襯衫顏色的圖片。透過 amp-bind,我們可以對 <amp-carousel>
中的 <amp-img>
元素繫結 [src]
,以執行此動作。
不過,我們需要先使用各個 T 恤的圖片來源網址初始化狀態資料。讓我們使用新的 <amp-state>
元素來執行這個動作:
<!-- Available shirts. Maps unique string identifier to color and image URL string. -->
<amp-state id="shirts">
<script type="application/json">
{
"1001": {
"color": "black",
"image": "./shirts/black.jpg"
},
"1002": {
"color": "blue",
"image": "./shirts/blue.jpg"
},
"1010": {
"color": "brown",
"image": "./shirts/brown.jpg"
},
"1014": {
"color": "dark green",
"image": "./shirts/dark-green.jpg"
},
"1015": {
"color": "gray",
"image": "./shirts/gray.jpg"
},
"1016": {
"color": "light gray",
"image": "./shirts/light-gray.jpg"
},
"1021": {
"color": "navy",
"image": "./shirts/navy.jpg"
},
"1030": {
"color": "wine",
"image": "./shirts/wine.jpg"
}
}
</script>
</amp-state>
這個 <amp-state>
元素包含 JSON 物件,能夠將襯衫識別碼 (例如 SKU) 對應至對應的襯衫顏色和圖片網址。JSON 陣列也可在這裡運作,但使用物件能讓我們執行一些很快就會看到的操作。
現在,我們可以透過襯衫 ID 存取圖片網址。舉例來說,shirts['10014'].color
會評估為 "dark green"
,而 shirts['10030'].image
會傳回「wine」襯衫顏色的圖片網址。
如果我們加入了另一個可追蹤所選 SKU 的州變數,我們可以將運算式繫結至 <amp-img>
元素,以在所選 SKU 變更時更新其 src
屬性。在現有 amp-state#selected
元素的 JSON 中新增 sku
金鑰:
<amp-state id="selected">
<script type="application/json">
{
"slide": 0,
"sku": "1001"
}
</script>
</amp-state>
將「加入」動作加入 <amp-selector>
,以便在選取新顏色時更新 selected.sku
變數:
<amp-selector name="color"
on="select:AMP.setState({selected: {sku: event.targetOption}})">
然後,為 <amp-carousel>
中的 <amp-img>
元素新增繫結 (尋找 <!-- TODO: "Changing images in amp-carousel-->"
):
<!-- Update the `src` of each <amp-img> when the `selected.sku` variable changes. -->
<amp-img width=200 height=250 src="./shirts/black.jpg"
[src]="shirts[selected.sku].image"></amp-img>
<amp-img width=300 height=375 src="./shirts/black.jpg"
[src]="shirts[selected.sku].image"></amp-img>
<amp-img width=400 height=500 src="./shirts/black.jpg"
[src]="shirts[selected.sku].image"></amp-img>
注意:實際上,輪轉介面中的每個圖片都可能有不同的 src
。只要將單一圖片換成圖片陣列即可。為求簡單,這個程式碼研究室使用單一圖片,不同尺寸。
現在,請重新整理頁面,並為襯衫選取其他顏色。系統隨即更新輪轉介面,以顯示所選顏色的襯衫。
如果可繫結的資料過大,或是無法於載入網頁時擷取,該怎麼辦?或者,如果每個 SKU 的價格都需要較長時間,該怎麼辦?針對非檢視項目 SKU 查詢價格是浪費的做法。
正在擷取襯衫的可用尺寸
讓我們能擷取遠端資料,在程式碼研究室樣本中查詢 SKU 價格。位於 app.js
的 Express.js 開發伺服器已有端點 /shirts/sizes?shirt=<sku>
,這個端點會按襯衫 SKU 傳回每個尺寸的可用尺寸與價格。這個模型會以人工延遲時間 (一秒) 傳送回應,模擬網路延遲時間。
要求 | 回應 |
|
|
與 <amp-state>
元素中的 JSON 資料類似,從這些擷取作業傳回的遠端資料會合併到元素,並放在元素的 id
屬性底下。例如,可從運算式存取上述範例回應傳回的資料:
運算式 | 結果 |
|
|
現在,讓我們把此範例套用到我們的電子商務範例。首先,選取新 SKU 時,系統會擷取這個襯衫資料。將 [src]
繫結新增至我們的 amp-state#shirts
元素:
<!-- When `selected.sku` changes, update the `src` attribute and fetch
JSON at the new URL. Then, merge that data under `id` ("shirts"). -->
<amp-state id="shirts" [src]="'/shirts/sizesAndPrices?sku=' + selected.sku">
接著,就讓特定 SKU 清楚標示無法使用的大小。"unavailable"
CSS 類別透過元素新增對角線。我們可以對 amp-selector[name="size"]
中的對應大小沒有對應的對角線:
<amp-selector name="size">
<table>
<tr>
<!-- If 'XS' size is available for selected SKU, return empty string.
Otherwise, return 'unavailable'. -->
<td [class]="shirts[selected.sku].sizes['XS'] ? '' : 'unavailable'">
<div option="XS">XS</div>
</td>
<td [class]="shirts[selected.sku].sizes['S'] ? '' : 'unavailable'">
<div option="S">S</div>
</td>
<td [class]="shirts[selected.sku].sizes['M'] ? '' : 'unavailable'">
<div option="M">M</div>
</td>
<td [class]="shirts[selected.sku].sizes['L'] ? '' : 'unavailable'">
<div option="L">L</div>
</td>
<td [class]="shirts[selected.sku].sizes['XL'] ? '' : 'unavailable'">
<div option="XL">XL</div>
</td>
</tr>
</table>
</amp-selector>
現在重新載入頁面並再試一次。選取新的 SKU (襯衫顏色) 會導致無法完整檢視尺寸不足的延遲情形 (經過一小段時間後)。
不過,這其實是個小問題:那是黑色襯衫呢,預設顏色為何?我們必須將黑色襯衫尺寸和價格資料新增到「amp-state#shirts
」...
<amp-state id="shirts" [src]="'/shirts/sizesAndPrices?sku=' + selected.sku">
<script type="application/json">
{
"1001": {
"color": "black",
"image": "./shirts/black.jpg",
"sizes": {
"XS": 8.99,
"S": 9.99
}
},
<!-- ... -->
...以及更新相關元素的預設狀態。
<amp-selector name="size">
<table>
<tr>
<!-- If 'XS' size is available for selected SKU, return empty string.
Otherwise, return 'unavailable'. -->
<td [class]="shirts[selected.sku].sizes['XS'] ? '' : 'unavailable'">
<div option="XS">XS</div>
</td>
<td [class]="shirts[selected.sku].sizes['S'] ? '' : 'unavailable'">
<div option="S">S</div>
</td>
<!-- Add the ‘unavailable' class to the next three <td> elements
to be consistent with the available sizes of the default SKU. -->
<td class="unavailable"
[class]="shirts[selected.sku].sizes['M'] ? '' : 'unavailable'">
<div option="M">M</div>
</td>
<td class="unavailable"
[class]="shirts[selected.sku].sizes['L'] ? '' : 'unavailable'">
<div option="L">L</div>
</td>
<td class="unavailable"
[class]="shirts[selected.sku].sizes['XL'] ? '' : 'unavailable'">
<div option="XL">XL</div>
</td>
</tr>
</table>
</amp-selector>
可變動的襯衫價格
正確顯示可用尺寸後,請確認價格也正確無誤。
我們的 AMPPAREL 商店有特別的特點,就是 T 恤價格同時適用於顏色和尺寸。這表示我們需要一個新變數來追蹤使用者選取的大小。將新動作新增至大小 <amp-selector>
元素:
<!-- When an element is selected, set the `selectedSize` variable to the
value of the "option" attribute of the selected element. -->
<amp-selector name="size"
on="select:AMP.setState({selectedSize: event.targetOption})">
請注意,我們不會透過 amp-state#selected
元素初始化 selectedSize
的值。因為我們刻意沒有提供預設選取的尺寸,而想要強制使用者選擇大小。
新增新的 <span>
元素,納入價格標籤,並將預設文字變更為「---」符號 (因為沒有預設大小)。
<h6>PRICE :
<!-- Display the price of the selected shirt in the selected size if available.
Otherwise, display the placeholder text '---'. -->
<span [text]="shirts[selected.sku].sizes[selectedSize] || '---'">---</span>
</h6>
此外,我們也有正確的價格!試試看。
有條件啟用的按鈕
就快完成了!現在,當所選大小無法使用時,請停用「加入購物車」按鈕:
<!-- Disable the "ADD TO CART" button when:
1. There is no selected size, OR
2. The available sizes for the selected SKU haven't been fetched yet
-->
<input type="submit" value="ADD TO CART" disabled
class="mdl-button mdl-button--raised mdl-button--accent"
[disabled]="!selectedSize || !shirts[selected.sku].sizes[selectedSize]">
我們有互動式電子商務產品詳細資料頁面,其中包含每個 SKU 的變動大小和價格,可從遠端 JSON 端點擷取以隨選取得。
如果遇到問題,請參閱 static/final.html
以取得完整解決方案。
希望這個程式碼研究室可展現您運用 <amp-bind>
建立互動式 AMP 網頁的強大功能和彈性。如需更多資訊,請參閱 <amp-bind> 說明文件。
我們十分願意提供寶貴意見,請將您的功能要求、建議或錯誤報告傳送給我們。如果您想要對實際的使用者測試 <amp-bind>
,建議您提出來源試用。
我們非常期待能在 <amp-bind>
上推出這項工具,並看看大家可以使用哪些功能建構而成!