vuexでのデータの扱いについて少し困ったので整理
目的
vuexを使っているある程度複雑なvueコンポーネント上で、定数的なものをどう扱っていいか解らなかったので、一旦考えを整理しておきたい。
現状の整理
なぜvuex?
コンポーネントの階層が4つまであって、propsだけで実現しようとすると、rootコンポーネントのpropsを最下層まで渡していくのが面倒だし、挙動や設計を少し変えようとした場合の変更箇所も増えるので大変。
vuexを使うと、storeを共有できるので、最下層のコンポーネントからも直接storeからstateを参照、更新(mutationの実行)ができるので楽。
vuexのデメリット?
コンポーネントが依存する先が増えるので、挙動を理解するのが少し大変になるのと、再利用性は低くなる。
props, data, storeそれぞれの役割を理解して使わないとカオスになる(なった。経験値が必要) 勿論ちゃんと整理して使えばかなり便利。
props, data, store
何に困ったか?
今回作っていたのはがっつりSPAという感じではなく、phpで動いているwebサービスのある一画面をSPA的に実装する形。
なので、
- php側からjsに各値を渡す
- 渡された値をstoreのデフォルト値として設定
という感じ。
php → js に渡したいデータとして、state的なもの以外にphp側では定数として定義されているデータも渡す必要があって、割と大事なデータで色々なコンポーネントから参照される。
window.constants
のように定義すればいけるけど、グローバル変数に依存するのは何か違くない?と思い及び腰に。
storeに突っ込んでおけば、 mapStateでどのコンポーネントからでも必要があれば簡単に参照できるし、依存先もstoreだけになるかあらまあいいか。。と思いそうしたけどなんか違うよな。。と。(じっくり考える余裕がなかった反省)
考察
storeに突っ込むのは何がいけない?
storeはアプリ全体でリアクティブなフローを実現するための仕組みなので、state的なデータを保持するためのものなのでそもそも使い方が間違っている。
storeにconstants的なデータも入れてしまうと、stateとconstantsが入り乱れてしまうので、何が動的に変わる想定のデータで、何がimmutableな定数的なデータとして想定されているものか解らなくなってしまい、コードを読み解くのが困難になってしまう。 (読み解くの難しいコードはどんな状況であれ、避けるべきで良くないもの)
どうすべきだったか?
- constants用のclassを定義する
- 名前をちゃんと付けることで、windowに直接入れ込むより用途が明確になる
- 各プロパティのgetterを定義することで、他にどういったデータがあるか解りやすくなる
- php側から渡されるjsonをloadする関数
loadJson
をexportして、loadしたらfreezeされる- 「phpから渡されるデータをload後にimmutableになる」という設計の意図が解りやすくなる
class HogeConstants { constructor(json) { // json parse .. } get a() { return this.a } get b() { return this.b } } let instance export function loadJson(json) { instance = new HogeConstants(json) Object.freeze(instance) // singleton pattern https://www.sitepoint.com/javascript-design-patterns-singleton/ } export function getHogeConstants() { return instance }
phpとの連携部分のjs部分で、 loadJson
を呼び出しあげて、
あとはこのデータを使いたいコンポーネント側でimportすれば参照できるようになる。
アプリの規模によってはwindowの直接設定しても問題にならないこともある気がする。
あんまりvuexどうたらは関係なく、jsもある程度の規模になったらある程度設計を考えないと、という話?