わいの日記

ありがちエンジニアブログ

Nuxt.js の基本的な使い方

Nuxt.jsの基本機能ちょっと紹介します

vue-cliがあればすぐにプロジェクト作成できます

vue init nuxt-community/starter-template nuxt-study

cd nuxt-study
yarn
yarn dev

f:id:exhikkii:20180811100948p:plain

localhost:3000でつながります

f:id:exhikkii:20180811101055p:plain


まず、プロジェクトルートにpagesディレクトリがあります
ここに作成したvueファイルの名前がそのままurlになります
例えば、
pages/categories/index.vue -> localhost:3000/categories //index.vueの場合、indexは省略されます
pages/categories/add.vue -> localhost:3000/categories/add

さらに動的なパラメータを含むurlを作成したい場合は_(アンダースコア)を使います
pages/categories/_id.vue -> localhost:3000/categories/:id になります

pages/categories/index.vue
pages/categories/_id.vue
それぞれを作成します

pages/categories/index.vue
localhost:3000/categories

<template>
  <div>
    categories index
  </div>
</template>

pages/categories/_id.vue
localhost:3000/categories/:id
:idの箇所には適当な数字を入力してください
画面にその数字が表示されるはずです

<template>
  <div>
    categories {{$route.params.id}}
  </div>
</template>

ここでルーティングのvalidationについて
idに渡ってくるものが数字だけにしたい場合もあると思います
Nuxt.jsではvalidateメソッドを使ってバリデートする事ができます
下記のコードをpages/categories/_id.vueのtemplateタグの下に追記してください

<script>
export default {
  validate ({ params }) {
    return !isNaN(+params.id)
  }
}
</script>

もしバリデーションに引っかかったら404のエラーになります
_idに数字以外を入力すると、下のような画面になります
f:id:exhikkii:20180811102718p:plain

エラー画面をカスタマイズしたい場合もあると思います
次にlayoutsディレクトリを見ます
default.vueというファイルがあり、その中のtemplateタグにはタグが見えます
これがrouter-viewの役割をしています
つまり、pages直下に作成したvueファイルがの箇所に埋め込まれるわけですね

<template>
  <div>
    <nuxt/>
  </div>
</template>

話が戻ってlayoutsディレクトリ直下にerror.vueを作成して下記を貼り付けてください

<template>
  <div>
    <template v-if="error.statusCode === 404">
      not found
    </template>
    <template v-else>
      server error
    </template>
  </div>
</template>

<script>
export default {
  props: ['error']
}
</script>

エラーが起きると、そのエラーをerrorという名前でpropsで受け取れます
したがってerrorのstatusCodeによって表示を切り替える事が可能です

次に
pages/categories/index.vue を下記のように修正

<template>
  <div>
    categories index
    <nuxt-link to="/categories/add">
      Add Category
    </nuxt-link>
  </div>
</template>

nuxt-linkをrouter-linkのようなものです
現時点では特に差があるわけではないのですが、将来的に機能が追加されるようです

参考
https://ja.nuxtjs.org/api/components-nuxt-link/


pages/categories/add.vue を作成し、下記コードを貼り付け

<template>
  <div>
    <form @submit.prevent="submitCategory">
      <input type="text" v-model.trim="name">
      <input type="submit" value="submit">
    </form>
  </div>
</template>

<script>
export default {
  data () {
    return {
      name: ''
    }
  },
  methods: {
    submitCategory () {

    }
  }
}
</script>
<||

ここでformへのバリデーションをpluginを使って実装します
プロジェクトルートにpluginsディレクトリがあります
puginに関する記述はこのディレクトリ以下にします
今回はVuelidateを使います
[https://monterail.github.io/vuelidate/:embed:cite]

まずインストール & ファイル作成
>||
yarn add vuelidate
touch plugins/Vuelidate.js

plugins/Vuelidate.jsに以下をコピペ

import Vue from 'vue'
import Vuelidate from 'vuelidate'
Vue.use(Vuelidate)

次にプロジェクトルートにあるnuxt.config.jsに追記

module.exports = {
  // 下3行を追記します
  plugins: [
    '~/plugins/Vuelidate' 
  ],
  ...
  build: {
    vendor: ['vuelidate'], // この1行を追加
    ....
  }
}

上記のように
pluginの使い方は基本的に、
plugins直下に該当の設定ファイルを作成し、nuxt.config.jsで呼び込ませるという感じですね

pages/categories/add.vue に戻ります
使い方は公式をご参照ください

<template>
  <div>
    <form @submit.prevent="submitCategory">
      <input
        type="text"
        v-model.trim="name"
        @input="$v.name.$touch()"
      >
      <p v-if="!$v.name.required && $v.name.$dirty"> // nameが未入力かつ、入力したことがある場合
        name is required
      </p>
      <p v-if="!$v.name.minLength && $v.name.$dirty"> // nameが6文字より小さくかつ、入力したことがある場合
        name must be at least 6 chars
      </p>
      <input
        type="submit"
        value="submit"
        :disabled="$v.$invalid" // validation合格しないとbuttonがdisabled
      >
    </form>
  </div>
</template>

<script>
import { required, minLength } from 'vuelidate/lib/validators' // vuelidateの必要なものをimport

export default {
  data () {
    return {
      name: ''
    }
  },
  // ここでバリデーションを設定
  validations: {
    name: {
      required,
      minLength: minLength(6)
    }
  },
  methods: {
    submitCategory () {

    }
  }
}
</script>

これでバリデーション完了

次にsubmitCategoryの実装もといデータ登録に移ります
serverやdb準備するのが面倒なので横着してjson-serverを利用します
そのためにjson-serverのインストールとjsonファイルをプロジェクトルートに作成

yarn global add json-server

touch category.data.json

category.data.jsonに空のcategories配列を作成しておきます

{
  "categories": []
}

そしてjson-server起動

json-server --watch category.data.json --port 3001

localhost:3001にアクセスするとreourcesにcategoriesがあるはずです
f:id:exhikkii:20180811183533p:plain

json-serverにデータを送るためにaxiosを入れます
Nuxt.js向けにaxiosがあるのでそちらをインストールします

yarn add @nuxtjs/axios

次に設定ですね
nuxt.config.jsの同じ階層に下記を追記

modules: [
    '@nuxtjs/axios',
 ],

準備できたのでsubmitCategoryメソッドを以下のように修正します
axiosをimportしなくとも利用できるようになります
実際にsubmitしてから、localhost:3001/categoriesにアクセスすると登録できているはずです

async submitCategory () {
    const category = { name: this.name }
    try {
      await this.$axios.$post(`http://localhost:3001/categories`, category)
    } catch (err) {
      console.log(err)
    }
  }

次に登録したデータを取得して表示します
pages/categories/index.vue を修正

<template>
  <div>
    categories index
    <nuxt-link to="/categories/add">
      Add Category
    </nuxt-link>
    <template v-for="(category, index) in categories">
      <div :key="index">
        category {{index}}: {{ category.name }}
      </div>
    </template>
  </div>
</template>

<script>
export default {
  async asyncData ({ app, req, params }) {
    const categories = await app.$axios.$get(`http://localhost:3001/categories`)
    return { categories }
  }
}
</script>

新しいキーワードとしてasyncDataがありますね
こちらはcomponentがロードされる前に、サーバからデータを取得して、
dataオブジェクトに突っ込んでくれるものです
なのでreturnしたオブジェクトがdataオブジェクトの一部かのように扱えるわけです

今回は使わないですが、reqやparamsといったものも引数で受け取れます

await使うときに async asyncDataとasyncが続くのがとてももっさく感じます

最後にmiddlewareを紹介します
ログインしていないユーザには遷移させたくないページなどがあると思いますが、
そういったルートを制御する使い方が多いかなと思います
vue-routerのbeforeEachとかと近いイメージだと思って大丈夫だと思います

touch middleware/auth.js

今回はlocalStorageにtokenというキーがなければcategories/index.vueにリダイレクする処理になっています
普通のプロジェクトならfirebaseやjwtを使うことになるのかな

export default  ({ redirect }) => {
  if (!localStorage.getItem('token')) {
    console.log('test')
    return redirect('/categories')
  }
}

このmiddlwwareを登録します
pages/categories/add.vue

export default { 
  middleware: 'auth', // これだけで登録完了
  data () {
    return {
      name: ''
    }
  },
   ...
}

これでcategories/add.vueには遷移できなくなったはずです

localStorageにtokenセットすれば遷移できるようになります

localStorage.setItem('token', 'nuxt')

まだまだ書きたいことあるけど、
疲れたのでここで終えます

お疲れさまでした

基礎から学ぶ Vue.js

基礎から学ぶ Vue.js