nuxtを使ってqiitaの投稿一覧サイトを作る(準備2)


2018/10/27 追記
store を使うよう更新しました。
詳細はこちらを参照してください。


ここのところ先日作成した LINE BOTに【cotogoto】や【repl-ai】を組み込んで遊んでいました
いやぁ・・・面白いですね!
microsoft のコグニートも使ってみたいなぁ…なんて夢が広がります

本題

だいぶ間が空きましたが、今回はページを読み込んだ際に
axios で取得したデータを描画したいと思います

前回はページを読み込んだ際に静的なデータをテーブルに描画しました

モジュールのバージョン

使用しているモジュールのバーションは以下の通りです
element-ui は 2.0 系がリリースされていますが、今回は 1.0 系で行きます

1
2
3
4
5
6
7
8
"dependencies": {
"axios": "^0.17.1",
"element-ui": "1.4.12",
"nuxt": "1.0.0-rc10",
"vue": "2.3.0",
"vue-server-renderer": "2.3.0",
"vue-template-compiler": "2.3.0"
}

使用する API

Qiita の公開 APIを使用します
ドキュメントによると、未認証ユーザーでも
1 時間に 60 回までリクエストできるそうなので未認証でいきます

コールする API は【投稿の一覧取得】です

axios のインストール

まずは axios をインストールします

1
$ yarn add axios

続いて nuxt.config.js の build 内に以下の設定を追加します

1
2
build: {
vendor: ['axios'], ...

これで axios を使う準備ができました

ページの作成

新たに pages/axiosList.vue を追加し、script 部分から作成します
axios をインポートしてレイアウトを指定します

よくよく考えると作っているデザインは 2 カラムではないのですが、気にしたらダメです。

1
2
3
4
5
6
7
8
<script lang="babel">
// axiosをインポート
import axios from 'axios'
export default {
// レイアウトを指定
layout: 'twocolumns'
}
</script>

ここまでは前回とあまり変わらないですね
次に axios で通信する部分を記述します

今回は vue インスタンスが作成された後に呼ばれる【created】で axios を呼びたいと思います

created で取得した Qiita 投稿データを lists に格納します
取得件数は 6 件、検索クエリは一先ず「nuxt.js」としました

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
export default {
layout: "twocolumns",
data() {
return {
lists: []
};
},
created() {
axios
.get("https://qiita.com/api/v2/items", {
params: {
page: 1,
per_page: 6,
query: "nuxt.js"
}
})
.then(response => {
this.lists = response.data;
})
.catch(e => {
console.error("error:", e);
});
}
};

通信部分ができたので次は描画部分に取り掛かります
今回は element-ui の【カード】、【タグ】を使って描画していきます
まずは記事タイトル、作成日、投稿者のアイコン、投稿者の id、記事タグの一覧を表示します

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
<div>
<el-row :gutter="10">
<el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="1"><div class="grid-content bg-purple"></div></el-col>
<el-col :xs="8" :sm="8" :md="8" :lg="8" :xl="8" v-for="(element, index) in lists" :key="index" class="col-style">
<el-card class="box-card">
<div slot="header" class="clearfix">
<a :href="element.url" target="_blank">
<i class="el-icon-edit"></i>
{{ element.title }}
</a>
</div>
<div class="bottom clearfix content-style">
<div>{{ element.created_at }}</div>
<div>
<img :src="element.user.profile_image_url" width="20" height="20" />
<span>@{{ element.user.id }}</span>
</div>
<el-tag size="mini" type="info" class="tab-style" v-for="(tag, index) in element.tags" :key="index">{{ tag.name }}</el-tag>
</div>
</el-card>
</el-col>
</el-row>
</div>
</template>

動作を見てみると・・・ちゃんと表示されました:)

ちょっと欲張ってみる

当初の目的は達成できました
記事の内容も多少覗けるともっといいですね!

…とは言え、qiita の GET /api/v2/items レスポンスにアブストラクトはありません
body を指定すると本文がまるっと表示されてしまうので、ちょっとだけ表示させるよう javascript で工夫します

script 部分に body トリミング用の関数を作成します

1
2
3
4
5
methods: {
getDescription: function (body) {
return body.slice(0, 100) + '...'
}
}

この関数を描画部分に指定します

1
<div>{{ getDescription(element.body) }}</div>

動作を見てみると・・・いい感じです ♪

もうちょっと欲張ってみる

投稿者の自己紹介が見れると更にいいと思うので、次は element-ui の【ポップオーバー】を使って
id 名にカーソルを持っていった場合に投稿者の方が自己紹介を登録していたら表示させたいと思います

描画部分に分岐処理を入れます

1
2
3
4
5
6
7
8
<template v-if="element.user.description">
<el-popover slot="description" placement="top-start" width="300" trigger="hover" :content="element.user.description">
<span slot="reference">@{{ element.user.id }}</span>
</el-popover>
</template>
<template v-else>
<span>@{{ element.user.id }}</span>
</template>

完成です!

axiosList.vue の最終形態

デモ

まとめ

だいぶ形になってきました
準備編は今回でおしまいです
次回はこれまで作成したものを流用しつつ
element-ui2.0 へのバージョンアップやページネーションや検索機能をつけたいと思います

参考

Share