emahiro/b.log

Drastically Repeat Yourself !!!!

VuexにおけるGettersのメソッドスタイルアクセス

gettersでstateから任意の値を取り出すときにVuexではGettersのプロパティの返り値にfunctionを指定することで、Gettersのプロパティに関数の引数という形で直接値を渡す(アクセスできる)手法があります。これを メソッドスタイルアクセス と言います。

メソッドアクセススタイルについてはVuexの公式のGettersのドキュメントでも記載があります。

ref. ゲッター #メソッドスタイルアクセス | Vuex

サンプルコードは以下のようになります。

Gettersでのプロパティの定義

getters: {
  hogeById: (state) => (id) => {
    // 外部から直に私た変数をidに入れて使うことができる。
  }
}

呼び出す側

store.getters.hogeById(2) 
// or
this.hogeById(2) 
// getters.hogeById 内で使われる id には 2が入る。

typescriptで書き直すと...

定義元

const hogeGetters: GetterTree<HogeState, RootState> = {
    hogeById(state){
        return (id: number) => {
        // id: numberを使った何かしらの処理
    }
}

呼び出す側

this.hogeById(123) 
// hogeById内でのstateを何らかの条件を元にGetするPropertyで id=123 として直に値を扱うことができる。

VueのGettersそれ自体はオブジェクトを作成しています。

const hogeGetters: GetterTree<HogeState, RootState> = {
    hogeById(state) {
        return (id: number) => {
            // idを使った何らかの処理
        }
    }
}

typescriptの例で見るとわかりやすいですが、hogeGettersは {} なのでそれ自体はオブジェクトであり、そのオブジェクトが hogeById という関数(hogeGettersオブジェクトからみたらプロパティ)を持っています。
hogeByIdをはじめとしてgettersの関数には引数としてstate(他にもgettersやrootStateなどVuexの作法に則ったstateやgetters)を渡していますが、呼び出し元では通常stateを明示的に指定しません。これはVuexのGettersではstateを渡さずともどのstateに対して呼ばれたものなのか呼び出したコンテキストから自動的に解釈してくれているからだと思います。

例) HogeというStateをもつ画面においてにthis or store.getters でHoge StateのGettersが呼ばれた場合には必ずHogeをゴニョった結果(state)が得られます。

あるStateのもつGetterの関数が呼ばれた時に、その関数の返り値が関数(function)であると、その関数の引数を呼び出し側から指定した特定の値にstateの引数を通り越して、直でアクセスできるように解釈してくれるみたいです。
この辺、何でそうなるのか時間のある時にもう少し調べてみようと思います。(僕のフロントエンド力で調べられるかわかりませんが...)

このメソッドスタイルアクセス、非常に便利だし、ちょっと見慣れない形でありますが、慣れるととても綺麗にGettersで特定の値を扱えるなと思いました。
ただ、参考文献はVuexの公式ドキュメントくらいしかなく、ググってもあまりヒットしないのでメジャーではないのかもしれません。。。ただ知ってるといいなと思う記法だったの備忘録として記載しました。

Updated at 20190109

上記でメソッドスタイルアクセスがどうして動作するのかの仮説をややこしく記載しましたが、この記法はJSのクロージャーだと捉えると腹落ちしました。

developer.mozilla.org

getters: {
  hogeById: (state) => (id) => {
    // 外部から直に私た変数をidに入れて使うことができる。
  }
}

というgettersのメソッドに対してメソッドスタイルアクセス記法を使ったとすると、hogeByIdメソッドを実行するときは必ず、stateが暗黙的に渡されて、さらにその関数内で作成されたローカル変数 state を保持する scope オブジェクトが作成されます。それは関数の引数として渡された変数とともに初期化されます。
このgettersメソッドにおいては hogeById メソッドが呼ばれる段階で state変数とid変数が初期化されてメソッド内で使えるようになります。

refった JavaScript「再」入門のクロージャーの章にて例に出されている以下のサンプル

function makeAdder(a) {
  return function(b) {
    return a + b;
  };
}

var x = makeAdder(5);
x(6) //11が出力される

これをgettersのhogeByIdと合わせてみると以下のような構造と捉えることができます。 ※ 擬似コードです。

var hogeById = getters(state)  
hogeById(1) // id: 1 で操作されたstateが返ってくる。

厳密な理解としてはまだ正しくないのかもしれませんが、クロージャーの構造としてみるとメソッドスタイルアクセスで指定した引数をstateを通り越してgettersのメソッドに伝播させることができるのか少しだけ理解に近づいた気がしました。