Nuxt.js インストール
yarn をダウンロード
https://yarnpkg.com/lang/en/docs/install/#windows-stable
vue-cli のインストール
グローバルインストールすることで vue コマンドが使えるようになる。
yarn global add @vue/cli
インストールできたら、バージョンを確認してみる
vue --version
テンプレートダウンロード
①starter-template
サクッと作りたいときに使う。starter-template には Babel と ESLint が含まれる
vue init nuxt-community/starter-template <projectName>
②create-nuxt-app
本格的なアプリを作るときはこれが良いらしい。
npx create-nuxt-app <projectName>
モジュールインストール
プロジェクトディレクトリに移動し、package.json にあるモジュールをインストールする
cd <projectName>
yarn
yarn dev
yarn dev
で起動したら、http://localhost:3000でアクセス。
環境変数を設定する
nuxt.js 内で使うグローバルな変数。
nuxt.config.js の env プロパティに設定する。サーバーの環境変数があればprocess.env
を優先し、そうでなければ直書きした方を設定する。
...
env: {
baseUrl: process.env.BASE_URL || 'http://localhost:3000'
}
...
スタイルの設定
scss の導入
yarn add -D node-sass sass-loader
グローバル領域の scss ファイルは nuxt.config.js
に記述
...
css: [
// CSS file in the project
'@/assets/css/main.css',
// SCSS file in the project
'@/assets/css/main.scss'
],
...
Chrome アドオン
vue 用のデベロッパーツール拡張アドオン。あるとデバッグが捗る。
https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=ja
サーバーサイドレンダリング(SSR)
asyncData() で非同期処理
axios を使った非同期処理をサーバーサイドでレンダリングして返す。pages/index.vueでの適当な例。
<template>
<div>
<ul>
<li v-for="item in items" :key="item.id">{{ item.適当なプロパティ名 }}</li>
</ul>
</div>
</template>
<script>
export default {
async asyncData({app}) {
const items = await app.$axios.$get('適当なAPIURL')
return { items }
}
}
</script>
これでソースコードを見ると、既に vue のコードがレンダリングされ、データが反映されていることが分かる。
asyncData()
はコンポーネントの初期化前に実行されるので this を使うことができない-
asyncData()
の引数は context で定義されているプロパティを受け取ることが出来るので、https://nuxtjs.org/api/context#the-context を参考にしてほしいデータを使う。 - 例えば app にはモジュールが格納されているので、this.$axios の代わりに app.$axios でモジュールを呼び出す(
import axios from 'asxios'
での呼び出しとは違う)。 asyncData()
で return したものは data() にマージされる。なので、 data() が無くても template 内で使用できている(上の例でいうとitems
)
メタの設定
nuxt.config.js で設定をする。%s
で呼び出す。
module.exports = {
head: {
title: '適当なタイトル',
titleTemplate: '%s'
},
...
}
head.title はそれぞれのテンプレートで上書きできる。例えば、data に page.title というプロパティがあるとすると…
export default {
head() {
return {
title: this.page.title,
meta: [
{ hid: 'description', name: 'description', content: '説明だ' }
]
}
},
}
タイトル以 外は meta 配列に定義していく。
Vuex で管理
一度読み込んだデータをキャッシュしておいたりできる?クラシックモードとモジュールモードがあり、クラシックモードは3系で廃止されるらしい。モジュールモードでとてもハマった。
例:store/todos.js
export const state = () => ({
items: [],
})
export const getters = {
items: state => state.items,
}
export const mutations = {
setItems(state, {items}) {
state.items = items
},
}
export const actions = {
async fetchItems({commit}) {
const items = await this.$axios.$get(適当なAPIURL)
commit('setItems', {items})
},
}
- state … 関数になる点に注意。ここにデータを保存する。
- getters … ゲッター。それぞれのpageではこのgetterを使ってstateの値を呼び出す。
- mutations … state を唯一変更できる。
store.commit('mutation名')
で呼び出す。 - actions … mutation に commit メソッドを送る。非同期処理はここに書く。page側では
store.dispatch('action名')
で action を呼び出す
page/index.vue
<template>
<div>
<p v-for="todo in todoList" :key="todo.id">{{ todo.name }}</p>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
async asyncData({store}) {
if (store.getters['todos/items'].length) {
return
}
await store.dispatch('todos/fetchItems')
},
computed: {
…mapGetters({
todoList: 'todos/items'
})
}
}
- 基本的に「storeのファイル名/関数名」みたいな形で呼び出す
- index.js に書いてたら「関数名」だけで呼べる(たぶん)けど、モジュールモードならあまり使わないのかも?
...mapGetters({ ... })
で、ゲッターでゲットしてきたプロパティ名を変更できる。
エラー
Error: EPERM: operation not permitted, lstat “******”
パーミッションエラーでコンパイルできない?
特にパーミッションに関する変更などは行っていなかったので、エディタの排他制御か何かの影響だったのか、とりあえずテキストエディタを閉じてからyarn dev
したら正常にコンパイルできた。.nuxt
ディレクトリ内のファイルを開いていたのがいけなかったのかも
Classic mode for store/ is deprecated and will be removed in Nuxt 3.
vuex のクラシックモードは廃止予定らしい。store/index.js
にて、Vuex インスタンスを return しているものはクラシックモードなので言われてしまう。なので、モジュールモードで書こう。
export default () => {
return new Vuex.Store({ ... })
}
参考
axiosモジュール
https://uncle-javascript.com/weird-nuxt-3-axios-data-fetch