「Nuxt.jsビギナーズガイド」の感想・備忘録2

スポンサーリンク
「Nuxt.jsビギナーズガイド」の感想・備忘録1の続き

Nuxt.jsの基本

pagesディレクトリ

  • users/_id.vueは/users/100のようなURLでアクセスすることができる。
<template>
  <h1>id: {{ $route.params.id }}</h1>
</template>
<!-- またはdataでuserId: this.$route.params.idとして -->
<template>
  <h1>id: {{ userId }}</h1>
</template>
  • /users/100/postsのようなURLにしたい場合はusers/_userId/posts.vueのようにディレクトリ名の先頭を_にする。
<!-- users/_userId/posts/_postId.vueに/users/100/posts/200でアクセスした場合 -->
<ul>
  <li>userId: {{ $route.params.userId }}</li>
  <li>postId: {{ $route.params.postId }}</li>
</ul>
<!-- ※ users/_userId/index.vueとusers/_userId.vueのようにディレクトリ名とファイル名が同じ_xxxxだとファイルの方が優先される。 -->

axios-module

  • axiosにリクエストのフックなどの機能を追加したNuxt.js専用のライブラリ。
  • https://axios.nuxtjs.org

使い方

1. npm install @nuxtjs/axios
2. nuxt.config.jsに追記
modules: ['@nuxtjs/axios'],
axios: {},
3. jsを記述
async asyncData({app}) {
  const json = await app.$axios.$get('https://qiita.com/api/v2/items?query=tag=nuxt.js');
  return { json };
},

asyncData()フック

  • Vue.jsではAPIでデータを取得する処理はcreated()フックに書くのが一般的である。
    しかし、created()フックはブラウザでの実行となるため、Nuxt.jsではcreated()でははなくasyncData()フックに書いてSSRにも対応させる。
  • asyncData()フックはコンポーネントの初期化前に実行されるため、thisへのアクセスができない。
    asyncData(context)と引数を取得することでcontext.appcontext.paramsを使うことができる。
    通常は分割代入を使ってasyncData({app, params})のように書く。
  • https://negalog.com/nuxt-js-fetch-data/
  • https://nuxtjs.org/ja/docs/internals-glossary/context/

head()によるHTMLメタの設定

  • nuxt.config.jsのheadにtitleなどを設定する。
  • titleTemplateを設定すると、共通のタイトルをsprintf記法で設定することができる。
head: {
  title: 'my-first-nuxt-app',
  titleTemplate: '%s | Nuxt.js Test',
  // 以下省略
}
  • 各ページでは以下のようにタイトルを指定する。
head() {
  return {
    title: 'nuxt.jsタグ一覧',
  }
}
// headメソッドはnuxt.config.jsのheadの値をオーバーライド(差分のみ)する。

vuex

  • Nuxt.jsアプリケーションは画面遷移やAPIキャッシュが必要になることが多いため、vuexを利用することをオススメする。
  • Nuxt.jsでvuexを使う場合、クラシックモードとモジュールモードがある。

クラシックモード

  • クラシックモードの場合、storeディレクトリにindex.jsを作成しVuex.Storeインスタンスを返却する関数を定義する。
  • Nuxt.jsのv3ではVuexのクラシックモードが廃止されるため、モジュールモードを使うべき。
クラシックモードのサンプル
import Vuex from 'vuex';

export default () =>
  new Vuex.Store({
    state: {
      articles: [],
    },
    mutations: {
      setArticles(state, {articles}) {
        state.articles = articles;
      },
    },
    actions: {
      setArticles({commit}, {articles}) {
        commit('setArticles', {articles});
      },
    },
  })

各コンポーネントからは、this.$storeでアクセスすることができる。
asyncDataフックでは以下のようになる。

asyncData({store}) {
  store.dispatch('setArticles', {articles: [1, 2]});
  console.log(store.state.articles);
}

モジュールモード

Nuxt.jsはstoreディレクトリ内のファイルに対して、以下のルールで動作する。

  • index.jsはルートモジュールである。
  • index.jsがStoreインスタンスをexportしている場合はクラシックモード、そうでない場合はモジュールモードとなる。
  • index.js以外のjsファイルはファイル名のスコープによるモジュールとして扱われる
モジュールモードのサンプル
export const state = () => ({
  isLoading: false
})
export const mutations = {
  setIsLoading(state, isLoading) {
    state.isLoading = isLoading
  }
}
export const state = () => ({
  list: []
})

export const mutations = {
  addUser(state, user) {
    state.list.push(user)
  }
}

export const actions = {
  addUser({ commit }, { user }) {
    commit('addUser', user)
  }
}

usersはモジュールとして扱われるため、gettersやactionsへのアクセスは以下のようになる。

  • store.dispatch('users/addUser', {user: 'hoge'});
  • console.log(store.state.users.list);

上記の例はクラシックモードで以下のようにindex.jsを記述した場合と同等に扱われる。

import Vuex from 'vuex';

export default () =>
  new Vuex.Store({
    state: {
      isLoading: false
    },
    mutations: {
      setIsLoading(state, isLoading) {
        state.isLoading = isLoading
      }
    },
    modules: {
      users: {
        state: {
          list: [],
        },
        mutations: {
          addUser(state, user) {
            state.list.push(user)
          },
        actions: {
          addUser({ commit }, { user }) {
            commit('addUser', user)
          },
        },
      },
    },
  })

コメント