Rails6 + Webpacker環境のVue.js3導入と、Viewからpropsへの受け渡し
環境
※Docker Desktop環境
Vueのインストール
yarn add vue@next vue-loader@next @vue/compiler-sfc
package.json
{ "name": "myapp", "private": true, "dependencies": { "@rails/actioncable": "^6.0.0", "@rails/activestorage": "^6.0.0", "@rails/ujs": "^6.0.0", "@rails/webpacker": "5.4.3", "@vue/compiler-sfc": "^3.2.26", // 追加項目 "turbolinks": "^5.2.0", "vue": "^3.2.26", // 追加項目 "vue-loader": "^17.0.0", // 追加項目 "webpack": "^4.46.0", "webpack-cli": "^3.3.12" }, "version": "0.1.0", "devDependencies": { "webpack-dev-server": "^3" } }
config\webpack\environment.jsの編集
初期状態
const { environment } = require('@rails/webpacker') module.exports = environment
編集後
const { environment } = require('@rails/webpacker') const path = require('path') const { VueLoaderPlugin } = require('vue-loader') const { DefinePlugin } = require('webpack') // アプリケーションのalias const customConfig = { resolve:{ alias: { "@": path.resolve(__dirname, '..', '..', 'app/javascript') } } } environment.plugins.prepend( 'VueLoaderPlugin', new VueLoaderPlugin() ) environment.loaders.prepend('vue', { test: /\.vue$/, use: [{ loader: 'vue-loader' }] }) environment.plugins.prepend( 'Define', new DefinePlugin({ __VUE_OPTIONS_API__: false, __VUE_PROD_DEVTOOLS__: false }) ) environment.config.merge(customConfig) module.exports = environment
config\webpacker.ymlの編集
- extensions: - .vue # 追加
Controller、View、JavaScriptの作成
config\routes.rb
Rails.application.routes.draw do resources :users end
app\controllers\users_controller.rb
class UsersController < ApplicationController def index @users = [{ id: 1, name: 'hoge' }, { id: 2, name: 'fuga' }] end end
app\views\users\index.html.erb
<div id="user" data-users="<%= @users.to_json %>"> <ul> <li v-for="item in items"> {{ item.name }} </li> </ul> </div> <%= javascript_pack_tag('users') %>
app\javascript\packs\users.js
import { createApp } from 'vue/dist/vue.esm-browser' import Index from '@/users/index' document.addEventListener('DOMContentLoaded', () => { // カスタムデータからの値取得と、propsへの受け渡し const { users } = document.getElementById('user').dataset createApp(Index, { users: JSON.parse(users) }).mount('#user') })
app\javascript\users\index.js
export default { props: { users: { type: Array, default: [], } }, data() { return { items: [] } }, mounted() { this.items = Object.assign({}, this.users) } }