收藏按鈕
簡介
此範例示範如何在 AMP 中實作收藏/讚/書籤按鈕。我們的實作方式
- 會根據使用者是否已喜歡某項目來顯示正確的圖示。這在 AMP 從 AMP 快取或原始來源提供時皆可運作。
- 在非同步載入目前狀態時顯示預留位置。
- 若請求失敗(例如使用者離線時),則會回復至原始狀態並顯示錯誤訊息。
設定
我們使用 `amp-list` 元件來動態呈現收藏按鈕的初始狀態。
<script async custom-element="amp-list" src="https://cdn.ampproject.org/v0/amp-list-0.1.js"></script>
`amp-list` 需要 mustache 元件。
<script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.js"></script>
我們需要 `amp-form` 來提交收藏請求。
<script async custom-element="amp-form" src="https://cdn.ampproject.org/v0/amp-form-0.1.js"></script>
當我們提交表單時,`amp-bind` 讓我們能夠動態變更按鈕狀態。
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
管理狀態
我們使用 `amp-state` 從 JSON 端點初始化按鈕狀態。由於我們使用 Cookie 來識別使用者,因此需要新增 `credentials="include"` 屬性。
<amp-state id="favorite" credentials="include" src="https://amp.dev.org.tw/documentation/examples/interactivity-dynamic-content/favorite_button/favorite">
</amp-state>
簡易收藏按鈕
按鈕嵌入在 `amp-list` 內,這讓我們能夠根據使用者是否已喜歡某項目來動態呈現按鈕。在範本內,我們使用 mustache 的隱含迭代器 `.` 來存取我們的 `/favorite` 端點傳回的布林值:`{{#.}}heart-fill{{/.}}`。
我們也在 `amp-list` 內使用 `placeholder` 屬性宣告預留位置圖示,該圖示會在 `amp-list` 載入時顯示。
當使用者按下收藏按鈕時,會發生幾件事
- 當使用者按下按鈕時,表單會傳送切換請求。
- 我們實作了樂觀的 UX,會在按下按鈕時立即更新按鈕狀態。
- 如果表單提交失敗 (`submit-error: ...`),我們會將收藏狀態回復為原始版本,並顯示錯誤訊息 (`favorite-failed-message.show`)。
- 我們會隱藏任何現有的錯誤訊息 (`favorite-failed-message.hide`)。
<form class="favorite-button" method="post" action-xhr="https://amp.dev.org.tw/documentation/examples/interactivity-dynamic-content/favorite_button/favorite" target="_top" on="submit:AMP.setState({
favorite: !favorite
}),
favorite-failed-message.hide;
submit-error:AMP.setState({
favorite: !favorite
}),
favorite-failed-message.show">
<amp-list width="56" height="56" credentials="include" items="." single-item src="https://amp.dev.org.tw/documentation/examples/interactivity-dynamic-content/favorite_button/favorite" binding="always">
<template type="amp-mustache">
<input type="submit" class="{{#.}}heart-fill{{/.}}{{^.}}heart-border{{/.}}" [class]="favorite ? 'heart-fill' : 'heart-border'" value aria-label="Favorite Toggle">
</template>
<div placeholder>
<input type="submit" disabled class="heart-loading" value aria-label="favorite placeholder">
</div>
</amp-list>
</form>
表單提交失敗時顯示的簡易 snackbar。
<div id="favorite-failed-message" hidden>Error: Could not favorite.
<div on="tap:favorite-failed-message.hide" tabindex="0" role="button">CLOSE</div>
</div>
具計數器的收藏按鈕
這是前一個範例的更精緻版本,其中也包含收藏數。我們的 JSON 端點 會傳回兩個值:`value` 和 `count`。
<amp-state id="favoriteWithCount" credentials="include" src="https://amp.dev.org.tw/documentation/examples/interactivity-dynamic-content/favorite_button/favorite-with-count">
</amp-state>
實作方式與前一個範例類似,但也會在按一下按鈕時更新計數
AMP.setState({ ..., count: favoriteWithCount.count + (favoriteWithCount.value ? -1 : 1) })
我們使用暫時變數 `previousFavoriteWithCount` 來儲存先前的值,以便在表單提交失敗時能夠回復按鈕狀態。
<form class="favorite-button" method="post" action-xhr="https://amp.dev.org.tw/documentation/examples/interactivity-dynamic-content/favorite_button/favorite-with-count" target="_top" on="submit:AMP.setState({
previousFavoriteWithCount: favoriteWithCount,
favoriteWithCount: {
value: !favoriteWithCount.value,
count: favoriteWithCount.count + (favoriteWithCount.value ? -1 : 1),
}
}),
favorite-failed-message.hide;
submit-error:AMP.setState({
value: !favoriteWithCount.value,
favoriteWithCount: previousFavoriteWithCount.count
}),
favorite-failed-message.show">
<amp-list width="200" height="56" credentials="include" items="." single-item noloading src="https://amp.dev.org.tw/documentation/examples/interactivity-dynamic-content/favorite_button/favorite-with-count" binding="always">
<template type="amp-mustache">
<div class="favorite-container">
<input type="submit" class="{{#value}}heart-fill{{/value}}{{^value}}heart-border{{/value}}" [class]="favoriteWithCount.value ? 'heart-fill' : 'heart-border'" value aria-label="Favorite Toggle">
<div class="favorite-count" [text]="favoriteWithCount.count ? favoriteWithCount.count : ''">{{count}}</div>
</div>
</template>
<div placeholder>
<div class="favorite-container">
<input type="submit" disabled class="heart-loading" value aria-label="favorite placeholder">
<div class="favorite-count loading">0</div>
</div>
</div>
</amp-list>
</form>
如果此頁面上的說明未涵蓋您的所有問題,請隨時與其他 AMP 使用者聯繫,討論您的確切使用案例。
前往 Stack Overflow 未說明的特色功能?AMP 專案大力鼓勵您的參與和貢獻!我們希望您能成為我們開放原始碼社群的長期參與者,但我們也歡迎您針對您特別熱衷的問題做出一次性貢獻。
在 GitHub 上編輯範例-
由 @sebastianbenz 撰寫