AMP
  • 網站

收藏按鈕

簡介

此範例示範如何在 AMP 中實作收藏/讚/書籤按鈕。我們的實作方式

  • 會根據使用者是否已按讚項目來顯示正確的圖示。無論 AMP 是從 AMP Cache 或原始來源提供,此功能皆可運作。
  • 在非同步載入目前狀態時顯示預留位置。
  • 若請求失敗 (例如,當使用者離線時),則會回復為原始狀態並顯示錯誤訊息。

設定

我們使用 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 載入時顯示。

當使用者按下收藏按鈕時,會發生以下幾件事

  • 當使用者按下按鈕時,表單會傳送切換請求。
  • 我們實作了樂觀的使用者體驗,會在按下按鈕時立即更新按鈕狀態。
  • 如果表單提交失敗 (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 端點傳回兩個值:valuecount

<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 來儲存先前的值,以便在表單提交失敗時能夠回復按鈕狀態。

0
<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 上編輯範例