web-dev-qa-db-ja.com

Vuex 2.0ディスパッチとコミット

ディスパッチを使用するか、コミットを使用するかを誰かが説明できますか?

コミットが変異を引き起こし、ディスパッチがアクションを引き起こすことを理解しています。

ただし、ディスパッチはアクションの一種でもありませんか?

38
imchingy

あなたが正しく言ったように、$dispatchはアクションをトリガーし、commitは突然変異をトリガーします。これらの概念の使用方法は次のとおりです。

ルート/コンポーネントのメソッドから常に$dispatchを使用します。 $dispatchは、アクションを実行するためにメッセージをvuexストアに送信します。フロントエンドのパフォーマンスに影響を与えないように、アクションはcurrent tickの後にいつでも実行できます。

コンポーネント/ルートのいずれからもcommitすることはありません。アクション内からonly、コミットするデータがある場合はonlyが行われます。理由:コミットはsynchronousで、完了するまでフロントエンドをフリーズする可能性があります。

このケースを考えてみましょう:サーバーからjsonデータを取得する必要がある場合。この場合、ユーザーインターフェイスが応答しない/しばらくフリーズしないように、これを非同期で行う必要があります。そのため、単にアクションを$dispatchし、後で実行されることを期待します。アクションがこのタスクを引き受け、サーバーからデータをロードし、後で状態を更新します。

アクションがいつ終了するかを知り、それまでajaxスピナーを表示できるようにする必要がある場合は、以下で説明するようにPromiseを返すことができます(例:現在のユーザーを読み込む)。

「loadCurrentUser」アクションを定義する方法は次のとおりです。

actions: {
    loadCurrentUser(context) {
        // Return a promise so that calling method may show an AJAX spinner gif till this is done
        return new Promise((resolve, reject) => {
            // Load data from server
            // Note: you cannot commit here, the data is not available yet
            this.$http.get("/api/current-user").then(response => {
                // The data is available now. Finally we can commit something
                context.commit("saveCurrentUser", response.body)  // ref: vue-resource docs
                // Now resolve the promise
                resolve()
            }, response => {
                // error in loading data
                reject()
            })
        })
    },
    // More actions
}

ミューテーションハンドラーでは、アクションから発生するすべてのコミットを実行します。 「saveCurrentUser」コミットを定義する方法は次のとおりです。

mutations: {
    saveCurrentUser(state, data) {
        Vue.set(state, "currentUser", data)
    },
    // More commit-handlers (mutations)
}

コンポーネントでcreatedまたはmountedの場合、次のようにアクションを呼び出すだけです。

mounted: function() {
    // This component just got created. Lets fetch some data here using an action
    // TODO: show ajax spinner before dispatching this action
    this.$store.dispatch("loadCurrentUser").then(response => {
        console.log("Got some data, now lets show something in this component")
        // TODO: stop the ajax spinner, loading is done at this point.
    }, error => {
        console.error("Got nothing from server. Prompt user to check internet connection and try again")
    })
}

上記のようにPromiseを返すことは完全にオプションであり、誰もが好まない設計上の決定です。 Promiseを返すかどうかの詳細な議論については、この回答の下のコメントを読むことができます。 https://stackoverflow.com/a/40167499/654825

94
Mani