Ich habe einen Vuex- Shop wie folgt:
import spreeApi from '../../gateways/spree-api'
// initial state
const state = {
products: [],
categories: []
}
// mutations
const mutations = {
SET_PRODUCTS: (state, response) => {
state.products = response.data.products
commit('SET_CATEGORIES')
},
SET_CATEGORIES: (state) => {
state.categories = state.products.map(function(product) { return product.category})
}
}
const actions = {
FETCH_PRODUCTS: (state, filters) => {
return spreeApi.get('products').then(response => state.commit('SET_PRODUCTS', response))
}
}
export default {
state,
mutations,
actions
}
Ich möchte Mutation aufrufen: SET_CATEGORIES
von Mutation : SET_PRODUCTS
, Aber das gibt mir Fehler:
projectFilter.js: 22 Nicht gefangen (im Versprechen) ReferenceError: Commit ist nicht definiert (…)
Was sollte der richtige Weg sein, um dies zu tun. Ich habe es versucht store.commit
und this.commit
, aber diese gaben auch ähnliche Fehler.
javascript
vue.js
vuex
Saurabh
quelle
quelle
Antworten:
Wenn Sie bereits eine Mutation durchführen, gibt es keine Möglichkeit zu einer
commit
anderen Mutation. Eine Mutation ist ein synchroner Aufruf, der den Status ändert. Innerhalb einer Mutation können Sie keine weitere Mutation festlegen.Hier ist die API-Referenz für Vuex: https://vuex.vuejs.org/en/api.html
Wie Sie sehen können, erhält ein Mutationshandler nur
state
undpayload
nichts weiter. Deshalb bekommen Siecommit
alsundefined
.In Ihrem obigen Fall können Sie PRODUKT und KATEGORIEN als Teil desselben Mutationshandlers als einzelnes Commit festlegen. Sie können versuchen, ob der folgende Code funktioniert:
// mutations const mutations = { SET_PRODUCTS_AND_CATEGORIES: (state, response) => { state.products = response.data.products state.categories = state.products.map(function(product) { return product.category}) }, // ... }
BEARBEITEN: Bitte beziehen Sie sich auf die Antwort von Daniel S. Deboer . Die richtige Methode besteht darin, zwei Mutationen aus einer einzigen Aktion zu begehen, wie in seiner Antwort beschrieben.
quelle
Wenn Sie unbedingt zwei Mutationen begehen müssen, warum nicht aus einer Aktion heraus? Aktionen müssen keine asynchronen Vorgänge ausführen. Sie können die Festschreibungsmethode in Ihrer Aktion genauso zerstören wie mit dem Status wie folgt:
commitTwoThings: ({commit}, payload) => { commit('MUTATION_1', payload.thing) commit('MUTATION_2', payload.otherThing) }
quelle
Für die Aufzeichnung. Um andere Mutationen aus einer Mutationsmethode aufzurufen, gehen Sie folgendermaßen vor:
const mutations = { mutationOne(state, payload){ this.commit("mutationTwo", payload) }, mutationTwo(state, payload){ console.log("called from another mutation", payload) } }
quelle
action
. Ich habe es getestet und es scheint gut zu funktionieren. Ich denke, diese Antwort sollte stattdessen oben stehen. Diese Lösung wurde bereits in Vuex Github besprochen. Bitte fügen Sie die Möglichkeit hinzu, eine Mutation aus einer anderen Mutation # 907 aufzurufen, wenn jemand mehr Beweise lesen möchte .modules
Namespace haben, obwohl Sie sich unter derselben Datei befinden, müssen Siethis.commit('modulesName/mutationName')
nur für den Fall darauf zugreifen, wenn sich jemand wundert. Wenn Sie weitere Informationen benötigen, ist es immer eine gute Erinnerung, nurconsole.log(this)
innerhalb der Mutation zu arbeiten. Es scheint, dass sie dieselbe Instanz enthält wieVue
, auf die Sie auch$route
von dort aus zugreifen können.Um Code zwischen Mutationen zu teilen, müssen Sie eine neue Funktion erstellen, die die Arbeit ausführt und die Sie dann wiederverwenden können. Glücklicherweise sind Mutationen nur alte Funktionen, und wir können den
state
Parameter nach Belieben weitergeben, so dass dies recht einfach ist.Zum Beispiel:
const mutations = { SET_PRODUCTS: (state, response) => { state.products = response.data.products setCategories(state) }, SET_CATEGORIES: (state) => { setCategories(state) } } function setCategories(state) { state.categories = state.products.map(product => product.category) }
quelle
setCategories
innerhalb einer Mutation anrufen , ist dies in Ordnung.Und wenn ich einen gemeinsamen Code habe, der den Status zwischen mehreren Mutationen beeinflusst, muss ich für alle meine Mutationen denselben Code duplizieren? Oder gibt es einen besseren Weg, das zu tun?
quelle
Wenn Sie die Vuex-Dokumentation zu Aktionen lesen , ist klar, wofür sie gemacht sind.
Aktionen können ( müssen nicht ) asynchronen Code enthalten. In der Tat ist das folgende Beispiel richtig
increment (context) { context.commit('increment') }
Ich sehe kein Problem darin, Aktionen zum Durchführen mehrerer Mutationen zu verwenden.
quelle
In Ihrem Fall sollten Sie nur eine Mutation in Betracht ziehen, nämlich SET_PRODUCTS.
// mutations const mutations = { SET_PRODUCTS: (state, response) => { state.products = response.data.products state.categories = state.products.map(function(product) { return product.category}) } }
Sie sollten SET_CATEGORIES niemals separat aufrufen müssen. Denk darüber nach! Kategorien können nur mutieren, wenn Produkte geändert werden. Und Produkte können sich nur über SET_PRODUCTS ändern.
quelle
Bearbeiten: Ich bin auf ein sehr ähnliches Problem gestoßen und die Lösung für mich bestand darin, einen vuex getter zu verwenden: https://vuex.vuejs.org/en/getters.html
Ihre Kategorien sind tatsächlich eine "berechnete" Version Ihrer Produkte. Wenn Sie Kategorien als Getter haben, können Sie sie mit Produkten synchronisieren und vermeiden, dass die Daten in Ihrem Geschäft dupliziert werden.
Um die Frage im Titel zu beantworten, lasse ich meine ursprüngliche Antwort.
Eine Alternative zur Daniel Buckmaster-Lösung:
const mutations = { SET_PRODUCTS: (state, response) => { state.products = response.data.products this.SET_CATEGORIES(state) }, SET_CATEGORIES: (state) => { state.categories = state.products.map(product => product.category) } }
Wie Sie sehen, können Sie die Mutation selbst direkt aufrufen. (wie Daniel sagte, es sind schließlich nur einfache Funktionen)
Ich glaube, dass dies eine angemessenere Antwort auf die ursprüngliche Frage ist: Es ist eine tatsächliche Art, Mutationen ohne Codeduplizierung oder zusätzliche Funktionen zusammenzusetzen
quelle
Weisen Sie zunächst einer Variablen die Schaltfläche Vue zu: In main.js:
export const app = new Vue({ router, vuetify, store,....
Importieren Sie dann die Variable "app" in die js-Datei, in der Sie die Mutation definieren: In modules.js:
import { app } from "../../main";
Sie können es jetzt als "app. $ Store.commit" verwenden:
mutations: { [AUTH_SET_TOKEN]: () => { app.$store.commit(USER_SUCCESS, params ); },...
quelle
Ich rufe lieber an als
mutations.SET_CATEGORIES(state)
: - 2 verschiedene Commits aus einer künstlichen Aktion aufzurufen - odercommit()
innerhalb einer Mutation zu tun, da dies das Testen von Einheiten schwieriger macht.const mutations = { SET_PRODUCTS: (state, response) => { state.products = response.data.products mutations.SET_CATEGORIES(state) }, SET_CATEGORIES: (state) => { state.categories = state.products.map(product => product.category) } }
Meiner Meinung nach müssen Sie nicht
SET_CATEGORIES
in der VueToolbox sehen. Die Zeitreise sollte sowieso funktionieren. Bitte korrigiere mich wenn ich falsch liege.quelle
Ich denke
Das Aufrufen einer Mutation von einer anderen Mutation ist eine schlechte Idee, da der Status und die Komponenten schwer zu debuggen sind
const mutations = { mutationOne(state, payload){ this.commit("mutationTwo", payload) }, mutationTwo(state, payload){ console.log("called from another mutation", payload) } }
Sie können jedoch einfache Funktionen schreiben und diese können wiederverwendbar sein
function mysecondfn(state,payload){ { // do your stuff here } const mutations = { mutationOne(state, payload){ mysecondfn(state,payload) }, }
quelle
import spreeApi from '../../gateways/spree-api' // initial state const state = { products: [], categories: [] } // mutations const mutations = { SET_PRODUCTS: (state, {response,commit}) => { // here you destructure the object passed to the mutation to get the response and also the commit function state.products = response.data.products commit('SET_CATEGORIES') // now the commit function is available }, SET_CATEGORIES: (state) => { state.categories = state.products.map(function(product) { return product.category}) } } const actions = { FETCH_PRODUCTS: ({commit}, filters) => { // here you destructure the state to get the commit function return spreeApi.get('products').then(response => commit('SET_PRODUCTS', {response,commit})) // here you pass the commit function through an object to 'SET_PRODUCTS' mutation } } export default { state, mutations, actions }
Dies sollte das Problem beheben. Sie können das Commit aus der Aktion in Ihre Mutation einfügen, damit Sie aus Ihrer Mutation ein Commit durchführen können. Hoffe das hilft
quelle