LoginSignup
249
225

More than 5 years have passed since last update.

Vuex:mapStateの書き方8パターン+11サンプルコード

Last updated at Posted at 2018-01-07

VuexのmapStateは書き方にバリエーションがある。ここではできるだけ多くのパターンを紹介する。

まず、話を具体的にするために次のようなストアを前提にする。

const profile = {
  namespaced: true,
  state: { twitter: "@suin", facebook: null, text: "よろしく〜" }
};

const user = {
  namespaced: true,
  state: { name: "suin" },
  modules: { profile }
};

const post = {
  namespaced: true,
  state: {
    title: "VuexのmapStateの書き方",
    tags: ["JavaScript", "Vue", "Vuex"]
  }
};

const store = new Store({
  state: { isLoggedIn: true },
  modules: { user, post }
});

従って、ストアのステートは次の図示のようになる。isLoggedInはルート直下のステートで、モジュールではない。userprofilepostはモジュールだ。userprofileはネストした構造にした。

なお、以下で示すサンプルコードの実行はCodePenのVuex: mapState patternsで行った。

mapStateを使う前のおまじない(定型文)

VueコンポーネントでmapStateを使うためには、vuexライブラリからmapStateをインポートする必要がある。コンポーネントの<script>タグのあたまに書いておこう。

<script>
import {mapState} from 'vuex'
...

mapStateの書き方パターン集

:one: 普通のバインド

通常のバインドの書き方。

構文
computed: mapState(["ステートのキー"])
// 複数のステートをバインドすることもできる
computed: mapState(["ステートのキー", "ステートのキー", ...])

:warning: 次のような配列でない使い方はできず、Uncaught TypeError: Cannot convert undefined or null to objectというエラーが発生する。

mapState("ステートのキー") // エラー

isLoggedInをバインドする例

const app = {
  name: "app",
  computed: mapState(["isLoggedIn"]),
  template: `<p>{{isLoggedIn}}</p>`
};
バインドされた状態
isLoggedIn: true

isLoggedInuserをバインドする例

const app = {
  name: "app",
  computed: mapState(["isLoggedIn", "user"]),
  template: `<p>{{isLoggedIn}}{{user}}</p>`
};
バインドされた状態
isLoggedIn: true
user:
  name: "suin"
  profile:
    facebook: null
    text: "よろしく〜"
    twitter: "@suin"

:two: 別名のバインド

ストアのステートを別名でバインドする書き方。

構文
computed: mapState({
  別名: "ステートのキー"
})
// 複数のステートをバインドすることもできる
computed: mapState({
  別名: "ステートのキー",
  別名: "ステートのキー",
  ...
})

isLoggedInisSignedInと呼称しつつバインドする例

const app = {
  name: "app",
  computed: mapState({
    isSignedIn: "isLoggedIn"
  }),
  template: `<p>{{isSignedIn}}</p>`
};
バインドされた状態
isSignedIn: true

:three: モジュール内のステートのバインド

構文
computed: mapState("モジュールのパス", ["モジュール内のステートのキー"])
// モジュール内の複数のステートをバインドすることもできる
computed: mapState("モジュールのパス", ["モジュール内のステートのキー", "モジュール内のステートのキー", ...])

user.profileをバインドする例

const app = {
  name: "app",
  computed: mapState("user", ["profile"]),
  template: `<p>{{profile}}</p>`
};
バインドされた状態
profile:
  facebook:null
  text: "よろしく〜"
  twitter: "@suin"

user.profile.twitterをバインドする例

const app = {
  name: "app",
  computed: mapState("user/profile", ["twitter"]),
  template: `<p>{{twitter}}</p>`
};
バインドされた状態
twitter: "@suin"

user.profile.textuser.profile.twitterをバインドする例

const app = {
  name: "app",
  computed: mapState("user/profile", ["text", "twitter"]),
  template: `<p>{{text}}{{twitter}}</p>`
};
バインドされた状態
text: "よろしく〜"
twitter: "@suin"

:four: 算出プロパティとステートの共存

オブジェクトスプレッド演算子(...)を使う必要がある。

構文
computed: {
  ...mapState(["ルートステートのキー"]),
  算出プロパティ1() { /* ... */ },
  算出プロパティ2() { /* ... */ },
  ...
}

算出プロパティがあるコンポーネントにisLoggedInをバインドする例

const app = {
  name: "app",
  computed: {
    ...mapState(["isLoggedIn"]),
    date() {
      return new Date()
    }
  },
  template: `<p>{{isLoggedIn}} {{date}}</p>`
};
算出プロパティ
date: "2018-01-07T11:11:03.779Z"
バインドされた状態
isLoggedIn: true

:five: 複数モジュールのモジュール内ステートのバインド

オブジェクトスプレッド演算子(...)を使う必要がある。

構文
computed: {
  ...mapState("モジュール名", ["モジュールステートのキー"]),
  ...mapState("モジュール名", ["モジュールステートのキー"]),
  ...
}

user.namepost.titlepost.tagsをバインドする例

const app = {
  name: "app",
  computed: {
    ...mapState("user", ["name"]),
    ...mapState("post", ["title", "tags"])
  },
  template: `<p>{{name}} {{title}} {{tags}}</p>`
};
バインドされた状態
name: "suin"
tags: 
  0: "JavaScript"
  1: "Vue"
  2: "Vuex"
title: "VuexのmapStateの書き方"

:six: モジュール内ステートの別名バインド

構文
computed: mapState("モジュールのパス", {
  別名: "モジュール内のステートのキー"
})

user.nameuserNameと呼称しながらバインドする例

const app = {
  name: "app",
  computed: mapState("user", {
    userName: "name"
  }),
  template: `<p>{{userName}}</p>`
};
バインドされた状態
userName: "suin"

:seven: ステート加工結果のバインド

ステートをそのままバインドするのではなく、ステートを加工した結果をバインドする方法。

構文
computed: mapState({
  加工後の名称: state => 加工処理(state.加工対象のステート名)
})

isLoggedInを加工した結果をisLoggedOutとしてバインドする例

const app = {
  name: "app",
  computed: mapState({
    isLoggedOut: state => !state.isLoggedIn
  }),
  template: `<p>{{isLoggedOut}}</p>`
};
バインドされた状態
isLoggedOut: false

:eight: 複雑なバインド

モジュールをまたいだ複雑なバインドをする方法。

isLoggedInuser.namepost.titleをバインドする例

const app = {
  name: "app",
  computed: mapState({
    isLoggedIn: "isLoggedIn",
    userName: state => state.user.name,
    postTitle: state => state.post.title
  }),
  template: `<p>{{isLoggedIn}} {{userName}} {{postTitle}}</p>`
};
バインドされた状態
isLoggedIn: true
postTitle: "VuexのmapStateの書き方"
userName: "suin"

質疑応答

質問などは、ここにコメントを残すかsuinのプログラミング相談室(チャット)で話しかけてください。どんな些細なものでも構いません。

249
225
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
249
225