サーチ…


前書き

Vuexは、Vue.jsアプリケーション用の状態管理パターン+ライブラリです。これは、アプリケーション内のすべてのコンポーネントの集中ストアとして機能し、ステートを予測可能な方法でのみ変更できるようにするルールを備えています。また、Vueの公式の開発ツール拡張機能と統合され、ゼロ設定のタイムトラベルデバッグや状態スナップショットのエクスポート/インポートなどの高度な機能を提供します。

Vuexとは何ですか?

VuexはVue.jsの公式プラグインで、アプリケーション内で使用するための集中データストアを提供します。単方向のデータフローを特徴とするFluxアプリケーションアーキテクチャの影響を強く受け、アプリケーションの設計と推論がより簡単になります。

Vuexアプリケーション内では、データストアはすべての共有アプリケーション状態を保持します 。この状態は、 ディスパッチャを介して突然変異イベントを呼び出すアクションに応答して実行される突然変異によって変更される。

Vuexアプリケーションのデータフローの例を下図に示します。 Vuexアプリケーションアーキテクチャもともと公式のVuex GitHubレポからのMITライセンスで使用されているダイアグラム。

個々のVue.jsアプリケーションコンポーネントは、目的のデータの読み取り専用コピーを返す純粋な関数であるゲッターを介してデータを取得するためにストアオブジェクトにアクセスできます。

コンポーネントは、コンポーネント自身のデータコピーの変更を実行し、 ディスパッチャを使用して突然変異イベントをディスパッチする機能であるアクションを持つことができます。このイベントは、必要に応じて状態を更新するデータストアによって処理されます。

すべてのコンポーネントはゲッターを介して店舗に反応的にバインドされているため、変更はアプリケーション全体に自動的に反映されます。


vueプロジェクトにおけるvuexの使用

const state = {
    lastClickTime: null
}

const mutations = {
    updateLastClickTime: (state, payload) => {
      state.lastClickTime = payload
  }
}

const getters = {
  getLastClickTime: state => {
    return new Date(state.lastClickTime)
  }
}

const actions = {
    syncUpdateTime: ({ commit }, payload) => {
    commit("updateLastClickTime", payload)
  },
  asyncUpdateTime: ({ commit }, payload) => {
    setTimeout(() => {
      commit("updateLastClickTime", payload)
    }, Math.random() * 5000)
  }
}

const store = new Vuex.Store({
  state,
  getters,
  mutations,
  actions
})

const { mapActions, mapGetters } = Vuex;

// Vue 
const vm = new Vue({
    el: '#container',
  store,
  computed: {
      ...mapGetters([
        'getLastClickTime'
    ])
  },
  methods: {
      ...mapActions([
        'syncUpdateTime',
      'asyncUpdateTime'
    ]),
    updateTimeSyncTest () {
        this.syncUpdateTime(Date.now())
    },
    updateTimeAsyncTest () {
        this.asyncUpdateTime(Date.now())
    }
  }
})

そして同じもののHTMLテンプレート:

<div id="container">
  <p>{{ getLastClickTime || "No time selected yet" }}</p>
  <button @click="updateTimeSyncTest">Sync Action test</button>
  <button @click="updateTimeAsyncTest">Async Action test</button>
</div>
  1. ここで、 状態が nullのように初期化lastClickTimeプロパティが含まれています。デフォルト値のこの設定アップは、 反応性の特性を維持することが重要です。 状態で言及されていないプロパティは利用可能ですが、その後の変更はゲッターを使用してアクセスできなくなります

  2. 使用されるゲッターは、突然変異がstateプロパティの値を更新するたびに更新される計算されたプロパティを提供します。

  3. 突然変異だけが状態とその性質を変えることが許されている、つまり、それは同調的にしか行いませ

  4. アクションは、非同期更新の場合に使用できます。ここでは、APIコール(ここでは無作為にタイムアウトしたsetTimeoutによって模倣されます)をアクション内で作成し、応答を取得した後に突然変異をコミットして状態を変更します。

なぜVuexを使うのですか?

通常は多くの再利用可能なコンポーネントで構成されているシングルページアプリケーション(SPA)などの大規模なアプリケーションを構築する場合、迅速に構築および保守が難しくなります。これらのコンポーネント間でのデータと状態の共有も迅速に破壊され、デバッグやメンテナンスが難しくなります。

集中化されたアプリケーション・データ・ストアを使用することにより、アプリケーションの状態全体を1か所に表現して、アプリケーションをより組織化することができます。単方向のデータフロー、突然変異の使用、および必要なデータのみへのコンポーネントデータアクセスのスコープによって、コンポーネントの役割とアプリケーションの状態にどのように影響を及ぼすかについて、より簡単に判断することができます。

VueJSコンポーネントは別々のエンティティであり、互いにデータを簡単に共有することはできません。 vuexを使用せずにデータを共有するには、データでイベントを発生on 、そのイベントをon捕捉して捕捉emit必要があります。

コンポーネント1

this.$emit('eventWithDataObject', dataObject)

コンポーネント2

this.$on('eventWithDataObject', function (dataObject) {
    console.log(dataObject)
})

vuexがインストールされていると、イベントを聴く必要なく、どのコンポーネントからでも簡単にデータにアクセスできます。

this.$store.state.myData

また、 ミューテータと同期してデータを変更したり、非同期アクションを使用したりゲッター関数でデータを取得することもできます。

ゲッター関数は、グローバルに計算された関数として機能します。私たちはコンポーネントからアクセスできます:

this.$store.getters.myGetter

アクションはグローバルな方法です。我々はコンポーネントからそれらをディスパッチすることができます:

this.$store.dispatch('myAction', myDataObject)

そして、突然変異はvuexのデータを変更する唯一の方法です。私たちは変更をコミットできます:

this.$store.commit('myMutation', myDataObject)

Vuexコードは次のようになります

state: {
  myData: {
    key: 'val'
  }
},
getters: {
  myGetter: state => {
     return state.myData.key.length
  }
},
actions: {
  myAction ({ commit }, myDataObject) {
    setTimeout(() => {
      commit('myMutation', myDataObject)
    }, 2000)
  }
},
mutations: {
  myMutation (state, myDataObject) {
    state.myData = myDataObject
  }
}

Vuexのインストール方法は?

Vuexを使用する大部分の時間は、単一のファイルを使用している場合、Vueifyと組み合わせてWebpackやBrowserifyなどのモジュール・バンドラを使用する可能性のある、より大きなコンポーネントベースのアプリケーションになります。

この場合、Vuexを入手する最も簡単な方法はNPMからです。以下のコマンドを実行してVuexをインストールし、アプリケーションの依存関係に保存します。

 npm install --save vuex

require('vue')ステートメントの後に次の行を挿入して、Vue設定とリンクVuexをロードするようにしてください。

Vue.use(require('vuex'))

VuexはCDNでも入手できます。 cdnjsから最新バージョンを入手することができます

自動拒否通知

この例では、vuexモジュールが動的に登録され、自動的に却下されるカスタム通知を格納します

notifications.js

vuexストアを解決し、いくつかの定数を定義する

//Vuex store previously configured on other side
import _store from 'path/to/store';

//Notification default duration in milliseconds
const defaultDuration = 8000;

//Valid mutation names
const NOTIFICATION_ADDED = 'NOTIFICATION_ADDED';
const NOTIFICATION_DISMISSED = 'NOTIFICATION_DISMISSED';

モジュールの初期状態を設定する

const state = {
  Notifications: []
}

私たちのモジュールgettersを設定する

const getters = {
  //All notifications, we are returning only the raw notification objects
  Notifications: state => state.Notifications.map(n => n.Raw)
}

モジュールのアクションを設定する

const actions = {
  //On actions we receive a context object which exposes the 
  //same set of methods/properties on the store instance
  //{commit} is a shorthand for context.commit, this is an 
  //ES2015 feature called argument destructuring
  Add({ commit }, notification) {
    //Get notification duration or use default duration
    let duration = notification.duration || defaultDuration

    //Create a timeout to dismiss notification
    var timeOut = setTimeout(function () {
      //On timeout mutate state to dismiss notification
      commit(NOTIFICATION_DISMISSED, notification);
    }, duration);

    //Mutate state to add new notification, we create a new object 
    //for save original raw notification object and timeout reference
    commit(NOTIFICATION_ADDED, {
      Raw: notification,
      TimeOut: timeOut
    })
  },
  //Here we are using context object directly
  Dismiss(context, notification) {
    //Just pass payload
    context.commit(NOTIFICATION_DISMISSED, notification);
  }
}

モジュールの突然変異を設定する

const mutations = {
  //On mutations we receive current state and a payload
  [NOTIFICATION_ADDED](state, notification) {
    state.Notifications.push(notification);
  },
  //remember, current state and payload
  [NOTIFICATION_DISMISSED](state, rawNotification) {
    var i = state.Notifications.map(n => n.Raw).indexOf(rawNotification);
    if (i == -1) {
      return;
    }

    clearTimeout(state.Notifications[i].TimeOut);
    state.Notifications.splice(i, 1);
  }
}

定義された状態、ゲッター、アクション、および突然変異を含むモジュールを登録する

_store.registerModule('notifications', {
  state,
  getters,
  actions,
  mutations
});

使用法

componentA.vue

このコンポーネントは、すべての通知を画面の右上隅にブートストラップのアラートとして表示し、手動で各通知を却下することもできます。

<template>
<transition-group name="notification-list" tag="div" class="top-right">
  <div v-for="alert in alerts" v-bind:key="alert" class="notification alert alert-dismissible" v-bind:class="'alert-'+alert.type">
    <button v-on:click="dismiss(alert)" type="button" class="close" aria-label="Close"><span aria-hidden="true">&times;</span></button>
    <div>
      <div>
        <strong>{{alert.title}}</strong>
      </div>
      <div>
        {{alert.text}}
      </div>
    </div>
  </div>
</transition-group>
</template>

<script>
export default {
  name: 'arc-notifications',
  computed: {
    alerts() {
      //Get all notifications from store
      return this.$store.getters.Notifications;
    }
  },
  methods: {
    //Manually dismiss a notification
    dismiss(alert) {
      this.$store.dispatch('Dismiss', alert);
    }
  }
}
</script>
<style lang="scss" scoped>
$margin: 15px;

.top-right {
    top: $margin;
    right: $margin;
    left: auto;
    width: 300px;
    //height: 600px;
    position: absolute;
    opacity: 0.95;
    z-index: 100;
    display: flex;
    flex-wrap: wrap;
    //background-color: red;
}
.notification {
    transition: all 0.8s;
    display: flex;
    width: 100%;
    position: relative;
    margin-bottom: 10px;
    .close {
        position: absolute;
        right: 10px;
        top: 5px;
    }

    > div {
        position: relative;
        display: inline;
    }
}
.notification:last-child {
    margin-bottom: 0;
}
.notification-list-enter,
.notification-list-leave-active {
    opacity: 0;
    transform: translateX(-90px);
}
.notification-list-leave-active {
    position: absolute;
}
</style>

他のコンポーネントに通知を追加するスニペット

//payload could be anything, this example content matches with componentA.vue 
this.$store.dispatch('Add', {
  title = 'Hello',
  text = 'World',
  type = 'info',
  duration = 15000
});


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow