2017-12-19 11 views
1

Ich versuche zu erreichen, was eine grundlegende Aufgabe mit Vuex sein sollte, aber aus irgendeinem Grund funktioniert es nicht, und nach weit und breit suchen, schätze ich jede Hilfe.Vue2 + Vuex Commit Nicht Commit (ohne Vue Devtools)

Was ich versuche zu tun: mit einer neuen Eigenschaft (Objekt)

aktualisiert eine Liste (Objekt) von Objekten in meinem Speicher.

Was falsch läuft:

Bevor ich die Aktion Versand sind das neue Objekt aus meiner Komponente (ich Zugriff auf die Aktion über mapActions), bestimmte Eigenschaften in allen vorhandenen Objekten in der Liste zu begehen aktualisiert mit den Werten, die an die Eingaben/v-Modelle in meiner Komponente gebunden sind. Wie mein Code unten zeigt, weiß, dass ich mit Objekten Reaktivität ist ein Thema, also verwende ich Vue.set(...) pro Docs (Mutations Follow Vue's Reactivity Rules)

Warum glaube ich nicht, dass ich etwas ganz dumm ... mach (aber bin wahrscheinlich falsch)

Wenn ich die Mutation in DevTools überprüfen, wird die Mutation wie erwartet protokolliert, und wenn ich "Commit"/"Commit All" drücke, reagieren die vorhandenen Objekte in meiner Liste nicht mehr auf Änderungen in die Eingänge. Dies ist offensichtlich das Verhalten, das ich erwarte, wenn man bedenkt, dass die Aktion die Änderung des Staates buchstäblich begehen soll. Warum funktioniert es nicht innerhalb des Codes und nur innerhalb der Devtools?

Ich entschuldige mich noch einmal für das, was ist wahrscheinlich eine grundlegende Frage, aber ich habe ein paar andere mit einem ähnlichen Problem und keine schriftliche Erklärung gesehen, was uns fehlt ...

Initial

const state = { 
    quotes: {} 
} 

Mutation

mutations: { 
    [types.ADD_QUOTE] (state, payload) { 
    Vue.set(state.quotes, payload.id, payload) 
    } 
} 

Aktion

actions: { 
    addQuote ({ commit }, payload) { 
    commit(types.ADD_QUOTE, payload) 
    }  
} 

Komponente

<template> 
    <div class="quote-block"> 
    <label>price</label> 
    <input type="text" v-model="quote.price"> 
    <label>id</label> 
    <input type="text" v-model="quote.id"> 
    <!-- Just displaying props below --> 
    <div>{{ quote.item }}</div> 
    <div>{{ quote.vendor }}</div> 
    <div>Qty: {{ quote.qty }}</div> 
    <button @click="addQuote(quote)">Submit quote</button> 
    </div> 
</template> 

<script> 
import { mapActions } from 'vuex' 

export default { 
    props: { 
    vendor: String, 
    item: String, 
    qty: Number 
    }, 
    data() { 
    return { 
     quote: { 
     id: '', 
     price: '', 
     timestamp: Date.now(), 
     vendor: this.vendor, 
     item: this.item, 
     qty: this.qty 
     } 
    } 
    }, 
    methods: { 
    ...mapActions([ 
     'addQuote' 
    ]) 
    } 
    } 

Zusammengefasst innerhalb der devtools, ich sehe Werte für id und price innerhalb von Objekten zu ändern, die ich state.quotes gesetzt - sie sind offenbar gebunden zu den V-Modellen für quote.price und quote.id innerhalb meiner Komponente. Nur wenn ich in Devtools "Commit All" setze, ändern sich die Eigenschaften dieser Objekte nicht mehr. Warum ist die commit Methode nicht innerhalb der Aktion, die diese Commits macht?

+0

Hier ist eine verwandte Frage, die nicht das gleiche zugrunde liegende Problem zu teilen schien: https://stackoverflow.com/questions/42294030/vuex-comit-does-not-commit-to-store?rq=1 – pandycircus

+0

Der Code hier sieht alles gut aus. Allerdings verstehe ich nicht, was schief geht. scheint es in einer anderen Komponente zu geschehen? Was wird mit was aktualisiert? – dube

+1

Danke @dube! Ich habe nur eine Zusammenfassung eingefügt, bevor ich deinen Kommentar bemerkt habe. Die kürzeste Antwort ist, dass sich der Status basierend auf dem Wert in den Eingaben der Komponente ändert. Nur "Commit All" innerhalb der Devtools scheint den Staat zu "verriegeln". – pandycircus

Antwort

0

Sie fielen in die Objektreferenz Falle. Das Zitat ist ein Objekt, das als Payload an die Aktion übergeben wird. Wenn Sie diese Nutzlast festschreiben, sichert sie die Referenz in Ihrem Zustand.

Jetzt zeigen sowohl die Komponente als auch der Speicher auf das gleiche Objekt.

Die Lösung ist die Eingabe in ein neues Objekt, entweder mit der Verbreitung Betreibern oder Object.assign

Sein im Allgemeinen eine gute Praxis immer kopieren Sie die Nutzlast in Mutatoren zu kopieren (wenn es ein Objekt)

function(state, payload){ 
    Vue.set(state.quotes, payload.id, {... payload }); 
} 
+0

Ich verstehe jetzt - danke! Also werde ich auch die Devtools-Dokumentation durchgehen, aber es ist sicher anzunehmen, dass der einzige Grund, warum sie die Mutation ohne den Spread-Operator gehandhabt hat, darin besteht, eine Momentaufnahme des Zustands zu machen, um "Zeitreisen" zu ermöglichen. – pandycircus

+0

Ich denke schon, ja. Der strikte Modus (nur für die Entwicklung!) Würde eine Ausnahme auslösen, wenn dies geschieht. Siehe Dokumentation, (Entschuldigung, ich kann sie nicht in der Telefon-App verlinken) – dube