Vue CLI 3(Command Line Interface)を利用して、ルーティング処理を施すVue Routerと、データの状態管理をおこなうVuexによるアプリ構築の概略を説明してみます。
インストール
まずはVue CLIをインストールします。Node.jsのバージョンは8.9以上が必要です。
1 |
npm install -g @vue/cli |
Yarnを利用する場合は下記のようにします。
1 |
yarn global add @vue/cli |
バージョンを指定する場合は下記のようにします。
1 |
npm install -g @vue/cli@3.4.0 |
ついでに単一ファイルコンポーネントを手軽に起動できるvue serveやvue build等のコマンドを利用するための@vue/cli-service-globalもインストールしておきます。
1 |
npm install -g @vue/cli-service-global |
同じくYarnを利用する場合は下記のようにします。
1 |
yarn global add @vue/cli-service-global |
本記事執筆時点でバージョンは3.4.0になります。
1 2 |
vue --version //もしくはvue -V 3.4.0 |
もし@vue/cliではなくvue-cliをすでにインストールしている場合は、アンインストールしておく必要があります。
1 |
npm uninstall vue-cli -g |
1 |
yarn global remove vue-cli |
プロジェクト作成
vue createでプロジェクトを作成します。今回は「my-project」という名前のプロジェクトにします。
1 |
vue create my-project |
まず「default〜」か「Manually〜」かを選択します。本記事ではVue RouterとVuexを利用するので「Manually〜」の方を選択します。
1 2 3 4 |
Vue CLI v3.4.0 ? Please pick a preset: default (babel, eslint) ❯ Manually select features |
「Router」と「Vuex」を追加設定しておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Vue CLI v3.4.0 ? Please pick a preset: Manually select features ? Check the features needed for your project: (Press <space> to select, <a> to toggle all, <i> to invert selection) ◉ Babel ◯ TypeScript ◯ Progressive Web App (PWA) Support ◉ Router ❯◉ Vuex ◯ CSS Pre-processors ◉ Linter / Formatter ◯ Unit Testing ◯ E2E Testing |
関連ページ
Vue.jsでTypeScript入門 [class-style component]
Vue RouterのHistoryモードについてはYesを選択しておきます。
1 2 |
? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n) |
Lintとフォーマッター機能を選択します。今回はそのまま進みます。
1 2 3 4 5 |
? Pick a linter / formatter config: (Use arrow keys) ❯ ESLint with error prevention only ESLint + Airbnb config ESLint + Standard config ESLint + Prettier |
Lintが実行されるタイミングを選択します。今回は「保存時」で進みます。
1 2 3 4 |
? Pick additional lint features: (Press <space> to select, <a> to toggl e all, <i> to invert selection) ❯◉ Lint on save ◯ Lint and fix on commit |
Babel等各種ライブラリの設定方法を選択します。今回はそのまま進みます。
1 2 3 4 |
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? (Use arrow keys) ❯ In dedicated config files In package.json |
上記でおこなってきた設定内容を保存しておくかを問われます。今回は「N」を選択します。
1 |
? Save this as a preset for future projects? (y/N) |
確定ししばらくすると下記のように表示され、my-projectプロジェクトが生成されているのが確認できます。
1 2 3 4 5 6 |
省略〜 🎉 Successfully created project my-project. 👉 Get started with the following commands: $ cd my-project $ npm run serve |
実際に「npm run serve」コマンドを実行すると、ブラウザで下記のような画面を確認することができます。上部にHomeとAboutのリンクがあり、それぞれの画面に遷移できます。後で説明するように、それぞれの画面はHome.vueおよびAbout.vueコンポーネントによって作成されています。
↓トップページであるHome画面
↓下記はAbout画面
上記で記述したプロジェクト作成の過程は、下記コマンドで起動するブラウザのUI上でも実行することができます(本記事では説明しません)。
1 |
vue ui |
プロジェクトの構成
Vue CLI 3によって実際に生成されたプロジェクトは下記のような構成になっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
. ├── README.md ├── babel.config.js ├── node_modules ├── package-lock.json ├── package.json ├── postcss.config.js ├── public │ ├── favicon.ico │ └── index.html └── src ├── App.vue ├── assets │ └── logo.png ├── components │ └── HelloWorld.vue ├── main.js ├── router.js ├── store.js └── views ├── About.vue └── Home.vue |
App.vue
アプリケーションのルートコンポーネントです。8行目の<router-view/>の部分には、URLのパスと一致するコンポーネントが組み込まれ表示されていきます。viewsの項目を参照して下さい。
main.js
App.vueを取り込み、index.htmlと紐づけています。routerおよびstoreのインスタンスをVueに設定しているのが確認できます。この設定によってどのコンポーネント内においても、$store〜のように記述することによってストアのデータを取得できるようになります(後述)。
1 2 3 4 5 6 7 8 9 10 11 12 |
import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' Vue.config.productionTip = false new Vue({ router, store, render: h => h(App) }).$mount('#app') |
components内には、アプリケーションで使用するコンポーネントが配置されます。デフォルトではすでにHelloWorld.vueが存在しますが、これはHome.vue内で部品として使用されています。
関連ページ
Vue.jsのコンポーネント入門[props][$emit]
views内には、主にVue Routerでルーティングする、いわゆるURLのパスに一致する画面単位でのコンポーネントが配置されます。プロジェクト生成時には、すでにHome.vueとAbout.vueが生成されていますが、それぞれトップ画面(/)としてルーティングされているHome画面とAbout画面(/about)のコンポーネントになります。
router.js
Vue Routerの設定ファイルです。
store.js
Vuexのストアによってデータを一元管理する設定ファイルです。デフォルトではまだデータは管理されていません。
プロジェクトのビルド
公開用のファイル群を生成するためのビルドは、下記コマンドによって実行できます。ビルドすると「dist」フォルダが生成されます。本記事では説明しません。
1 |
npm run build |
簡単なカウンターアプリの構築
上記で作成した「my-project」プロジェクトを元に、ご多分に漏れず簡単なカウンターアプリを実装してみます。
Vue Routerで管理するページを1画面増やし、またVuexによるストア機能によってカウンターの数値を一元管理してみます。
まずはプロジェクト作成時にデフォルトで存在するHome・About画面に対して、1画面増やしてみます。追加するのは画面単位でのコンポーネントになるので、componentsディレクトリ内ではなくviewsディレクトリ内にCount.vueという名前のファイルを新規追加します。
次にrouter.jsを編集します。Count.vueが、URLのパス「/count」で表示されるように設定します。
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 26 27 28 29 30 |
import Vue from 'vue' import Router from 'vue-router' import Home from './views/Home.vue' Vue.use(Router) export default new Router({ mode: 'history', base: process.env.BASE_URL, routes: [ { path: '/', name: 'home', component: Home }, { path: '/about', name: 'about', // route level code-splitting // this generates a separate chunk (about.[hash].js) for this route // which is lazy-loaded when the route is visited. component: () => import(/* webpackChunkName: "about" */ './views/About.vue') }, { path: '/count', name: 'count', component: () => import('./views/Count.vue') } ] }) |
App.vueに、画面へ遷移するリンクを付け足します。
1 2 3 4 5 6 7 8 9 10 11 12 |
<template> <div id="app"> <div id="nav"> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> | <router-link to="/count">Count</router-link> </div> <router-view/> </div> </template> …省略 |
以上でまだ画面上部にリンクしか表示されていませんが、「localhost:8080/count」にて下記のような画面が確認できます。
次にカウンターアプリとしての機能を追加していきます。上記で作成したCount画面にて、Vuexによるストアで一元管理している数値をカウントする機能を実装しています。
まずは、store.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 25 |
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { count: 5 }, mutations: { increment(state) { state.count++ }, decrement(state) { state.count-- } }, actions: { increment: ({ commit }) => { setTimeout(() => { commit('increment') }, 5000) } } }) |
state
このcountデータは「$store.state.count」のように記述することによって、様々なコンポーネント内において取得できます。stateに記述したデータを更新する処理は、mutationsに記述していきます。
mutations
stateに対する処理をおこなっています。countデータを加減させる2つの処理(increment/decrement)を記述しています。例えばコンポーネント内において、このmutations内のincrementの処理を呼び出すには、commitメソッドを利用して「this.$store.commit(“increment”)」のように記述します。
actions
一般的にAPI通信や非同期処理はこのactionsに記述し、mutationsを実行する処理などをおこないます。上記ではmutationsのincrement処理を呼び出し、その処理が5秒後に実行されるよう記述しています。例えばコンポーネント内において、このactions内のincrementの処理を呼び出すには、dispatchメソッドを利用して「this.$store.dispatch(“increment”)」のように記述します。
そしてまだ空白であるCount.vueを下記のように編集します。これでカウンターアプリとしての機能はとりあえず完成です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<template> <div class="count"> <h1>This is an count page</h1> {{$store.state.count}} <button @click="increment">+</button> <button @click="decrement">-</button> </div> </template> <script> export default { methods: { increment() { this.$store.commit("increment"); }, decrement() { this.$store.commit("decrement"); } } }; </script> |
4行目
上述したように、Vuexのストアに状態として管理されているcountデータを取得しています。
14、17行目
上述したように、commitを利用しているのでmutationsの方のincrement処理を実行しています。仮に14行目を下記のようにdispatchで呼び出した場合、actionsの方のincrement処理が呼び出されるので「+」ボタンをクリックして5秒後に数値が増える挙動に変化します。
1 |
this.$store.dispatch("increment"); |
ヘルパー関数を利用してCount.vueを下記のように記述することも可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<template> <div class="count"> <h1>This is an count page</h1> {{$store.state.count}} <button @click="increment">+</button> <button @click="decrement">-</button> </div> </template> <script> import { mapMutations } from "vuex"; export default { methods: { ...mapMutations(["increment", "decrement"]) } }; </script> |
本記事では説明しませんが、ヘルパー関数としては他にもmapStateやmapGetters、mapActionsが存在します。
例)actionsの方のincrementを呼び出したい場合
1 2 3 4 5 6 7 8 9 10 11 |
〜省略 <script> import { mapMutations, mapActions } from "vuex"; export default { methods: { ...mapMutations(["decrement"]), ...mapActions(["increment"]) } }; </script> |
最後にAbout.vueも下記のように編集してみて下さい。Vuexのストアで数値が管理されているのでCount画面で変更した数値が、About画面に切り替えてもしっかりと同期されているのが確認できます。
1 2 3 4 5 6 |
<template> <div class="about"> <h1>This is an about page</h1> {{$store.state.count}} </div> </template> |
Nuxt.jsフレームワークによる構築はこちら
Nuxt.js入門 [$route.params][layouts]
参照ページ