Vuexの使い方 [Rails]
Vue.jsの「Vuex」(状態管理ライブラリ)を使用するとstate(状態)が管理できるので親、子、兄弟のコンポーネント間でデータを共有、参照可能です。
作るもの
親コンポーネント 0
子コンポーネント 0
1. プロジェクトの作成
cd ~/ mkdir myapp cd myapp rails new . --webpack=vue --skip-turbolinks --skip-action-mailer --skip-action-mailbox --skip-active-storage --skip-test -d mysql
2. Vuexのインストール
yarn add vuex
3. コントローラー/ビューの作成
bin/rails g controller pages index
4. Vue.js関連のファイル
ファイル構成
app/javascript/app.vue app/javascript/child.vue app/javascript/store.js app/javascript/packs/hello_vue.js
app/javascript/app.vue
<template> <div> <p>{{ msg }} <span>{{ count }}</span></p> <MyChild msg="子コンポーネント"/> <input type="button" value=" + " v-on:click="increment" /> <input type="button" value=" - " v-on:click="decrement" /> </div> </template> <script> import MyChild from 'child.vue' export default { data: function () { return { msg: "親コンポーネント" } }, components: { // 子コンポーネント MyChild }, computed: { // ゲッターの呼び出し count(){ return this.$store.getters['getCount']; } }, methods: { // ディスパッチ(アクションを呼ぶ) increment() { this.$store.dispatch('countAction', 1); }, // ディスパッチ(アクションを呼ぶ) decrement() { this.$store.dispatch('countAction', -1); } } } </script> <style scoped> </style>
app/javascript/child.vue
<template> <p>{{ msg }} <span>{{ count }}</span></p> </template> <script> export default { props: ['msg'], computed: { // ゲッターの呼び出し count(){ return this.$store.getters['getCount']; } } } </script> <style scoped> </style>
app/javascript/store.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ // 共有するデータ state: { count: 0 }, // ミューテーション // ※stateのデータ変更はミューテーションが行う mutations: { setCount(state, payload) { state.count = state.count + payload; } }, // ゲッター getters: { getCount(state) { return state.count; } }, // アクション actions: { countAction(context, payload) { context.commit('setCount', payload); } } })
app/javascript/packs/hello_vue.js
import Vue from 'vue' import App from '../app.vue' import store from '../store' document.addEventListener('DOMContentLoaded', () => { const app = new Vue({ store: store, render: h => h(App) }).$mount() document.getElementById('root').appendChild(app.$el) })
5. Rails関連のファイル
app/views/layouts/application.html.erb
<!DOCTYPE html> <html> <head> <title>Myapp</title> <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag 'application', media: 'all' %> <%= javascript_pack_tag 'application' %> <%= javascript_pack_tag 'hello_vue' %> </head> <body> <%= yield %> </body> </html>
app/views/pages/index.html.erb
<div id="root"></div>
config/database.yml
database、username、passwordを設定する。未設定でログインできない場合は「Access denied for user 'root'@'localhost' (using password: NO)」のエラーとなる。
config/routes.rb
Rails.application.routes.draw do get 'pages/index' root to: 'pages#index' end
6. 実行する
7. 解説
stateについて
stateのデータ変更はミューテーション(mutation)が行います。ミューテーションは同期処理で実行する必要があるので、一般的にアクション経由でミューテーションを呼び出します。
以下は、stateのデータを変更する流れです。
コンポーネント、ディスパッチ、アクション、ミューテーションとなります。
ヘルパー関数
ヘルパー関数にはmapState、mapGetters、mapMutations、mapActionsがあります。これらはVuexに慣れた方が「コードの簡素化」の為に使用します。詳細は公式サイトをご確認ください。
Vuexストアの分割
Vuexストア(store.js)は複数のモジュール(modules)に分割する事が可能です。その際は名前の衝突を防ぐために「namespaced: true」にします。詳細は公式サイトをご確認ください。
参考URL
API リファレンス (Vuex公式)