Nuxt.js 入門 #1 Nuxt.js によるブログアプリ制作 解説メモ

この記事は
[Nuxt.js 入門 #1](https://www.chatbox.blog/2018/03/26/nuxt-js-start-1/)
を実践しながら、詰まったところを記録しておくものです。

# なぜこの記事を選んだか

Nuxt.jsを触りたいが、初めから順番に作っていくような、RoRチュートリアルのような記事が見つからなかったからです。

できればフルスクラッチがよかったのですが、他に見つからないので。(vue-cliからテンプレートを使用します。)

あと、コードがハイライトされていないことがかなりの苦痛で、できれば避けたかったのですが…

第一候補の
[The Nuxt.js Tutorial to Build a Multilanguage Website - Storyblok](https://www.storyblok.com/tp/nuxt-js-multilanguage-website-tutorial)
がstoryblok.comの登録が必要だったので、第二候補のこちらへ。


# 筆者知識

* JSそこそこ使う
* 2017年前半ごろにVueとVuexをてきとーに使いTODO(未満)アプリ作成(ほぼ忘却)
* Nuxt.js未経験

# 実行環境

* Windows7 64bit
* node v9.3.0

## テンプレート作成側

* vue-cli 2.9.6

## テンプレート内

`nuxt-community/starter-template my-vue-app`

(いろいろはいっているのでメインのみ)

* nuxt 1.4.2
* vue 2.5.17
* vue-router 3.0.1
* vuex 3.0.1
* webpack 3.12.0

# 作業環境

* Firefox 61
* Visual Studio Code 1.25.1
 * Vetur 0.12.6 を新規追加 

# 付録 Emmet

いきなり付録で申し訳ない。
久しぶりにEmmetを書いたのですが、vueファイルではいきなりEmmetではかけず、タグの中なら有効になるようです。
つまり、白紙ファイルに

`template>div...`
と書いても展開されず、手打ちで`<template>`を打ってから、その内部で`div...`とEmmetを書く必要がありました。


# ページの作成

```vuejs
<template>
  <div>
    <h1 class="title">My Blog App</h1>

    <ul>
        <li v-for="post in posts">{{post.title}}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data(){
    return {
      posts: [
        {
          "id": 1,
          "title": "最初の記事です。"
        },
        {
          "id": 2,
          "title": "2番目の投稿です。",
        },
        {
          "id": 3,
          "title": "３番めの投稿です。",
        },
      ]      
    }
  }  
}
</script>
```

VSCodeで作業していると警告が出るのですが、
`v-for`に`key`がありません。

```
5:7  error  Elements in iteration expect to have 'v-bind:key' directives  vue/require-v-for-key
```

[リストレンダリング — Vue.js](https://jp.vuejs.org/v2/guide/list.html)

>Vue が各ノードの識別情報を追跡できるヒントを与えるために、また、先ほど説明したような既存の要素の再利用と並び替えができるように、一意な `key` 属性を全てのアイテムに与える必要があります。この特別な属性は 1.x の `track-by` に相当するものですが、しかしこれは属性のように動作します。従って、これを動的な値に束縛するためには `v-bind` を使う必要があります (以下は省略構文を使ったものです):
>
```vue
<div v-for="item in items" :key="item.id">
  <!-- content -->
</div>
```
>可能なときはいつでも v-for に key を与えることが推奨されます。これは、繰り返される DOM の内容が単純でない、または性能向上を標準の動作に意図的に頼っていない場合に限ります。

[リストレンダリング#コンポーネントとv-for — Vue.js](https://jp.vuejs.org/v2/guide/list.html#%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%81%A8-v-for)
>
このセクションでは、コンポーネントについての知識を前提としています。もし分からなければ、このセクションを遠慮なく飛ばして、理解した後に戻ってきてください。
>
普通の要素のように、カスタムコンポーネントで直接 v-for を使うことができます:
>
```vue
<my-component v-for="item in items" :key="item.id"></my-component>
```
>
2.2.0 以降で、コンポーネントで v-for を使用するとき、key は必須です

**2.2.0 以降で、コンポーネントで v-for を使用するとき、key は必須です**

このことから入門記事はvue2.2.0以下だということが伺えますね。(投稿日時とリリースを突き合わせればいいんですが…)

['v-for' directives require 'v-bind:key' directives. · Issue #261 · vuejs/vetur](https://github.com/vuejs/vetur/issues/261)
(読んでいない)

## 解決方法

keyを指定してやります。

```vue
<li v-for="post in posts" :key=post.id>{{post.title}}</li>
```

# 画面遷移

>ページ遷移には a ではなく router-link コンポーネントを利用しましょう。
>
>```vue
<template>
  <div>
    <h1 class="title">About this App</h1>
>
    <p>アプリケーションの紹介文がここに入ります。</p>
>
    <router-link to="/">トップページへ戻る</router-link>    
  </div>
</template>
```

ここ、うっかり`a`を`router-link`に変えるだけでは、

````
TypeError
Cannot read property 'name' of undefined
```

が出ます。
`a`の移動先は`href`属性ですが、`router-link`は`to`属性なので、そこも書き換えましょう。

```vue:失敗例
<template>
    <div>
        <h1 class="title">About this App</h1>
        <p>アプリケーションの紹介文がここに入ります。</p>
        <router-link href="/">トップページへ戻る</router-link>
    </div>
</template>

<script>
export default {
    date() {
        return {}
    }
}
</script>
```



## 付録

>ページ遷移には a ではなく router-link コンポーネントを利用しましょう。

nuxtには`nuxt-link`というものもあります。

[API: - Nuxt.js](https://ja.nuxtjs.org/api/components-nuxt-link/)
>現時点では、`<nuxt-link>` は `<router-link>` と同じです。そのため、[Vue Router](https://router.vuejs.org/ja/api/) のドキュメント でこのコンポーネントの使い方を確認することをお勧めします。

念の為頭の中でaliasをはっておきましょう。

# API アクセスとデータのハンドリング

昔触ったときは`...hogehoge`でコンポーネント側はVuexを呼び出していた記憶があるのですが、なんだったか？

>各コンポーネント内では Vuex ストアが自動的にロードされているため、

いちいちimportしなくていいのは楽ですね。
どうなっているのだろう？

## 付録 Vuexの書き方

ここからVuexを使いますが、

```js
export const state = () => ({
  posts: []
})
```

という書き方は

[Vuex | Vuex 入門](https://vuex.vuejs.org/ja/guide/)
のような

```js
const store = new Vuex.Store({
```

の形式ではありません。

[Vuex ストア - Nuxt.js](https://ja.nuxtjs.org/guide/vuex-store/)
で紹介されている、**モジュールモード**という記述方法のようです。

## どうでもいいもの

page.vueの直書きのときからだったんですが、3が全角なのが激しく気になって気になってしかたがないです。

```js
export const actions = {
  load(ctx){
    const items = [
      {
        "id": 1,
        "title": "最初の記事です。"
      },
      {
        "id": 2,
        "title": "2番目の投稿です。",
      },
      {
        "id": 3,
        "title": "３番めの投稿です。",
      }      
    ]
    ctx.commit("set",items)
  }

}
```

***

ここまで書いて#2以降読んでいったら、これアプリを拡張する方向ではなくて記事ごとに別々の内容ですね…
やはりハンズオン資料などがいいのかな。