vue.js
Vuex

vuexで登場する分割代入の説明

今回のJSLoungeは、Vuexの二回目。前回Vuexで動くようにしたtodoアプリに、Actionを導入してサーバと通信して読み書きできるようにしました。
JSLounge「今から始めるVuex - 非同期マスター」ハンズオン - connpass

個人的にJSON-serverを使ったのがはじめてだったので:open_mouth:でした。一人でやってるとどうしても分野が偏るので、ときどき外部の刺激入れるの大事。

さて、今回学んだこと。分割代入について。

vuexのアクションに登場する謎コード

vuexでアクションを導入しようとすると、こういうコードが出てきます(アクション · Vuex)

actions: {
  increment ({ commit }) {
    commit('increment')
  }
}

なにこの気持ちの悪い引数:fearful:

公式の説明によると、「コードを少しシンプルにするために ES2015 の引数分割束縛(argument destructuring)がよく使われます」とのこと。

本来はこういうコードらしく。

  actions: {
    increment (context) {
      context.commit('increment')
    }
  }

「アクションハンドラはストアインスタンスのメソッドやプロパティのセットと同じものを呼び出せるコンテキストオブジェクトを受け取ります。したがって context.commit を呼び出すことでミューテーションをコミットできます。」ということになっている。

つまり、vuexでアクションを書く場合は必ず最初の引数がcontextになる。

コードを見比べると、 { commit } という謎の儀式によりcontext.commit('increment')commit('increment')と書けるようになるということらしいのだけれど...引数分割束縛?

引数分割束縛

 MDNでは、分割代入と説明されていて、こっちのほうが断然分かりやすかった。

var a, b;
[a, b] = [1, 2]
console.log(a) // 1
console.log(b) // 2

左辺に複数の変数を書いて、まとめて代入ができるよということのようです。rubyだと多重代入と呼ばれているやつですね。

JSの場合、配列だけでなく、オブジェクトも書ける

({a, b} = {a:1, b:2})
console.log(a) // 1
console.log(b) // 2

vuexにおける分割代入

さて、謎のコードに戻ります。

actions: {
  increment ({ commit }) {
    commit('increment')
  }
}

謎の{ commit } 部分に、分割代入のテクニックを適用してみる。最初の引数はcontextが渡されるのだから、{ commit }がcontextと等しい、つまり

({ commit } = context)

というコードを想像すればよいはず。

({a} = {a:1})

だと、{a:1} というオブジェクトから a部分を取り出して a = 1 になっていたから、{ commit } = contextだと、contextオブジェクトからcommitを取り出して、 commit = context.commit になる。

その結果、

actions: {
  increment ({ commit }) {
    commit('increment')
  }
}

のcommitはcontext.commitを呼び出すことができる。おお、なるほど。