ホーム > カテゴリ > Ruby・Ruby on Rails >

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. 実行する

http://localhost:3000/

7. 解説

stateについて

stateのデータ変更はミューテーション(mutation)が行います。ミューテーションは同期処理で実行する必要があるので、一般的にアクション経由でミューテーションを呼び出します。

以下は、stateのデータを変更する流れです。

コンポーネント、ディスパッチ、アクション、ミューテーションとなります。

ヘルパー関数

ヘルパー関数にはmapState、mapGetters、mapMutations、mapActionsがあります。これらはVuexに慣れた方が「コードの簡素化」の為に使用します。詳細は公式サイトをご確認ください。

Vuexストアの分割

Vuexストア(store.js)は複数のモジュール(modules)に分割する事が可能です。その際は名前の衝突を防ぐために「namespaced: true」にします。詳細は公式サイトをご確認ください。

参考URL

API リファレンス (Vuex公式)





関連記事



公開日:2020年06月23日 最終更新日:2020年06月24日
記事NO:02834