Vue.js童貞がネコ本読んで得たもの⑤
Vue.js童貞がネコ本読んで得たもの⑤:
本稿はフロントエンド領域から逃げてきたバックエンドエンジニアが追い詰められて0から勉強した軌跡である。詳細は前回をご参照ください^^
みんな大好きMio様の名著「基礎から学ぶ Vue.js」です。
https://www.amazon.co.jp/dp/B07D9BYHMZ
アプリケーション内で唯一無二なデータ管理用の箱とデータ関連の便利機能を提供してくれるプラグインですね。
コンポーネント間でいちいちデータのやり取りを繰り返していても埒が明かないので、データ管理を一元化しようって寸法ですね^^
vuexのインストールをnpmで行う場合は以下を実行します。
ストアとは、前述したデータ管理用の箱ですね。
Vuexはストアで定義したstateがアプリケーション全体で利用されるリアクティブデータで、そのデータのライフサイクルをアクションやミューテーションで構築するようなFluxライクな機能を提供してくれます。
ネコ本にならい、getterもお忘れなく。
まずは、以下の内容で
これで、ストアの作成ができました。
stateに
上記で定義したストアをアプリケーションに登録するには、
これで、ストアがアプリケーションに登録されました。
せっかくストアを登録したので使いましょう。
どこから?コンポーネントからです^^
コンポーネントは、
以下の内容を
はい、これでコンポーネントから登録したストアを利用できましたね^^
ネコ本ではマッピングヘルパーと記載されていますが、正式名称は内容ですね。本稿ではネコ本に習ってそう呼称します。
複数のストアを呼び出すとなると、
マッピングヘルパーを使うと、その冗長な記述を省略することができます。便利なので、普段から使っていきましょう。
挙動は同じですが、マッピングヘルパーを使うと上記のように記述できます。
ちょっとアプリケーションが大きくなると扱うデータの数も多くなりますね。
それを全てVuexで管理しようとすると、ストアがあっという間に肥大化して管理しづらくなります。
モジュールを使って肥大化したストアを分割しましょう。
分割の粒度はデータモデル設計の腕の見せ所ですね^^
まずは試しに
moduleA、moduleB、および呼び出し元の
呼び出し元のコンポーネントは、以下の通りですね。
これで、moduleAとmoduleBをそれぞれコンポーネントから呼び出すことができました^^
Vue Routerとは、SPAを構築するためのVueの拡張ライブラリです。
SPAですよ!SPA!それっぽくなってきました^^
Vue Routerのインストールをnpmで行う場合はvuexと同様に以下を実行します。
ルート定義を
上記で作成したルート定義をアプリケーションに登録します。
ここで追加した2ページ(「/」と「/product/:id」)に対応するコンポーネントを作成しましょう。
これで、簡単なSPAを構築できました^^
ネコ本を一通り舐め回しましたが、これで脱童貞できた気がしない。。。
あと何が必要なんだろう???会社のフロントエンドエンジニアに聞いてみます^^
はじめに
本稿はフロントエンド領域から逃げてきたバックエンドエンジニアが追い詰められて0から勉強した軌跡である。詳細は前回をご参照ください^^
ネコ本とは?
みんな大好きMio様の名著「基礎から学ぶ Vue.js」です。https://www.amazon.co.jp/dp/B07D9BYHMZ
童貞卒業までの道程
- (済)基本
- (済)データバインディング、条件分岐、繰り返し
- (済)ハンドラ、双方向バインディング
- (済)算出プロパティ
- (済)ウォッチャ、フィルタ
- (済)コンポーネント
- (済)VueCLI、単一ファイルコンポーネント
- Vuex
- Vue Router ←今日はここまで
- ???
Vuex
アプリケーション内で唯一無二なデータ管理用の箱とデータ関連の便利機能を提供してくれるプラグインですね。コンポーネント間でいちいちデータのやり取りを繰り返していても埒が明かないので、データ管理を一元化しようって寸法ですね^^
インストール
vuexのインストールをnpmで行う場合は以下を実行します。$ npm install vuex babel-polyfill
ストアの登録
ストアとは、前述したデータ管理用の箱ですね。Vuexはストアで定義したstateがアプリケーション全体で利用されるリアクティブデータで、そのデータのライフサイクルをアクションやミューテーションで構築するようなFluxライクな機能を提供してくれます。
ネコ本にならい、getterもお忘れなく。
まずは、以下の内容で
./src/store.js
を作成しましょう。import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store new Vuex.Store({ // リアクティブなデータを定義する。 state: { message : 'Hello Vue.js' }, // stateで定義したリアクティブデータのアクセッサ。直接stateにもアクセスできるが混乱を防ぐために明示的に記述することが推奨されるケースもある。 getters: { message(state) { return state.message } }, // stateで定義されたリアクティブデータを更新する。主にactionからのみ呼び出される。 mutations: { setMessage(state, payload) { state.message = payload.message } }, // APIの呼び出しや入力チェックなどの前処理を担当する。コンポーネントや他のアクションから呼び出される。 actions: { update({ commit }, message) { commit('setMessage', {message}) } } }) export default store
stateに
message
というリアクティブデータを定義し、適当にライフサイクルに必要な処理を記載していますが、詳しくはインラインのコメントをみてください^^上記で定義したストアをアプリケーションに登録するには、
src/main.js
に以下のよう記述します。import Vue from 'vue' import App from './App' import store from './store.js' // ここを追記 Vue.config.productionTip = false new Vue({ el: '#app', store, // ここも追記 components: { App }, template: '<App/>' })
コンポーネントからストアを利用
せっかくストアを登録したので使いましょう。どこから?コンポーネントからです^^
コンポーネントは、
src/components
配下に配置しましょう。以下の内容を
src/components/EditForm.vue
に記載します。<template> <div class='edit-form'> <input type="text" v-bind:value="message" v-on:input="doUpdate"/> </div> </template> <script> export default { name: 'EditForm', computed: { message() {return this.$store.getters.message} }, methods: { doUpdate(event) { this.$store.dispatch('update', event.target.value) } } } </script>
マッピングヘルパーで一括登録
ネコ本ではマッピングヘルパーと記載されていますが、正式名称は内容ですね。本稿ではネコ本に習ってそう呼称します。複数のストアを呼び出すとなると、
this.$store.
を何度も記述しなければなりませんね。はい、面倒です。マッピングヘルパーを使うと、その冗長な記述を省略することができます。便利なので、普段から使っていきましょう。
<template> <div class='edit-form'> <input type="text" v-bind:value="message" v-on:input="doUpdate"/> </div> </template> <script> import { mapState, mapGetters, mapMutations, mapActions} from 'vuex' export default { name: 'EditForm', computed: { // message() {return this.$store.getters.message} ...mapGetters(['message']) }, methods: { ...mapActions(['update']), doUpdate(event) { //this.$store.dispatch('update', event.target.value) this.update(event.target.value) } } } </script>
ストアの分割
ちょっとアプリケーションが大きくなると扱うデータの数も多くなりますね。それを全てVuexで管理しようとすると、ストアがあっという間に肥大化して管理しづらくなります。
モジュールを使って肥大化したストアを分割しましょう。
分割の粒度はデータモデル設計の腕の見せ所ですね^^
まずは試しに
moduleA
とmoduleB
というファイルを以下のように追加しましょう。${APP_ROOT} └── src ├── App.vue ├── assets │ └── logo.png ├── components │ ├── EditForm.vue │ └── HelloWorld.vue ├── main.js ├── store.js └── stores ←追加 ├── module_a.js ←追加 └── module_b.js ←追加
store.js
の記述は以下の通りです。// ./src/stores/module_a.js export default { namespaced: true, state: { message : 'Hello Vue.js(module_a)' }, getters: { message(state) { return state.message } }, mutations: { setMessage(state, payload) { state.message = payload.message } }, actions: { update({ commit }, message) { commit('setMessage', {message}) } } }
// ./src/stores/module_b.js export default { namespaced: true, state: { message : 'Hello Vue.js(module_b)' }, getters: { message(state) { return state.message } }, mutations: { setMessage(state, payload) { state.message = payload.message } }, actions: { update({ commit }, message) { commit('setMessage', {message}) } } }
// ./src/store.js import Vue from 'vue' import Vuex from 'vuex' import moduleA from '@/stores/module_a.js' import moduleB from '@/stores/module_b.js' Vue.use(Vuex) const store = new Vuex.Store({ modules: { moduleA, moduleB } }) export default store
<template> <div class='edit-form'> <input type="text" v-bind:value="messageA" v-on:input="doUpdateA"/> <input type="text" v-bind:value="messageB" v-on:input="doUpdateB"/> </div> </template> <script> import { mapState, mapGetters, mapMutations, mapActions} from 'vuex' export default { name: 'EditForm', computed: { ...mapGetters({'messageA': 'moduleA/message'}), ...mapGetters({'messageB': 'moduleB/message'}), }, methods: { ...mapActions({'updateA': 'moduleA/update'}), doUpdateA(event) { this.updateA(event.target.value) }, ...mapActions({'updateB': 'moduleB/update'}), doUpdateB(event) { this.updateB(event.target.value) } } } </script>
Vue Router
Vue Routerとは、SPAを構築するためのVueの拡張ライブラリです。SPAですよ!SPA!それっぽくなってきました^^
インストール
Vue Routerのインストールをnpmで行う場合はvuexと同様に以下を実行します。$ npm install vue-router
ルート定義の登録
ルート定義を./src/router.js
というファイルを追加して記載しましょう。// ./src/router.js import Vue from 'vue' import VueRouter from 'vue-router' import Home from '@/pages/Home.vue' import Product from '@/pages/Product.vue' Vue.use(VueRouter) const router = new VueRouter({ routes: [ {name: 'home', path: '/', component: Home}, {name: 'product', path: '/product/:id', component: Product, props: route => ({id: Number(route.params.id)})}, ] }) export default router
// ./src/main.js import Vue from 'vue' import App from './App' import router from './router.js' Vue.config.productionTip = false new Vue({ el: '#app', router, components: { App }, template: '<App/>' })
// ./src/pages/Home.vue <template> <div class="home"> <h1>Home</h1> </div> </template> <script> export default { name: 'Home' } </script>
// ./src/pages/Product.vue <template> <div class="product"> <h1>Product</h1> <p>id : {{id}}</p> </div> </template> <script> export default { name: 'Product', props: {id: Number} } </script>
終わりに
ネコ本を一通り舐め回しましたが、これで脱童貞できた気がしない。。。あと何が必要なんだろう???会社のフロントエンドエンジニアに聞いてみます^^
コメント
コメントを投稿