Vue.js で Vuex をかじりつつ遅延するフォームを作る
状態管理・Vuexを勉強しながらフォームのコンポーネントを作ります。
状態管理って何?Flux?ストア?ディスパッチ?俊足?コーナーで差をつけろ!
ここへ来ると良くかわからない言葉が沢山出てきてつらいです。今までは何も考えずにとりあえず今動けば良いや精神で作っていたのです。
私の場合 Vuex の基本となっている Flux という概念もよく分かっていないためいきなりガッツリしたものを作るのは無理なので徐々に取り入れながら Vue の勉強をしていきたいと思います。多分このページを見ている jQuery 難民のフレンズも同じような感じでここら辺が辛くなってくると思いますが頑張りましょう。
状態管理について
今までいくつかコンポーネントを作ってきましたが、親子関係の場合は props や emit を使い、親子関係じゃない場合はイベントバスという空の Vue インスタンスを使いました。同じデータを参照するコンポーネントが増えたりネストが増えると、一つ上に emit で送信して またその上に emit で送信して…という苦行がもれなく付いてきます。
状態管理で参照先を固定にしておくとこの苦行が楽になるというお話。簡単に言えばどこからでも参照できるデータ state (状態)が入った入れ物(ストア)を1つだけ作って、データが必要な時はそれを参照してね、ただしデータを操作する時はストア専用のルートを通ってね!という感じみたいです。
Vuex について
Vuex でよく見る図です。この類の図を見ると眠くなりますが一個づつ理解していきましょう…。
コンポーネントからディスパッチという命令を送るとアクションに繋がってますね。API 等からデータを受け取ったりするのはこの部分みたいです。アクションの結果をコミットという命令でミューテーションに送ってストアが持っているデータを実際に書き換えるのはミューテーションという事みたいです。うぅん…初めてだととてもややこしい。
Vuex の一番最初の説明にもこう書いてあるのです。
Vuex を導入した場合、冗長で恐ろしいと感じるかもしれません。そう感じることは全く普通です。あなたのアプリがシンプルであれば、Vuex なしで問題ないでしょう。
~ おわり ~
とはいかないんだよなぁ。Vue 同様に Vuex のマニュアルも翻訳されていて知りたいことがしっかり載っていたのでひととおり読むだけでもだいぶ分かってきました。
ステート State
実際の状態(最新のデータ)が入ったもの。ミューテーション以外で直接書き換えてはいけない。
ミューテーション Miutation
ステートを変更させるロジック。非同期処理を含めてはいけない。
コミット Commit
ミューテーションを実行する命令。
アクション Action
非同期処理を行うロジック。API からデータを取得したりなど。
実際ステートを操作する場合はここからミューテーションしなければいけない。
逆に同期処理だけなら直接コミットでもOK。
ディスパッチ Dispatch
アクションを実行する命令。
ゲッター Getter
ステートを取得する際の処理。ストア専用の算出プロパティ的なもの。
これ以外にもいくつかありましたが、まずはこの辺のルールを押さえておけば大丈夫そうです。
遅延するフォームを作ってみる
今日書いて���た「データを遅延して反映させるフォーム」というのを Vuex を使って書き直してみました。カテゴリ→子アイテムリストという2階層のデータを持っていて、カテゴリ編集をする時個別に反映しないで決定ボタンを押したタイミングで反映する動きにしたいと思います。
元々は cmp-editor に編集中のIDを渡す時に親子間ではないので $root.$refs.editor... という書き方をしていたんですが、編集中のIDをストアで管理するようにしました。非同期処理はしてないのでアクションは使っていません。
cmp-editor-item をコンポーネントにしないで cmp-editor のスコープ内に収めるともう少しシンプルになるのですが、基本的にこう言う場合ってもっとごちゃごちゃしてきてコンポーネント化したい!となるはずなのでコンポーネント前提で作っています。
フローチャートはこんな感じです(作るのむずかしい)
編集中IDの更新と決定したカテゴリの状態の更新の2つのミューテーションを作りました。cmp-editor 以下は editid が更新されたタイミングで内部データでクローンを作りその内部データを子の cmp-ediitor-item に渡しています。データは全部ストアで持たないといけないわけでもなく、ローカルデータと織り交ぜながら使うといいより感じになりそうですね(๑'ᴗ'๑)
実際にデータベースにデータを保存したい場合は、最後のコミットの前にアクションを追加してバックエンドが成功したらフロントでも再取得か直接操作のコミットをするという感じになると思います。
オブジェクトマッピング
ステートやゲッターは算出プロパティ、ミューテーションやアクションはメソッドに使用 or 登録して実際に使えるようになるのですが、数が多い場合は mapState や mapMutations というマッピング用オブジェクトを使うとシンプルに書けるようです。
script で簡単に使用する場合は Vuex.mapState() や Vuex.mapMutations() という感じで使えます。
var app = new Vue({
el: '#app',
store,
computed: Vuex.mapState([
'list',
'editid'
]),
methods: Vuex.mapMutations(['updateItems']),
components: { 'cmp-cat': cmpCat, 'cmp-editor': cmpEditor },
})
まとめ
今回は本当少しだけですけどゲッターやミューテーションをかじってみました(•ө•)ノ ステートを参照する場合は単純に返す場合もゲッターを通した方が良いんでしょうか?
次はアクションも使ってきたいなーと思います。