AMPテンプレートからはじめる AMPで実装するリスト表示

# はじめに
AMPコンポーネントを組み合わせて一般的なリスト表示を実現する。
今回は[Qiita API v2](https://qiita.com/api/v2/docs)を使って新着の記事一覧を取得し、ページネーションを実現する。

[Qiita API v2](https://qiita.com/api/v2/docs)

# 実装したいもの
* 今回は以下のスクリーンショット赤枠の部分を実現する事とする。(https://qiita.com/tags/amp?page=1)
* 完全に模倣することはせず、それっぽい感じに実装する。
* 記事のタイトルとユーザー名、タグ、ユーザーアイコンが表示されたリストを実現する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148185/68f42110-2257-91e3-47ab-2639d8790fd9.png)


# 使用するAMP component
## amp-bind
* データバインディング及びカスタムステートフルインタラクティブを実現。

[amp-bind](https://amp.dev/documentation/components/amp-bind?format=websites)

## amp-list
* JSONを動的に取得し、レンダリングを実現。

[amp-list](https://amp.dev/documentation/components/amp-list?format=websites)

## amp-mustache
* [mustache.js](https://github.com/janl/mustache.js/)を使用できるようにする。

[amp-mustache](https://amp.dev/documentation/components/amp-mustache?format=websites)
[mustache.js](https://github.com/janl/mustache.js/)

# 実装手順
## 下準備
### AMP テンプレートの準備

```html
<!doctype html>
<html amp lang="en">
  <head>
    <meta charset="utf-8">
    <script async src="https://cdn.ampproject.org/v0.js"></script>
    <title>Hello, AMPs</title>
    <link rel="canonical" href="https://amp.dev/ja/documentation/guides-and-tutorials/start/create/basic_markup">
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
    <script type="application/ld+json">
      {
        "@context": "http://schema.org",
        "@type": "NewsArticle",
        "headline": "Open-source framework for publishing content",
        "datePublished": "2015-10-07T12:02:41Z",
        "image": [
          "logo.jpg"
        ]
      }
    </script>
    <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>
  </head>
  <body>
    <h1>Welcome to the mobile web</h1>
  </body>
</html>
```

### 使用するAMP componentの準備

```html
<!doctype html>
<html amp lang="en">
  <head>
    ・・・
    <link rel="canonical" href="https://amp.dev/ja/documentation/guides-and-tutorials/start/create/basic_markup">
    <meta name="viewport" content="widt
    h=device-width,minimum-scale=1,initial-scale=1">
    <script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
    <script async custom-element="amp-list" src="https://cdn.ampproject.org/v0/amp-list-0.1.js"></script>
    <script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.js"></script>
    <script type="application/ld+json">
      {
        "@context": "http://schema.org",
        "@type": "NewsArticle",
        "headline": "Open-source framework for publishing content",
        "datePublished": "2015-10-07T12:02:41Z",
        "image": [
          "logo.jpg"
        ]
      }
    </script>
    ・・・
</html>
```


[Create your AMP HTML page](https://amp.dev/documentation/guides-and-tutorials/start/create/basic_markup?format=websites)

## リストを作成する
### 記事のタイトルとユーザー名、タグの情報を表示

```html
<!doctype html>
<html amp lang="en">
  <head>
    ・・・
  </head>
  <body>
    <amp-list class="paged-amp-list"
    layout="fixed-height"
    height="720"
    src="https://qiita.com/api/v2/items"
    binding="no"
    items="."
    single-item
    id="App">
      <template type="amp-mustache">
        <div class="items">
          <div class="user-info-area">
            <div class="title">{{title}}</div>
            <div class="user-name">by {{user.name}}</div>
            <div class="tag-area">
              <i class="fas fa-tags"></i>
              {{#tags}}
                <span>{{name}}</span>
              {{/tags}}
            </div>
          </div>
        </div>
      </template>
    </amp-list>
  </body>
</html>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148185/7b653917-9b13-5e1d-a566-3175f2253083.png)


[amp-list](https://amp.dev/documentation/components/amp-list)
[amp-mustache](https://amp.dev/documentation/components/amp-mustache)
[amp-list src](https://amp.dev/documentation/components/amp-list#src-(required))
[amp-list binding](https://amp.dev/documentation/components/amp-list#binding-(optional))
[amp-list items](https://amp.dev/documentation/components/amp-list#items-(optional))


### ユーザーのアイコンを表示
* [amp-img](https://amp.dev/documentation/components/amp-img) を使って画像を表示する。

```html
<!doctype html>
<html amp lang="en">
  <head>
    ・・・
  </head>
  <body>
    <amp-list class="paged-amp-list"
    layout="fixed-height"
    height="720"
    src="https://qiita.com/api/v2/items"
    binding="no"
    items="."
    single-item
    id="App">
      <template type="amp-mustache">
        <div class="items">
          <div class="image-area">
            <amp-img
            class="image"
            width="40"
            height="40"
            src="{{user.profile_image_url}}"></amp-img>
          </div>
          <div class="user-info-area">
            <div class="title">{{title}}</div>
            <div class="user-name">by {{user.name}}</div>
            <div class="tag-area">
              <i class="fas fa-tags"></i>
              {{#tags}}
                <span>{{name}}</span>
              {{/tags}}
            </div>
          </div>
        </div>
      </template>
    </amp-list>
  </body>
</html>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148185/87c40ee4-7f3c-ed32-a020-25eea390ea93.png)

[amp-img](https://amp.dev/documentation/components/amp-img)

### 記事ページへのリンクを追加
* aタグ追加

```html
<!doctype html>
<html amp lang="en">
  <head>
    ・・・
  </head>
  <body>
    <amp-list class="paged-amp-list"
    layout="fixed-height"
    height="720"
    src="https://qiita.com/api/v2/items"
    binding="no"
    items="."
    single-item
    id="App">
      <template type="amp-mustache">
        <div class="items">
          <a href="{{url}}" class="item">
            <div class="image-area">
              <amp-img
              class="image"
              width="40"
              height="40"
              src="{{user.profile_image_url}}"></amp-img>
            </div>
            <div class="user-info-area">
              <div class="title">{{title}}</div>
              <div class="user-name">by {{user.name}}</div>
              <div class="tag-area">
                <i class="fas fa-tags"></i>
                {{#tags}}
                  <span>{{name}}</span>
                {{/tags}}
              </div>
            </div>
          </a>
        </div>
      </template>
    </amp-list>
  </body>
</html>
```

![amp-list-demo2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148185/a9a47283-cb95-d21d-e934-e477b3f095e1.gif)


### ページネーションの実装
* [amp-bind](https://amp.dev/documentation/components/amp-bind)の`setState`を使って実現する。
* `pageNumber`が変化したタイミングでqiita apiを叩いて、情報を取得する。

```html
[src]="'https://qiita.com/api/v2/items?page=' + pageNumber"
```

```html
<!doctype html>
<html amp lang="en">
  <head>
    ・・・
  </head>
  <body>
    <amp-list class="paged-amp-list"
    layout="fixed-height"
    height="720"
    src="https://qiita.com/api/v2/items"
    [src]="'https://qiita.com/api/v2/items?page=' + pageNumber"
    binding="no"
    items="."
    single-item
    id="App">
      <template type="amp-mustache">
        <div class="items">
          <a href="{{url}}" class="item">
            <div class="image-area">
              <amp-img
              class="image"
              width="40"
              height="40"
              src="{{user.profile_image_url}}"></amp-img>
            </div>
            <div class="user-info-area">
              <div class="title">{{title}}</div>
              <div class="user-name">by {{user.name}}</div>
              <div class="tag-area">
                <i class="fas fa-tags"></i>
                {{#tags}}
                  <span>{{name}}</span>
                {{/tags}}
              </div>
            </div>
          </a>
        </div>
      </template>
    </amp-list>
    <div class="navigation">
      <button class="button"
        hidden
        [hidden]="pageNumber < 2"
        on="tap: AMP.setState({ pageNumber: pageNumber - 1 })"
        >
        Previous
      </button>
      <button class="button"
        [hidden]="page ? pageNumber >= page.items.pageCount : false"
        on="tap: AMP.setState({ pageNumber: pageNumber ? pageNumber + 1 : 2 })">
        Next
      </button>
    </div>
  </body>
</html>
```

[amp-bind updating-state-with-amp.setstate()](https://amp.dev/documentation/components/amp-bind#updating-state-with-amp.setstate())


## fontawesome でタグのアイコンを表示
* タグのアイコン部分はfontawesomeを使う。

```html
<link href="https://use.fontawesome.com/releases/v5.6.1/css/all.css" rel="stylesheet">
```

```html
<!doctype html>
<html amp lang="en">
  <head>
    ・・・
    <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>
    <link href="https://use.fontawesome.com/releases/v5.6.1/css/all.css" rel="stylesheet">
  </head>
  <body>
    ・・・
  </body>
</html>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148185/0a2e68ec-6707-0681-529a-b581ef1ea070.png)


## 最低限のCSSをあてる

```html
<!doctype html>
<html amp lang="en">
  <head>
    ・・・
    <link href="https://use.fontawesome.com/releases/v5.6.1/css/all.css" rel="stylesheet">
    <style amp-custom>
      .paged-amp-list {
        margin: 20px;
      }

      .item {
        display: block;
        margin-bottom: 20px;
        border-bottom: solid 1px #e8e8e8;
        text-decoration: none;
        color: black;
      }

      .image {
        display: block;
      }

      .image-area {
        display: table-cell;
        padding: 15px;
      }

      .user-info-area {
        display: table-cell;
        vertical-align: top;
        padding: 15px;
      }

      .navigation {
        text-align: center;
      }

      .button {
        display: inline-block;
        width: 160px;
        padding: 0.8em;
        text-align: center;
        text-decoration: none;
        color: #fff;
        background:#0C88CA;
        border-bottom:4px solid #005691;
        border-radius: 4px;
      }
    </style>
  </head>
  <body>
    ・・・
  </body>
</html>
```

![amp-list-demo5.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148185/f4901016-9655-bb60-0220-7fb14fa6b477.gif)