Ich habe die Serie https://laracasts.com/series/learning-vue-step-by-step gestartet . Ich habe die Lektion Vue, Laravel und AJAX mit diesem Fehler abgebrochen :
vue.js: 2574 [Vue warn]: Vermeiden Sie es, eine Requisite direkt zu mutieren, da der Wert bei jedem erneuten Rendern der übergeordneten Komponente überschrieben wird. Verwenden Sie stattdessen Daten oder berechnete Eigenschaften, die auf dem Wert der Requisite basieren. Prop mutiert: "Liste" (in Komponente gefunden)
Ich habe diesen Code in main.js
Vue.component('task', {
template: '#task-template',
props: ['list'],
created() {
this.list = JSON.parse(this.list);
}
});
new Vue({
el: '.container'
})
Ich weiß, dass das Problem in created () liegt, wenn ich die Listen-Requisite überschreibe, aber ich bin ein Neuling in Vue, daher weiß ich überhaupt nicht, wie ich es beheben soll. Hat jemand eine Idee, wie (und bitte erklären Sie warum), um das Problem zu beheben?
quelle
Antworten:
Dies hat damit zu tun, dass die lokale Mutation einer Requisite in Vue 2 als Anti-Pattern angesehen wird
Was Sie jetzt tun sollten, wenn Sie eine Requisite lokal mutieren möchten , ist, ein Feld in Ihrem zu deklarieren
data
, das denprops
Wert als Anfangswert verwendet, und dann die Kopie zu mutieren:Weitere Informationen hierzu finden Sie im offiziellen Leitfaden von Vue.j.
Hinweis 1: Bitte beachten Sie, dass Sie nicht denselben Namen für Ihr
prop
und verwenden solltendata
, dh:Anmerkung 2: Da fühle ich mich gibt es einige Verwirrung in Bezug auf
props
und Reaktivität , empfehle ich Ihnen einen Blick haben auf diesen Threadquelle
Das Vue-Muster ist
props
auf undevents
ab. Es klingt einfach, ist aber beim Schreiben einer benutzerdefinierten Komponente leicht zu vergessen.Ab Vue 2.2.0 können Sie das V-Modell (mit berechneten Eigenschaften ) verwenden. Ich habe festgestellt, dass diese Kombination eine einfache, saubere und konsistente Schnittstelle zwischen Komponenten schafft:
props
an Ihre Komponente übergebenen Daten bleiben reaktiv (dh sie werden weder geklont noch erfordern sie einewatch
Funktion zum Aktualisieren einer lokalen Kopie, wenn Änderungen erkannt werden).Eine berechnete Eigenschaft ermöglicht die getrennte Definition von Setter und Getter. Dadurch kann die
Task
Komponente wie folgt umgeschrieben werden:Die Modelleigenschaft definiert, welcher Funktion zugeordnet
prop
istv-model
und welches Ereignis bei Änderungen ausgegeben wird. Sie können diese Komponente dann vom übergeordneten Element aus wie folgt aufrufen:Die
listLocal
berechnete Eigenschaft bietet eine einfache Getter- und Setter-Schnittstelle innerhalb der Komponente (stellen Sie sich vor, es handelt sich um eine private Variable). Innerhalb können#task-template
Sie rendernlistLocal
und es bleibt reaktiv (dh wennparentList
Änderungen, wird es dieTask
Komponente aktualisieren ). Sie können auch mutieren,listLocal
indem Sie den Setter aufrufen (z. B.this.listLocal = newList
), und die Änderung wird an das übergeordnete Element gesendet.Das Besondere an diesem Muster ist, dass Sie es
listLocal
an eine untergeordnete Komponente vonTask
(usingv-model
) übergeben können und Änderungen von der untergeordneten Komponente an die Komponente der obersten Ebene weitergegeben werden.Angenommen, wir haben eine separate
EditTask
Komponente, um Änderungen an den Aufgabendaten vorzunehmen. Unter Verwendung des gleichenv-model
und berechneten Eigenschaftenmusters können wirlistLocal
an die Komponente übergeben (unter Verwendungv-model
):Wenn
EditTask
aussendet eine Änderung es in geeigneter Weise ruftset()
auflistLocal
und damit propagieren das Ereignis auf die oberste Ebene. In ähnlicher Weise kann dieEditTask
Komponente auch andere untergeordnete Komponenten (z. B. Formularelemente) mit aufrufenv-model
.quelle
Vue warnt Sie nur: Sie ändern die Requisite in der Komponente, aber wenn die übergeordnete Komponente erneut gerendert wird, wird "Liste" überschrieben und Sie verlieren alle Ihre Änderungen. Es ist also gefährlich, dies zu tun.
Verwenden Sie stattdessen die berechnete Eigenschaft wie folgt:
quelle
Wenn Sie Lodash verwenden, können Sie die Requisite klonen, bevor Sie sie zurückgeben. Dieses Muster ist hilfreich, wenn Sie diese Requisite sowohl für Eltern als auch für Kinder ändern.
Lassen Sie uns sagen , dass wir prop haben Liste auf Komponenten Gitter .
In der übergeordneten Komponente
In der untergeordneten Komponente
quelle
Requisiten runter, Events rauf. Das ist Vues Muster. Der Punkt ist, dass, wenn Sie versuchen, Requisiten zu mutieren, die von einem Elternteil übergeben werden. Es funktioniert nicht und wird nur wiederholt von der übergeordneten Komponente überschrieben. Die untergeordnete Komponente kann nur ein Ereignis ausgeben, um die übergeordnete Komponente über etw zu informieren. Wenn Ihnen diese Einschränkungen nicht gefallen, können Sie VUEX verwenden (tatsächlich saugt dieses Muster die Struktur komplexer Komponenten an, Sie sollten VUEX verwenden!).
quelle
Sie sollten den Wert der Requisiten in der untergeordneten Komponente nicht ändern. Wenn Sie es wirklich ändern müssen, können Sie verwenden
.sync
. Genau wie dieser<your-component :list.sync="list"></your-component>
quelle
Gemäß den VueJs 2.0 sollten Sie eine Requisite innerhalb der Komponente nicht mutieren. Sie werden nur von ihren Eltern mutiert. Daher sollten Sie Variablen in Daten mit unterschiedlichen Namen definieren und durch Aktualisieren der tatsächlichen Requisiten auf dem neuesten Stand halten. Falls die Listen-Requisite von einem übergeordneten Element geändert wird, können Sie sie analysieren und mutableList zuweisen. Hier ist eine Komplettlösung.
Es verwendet mutableList, um Ihre Vorlage zu rendern, sodass Sie Ihre Listen-Requisite in der Komponente sicher aufbewahren.
quelle
Ändern Sie die Requisiten nicht direkt in Komponenten. Wenn Sie sie ändern müssen, legen Sie eine neue Eigenschaft wie folgt fest:
Und ändern Sie den Wert von listClone.
quelle
Die Antwort ist einfach: Sie sollten die direkte Prop-Mutation aufheben, indem Sie den Wert einigen lokalen Komponentenvariablen zuweisen (dies kann eine Dateneigenschaft sein, die mit Get-, Setter- oder Watchern berechnet wird).
Hier ist eine einfache Lösung mit dem Watcher.
Es ist das, was ich verwende, um Dateneingabekomponenten zu erstellen, und es funktioniert einwandfrei. Alle neuen Daten, die vom übergeordneten Element gesendet werden (v-Modell (ed)), werden vom Wertebeobachter überwacht und der Eingabevariablen zugewiesen. Sobald die Eingabe empfangen wurde, können wir diese Aktion abfangen und Eingaben an das übergeordnete Element senden, die darauf hinweisen, dass Daten eingegeben werden aus dem Formularelement.
quelle
Ich habe mich auch diesem Problem gestellt. Die Warnung ist verschwunden, nachdem ich
$on
und verwendet habe$emit
. Es ist so etwas wie Verwendung$on
und$emit
empfohlen, Daten von der untergeordneten Komponente zur übergeordneten Komponente zu senden.quelle
Wenn Sie Requisiten mutieren möchten, verwenden Sie Objekt.
Komponente:
quelle
Sie müssen eine berechnete Methode wie diese hinzufügen
component.vue
quelle
Einweg-Datenfluss Gemäß https://vuejs.org/v2/guide/components.html folgt die Komponente dem Einweg-Datenfluss. Alle Requisiten bilden eine Einweg-Bindung zwischen der untergeordneten Eigenschaft und dem übergeordneten Objekt Wenn die übergeordnete Eigenschaft aktualisiert wird, fließt sie zum untergeordneten Element, nicht jedoch umgekehrt. Dadurch wird verhindert, dass untergeordnete Komponenten versehentlich die übergeordneten Komponenten mutieren, wodurch der Datenfluss Ihrer App möglicherweise schwerer zu verstehen ist.
Außerdem werden jedes Mal, wenn die übergeordnete Komponente aktualisiert wird, alle Requisiten in den untergeordneten Komponenten mit dem neuesten Wert aktualisiert. Dies bedeutet, dass Sie nicht versuchen sollten, eine Requisite innerhalb einer untergeordneten Komponente zu mutieren. Wenn Sie dies tun, werden Sie von .vue in der Konsole gewarnt.
Es gibt normalerweise zwei Fälle, in denen es verlockend ist, eine Requisite zu mutieren: Die Requisite wird verwendet, um einen Anfangswert zu übergeben; Die untergeordnete Komponente möchte sie anschließend als lokale Dateneigenschaft verwenden. Die Requisite wird als Rohwert übergeben, der transformiert werden muss. Die richtige Antwort auf diese Anwendungsfälle lautet: Definieren Sie eine lokale Dateneigenschaft, die den Anfangswert der Requisite als Anfangswert verwendet:
Definieren Sie eine berechnete Eigenschaft, die aus dem Wert der Requisite berechnet wird:
quelle
Die Requisiten von Vue.j dürfen nicht mutiert werden, da dies in Vue als Anti-Pattern angesehen wird.
Der Ansatz, den Sie wählen müssen, besteht darin, eine Dateneigenschaft für Ihre Komponente zu erstellen, die auf die ursprüngliche Eigenschaft prop der Liste verweist
Jetzt wird Ihre Listenstruktur, die an die Komponente übergeben wird, über die
data
Eigenschaft Ihrer Komponente referenziert und mutiert :-)Wenn Sie mehr als nur Ihre Listeneigenschaft analysieren möchten, verwenden Sie die Eigenschaft der Vue-Komponente
computed
. Auf diese Weise können Sie Ihre Requisiten eingehender mutieren.Das obige Beispiel analysiert Ihre Listen- Requisite und filtert sie nur in aktive Listen-Tems, meldet sie für Schnitts und Kichern ab und gibt sie zurück.
Hinweis : Beide
data
&computed
Eigenschaften werden in der Vorlage gleich referenziert, zEs kann leicht zu denken sein, dass eine
computed
Eigenschaft (eine Methode) aufgerufen werden muss ... das tut es nichtquelle
Vielleicht wird dies Ihren Bedürfnissen entsprechen.
quelle
Zur besten Antwort hinzufügen,
Das Festlegen von Requisiten durch ein Array ist für die Entwicklung / das Prototyping gedacht. Stellen Sie in der Produktion sicher, dass Sie Requisitentypen ( https://vuejs.org/v2/guide/components-props.html ) festlegen und einen Standardwert festlegen, falls die Requisite dies nicht hat wurde vom Elternteil als solches bevölkert.
Auf diese Weise erhalten Sie mindestens ein leeres Objekt
mutableList
anstelle eines JSON.parse-Fehlers, wenn es nicht definiert ist.quelle
Vue.js betrachtet dies als Anti-Muster. Zum Beispiel deklarieren und setzen Sie einige Requisiten wie
Um dieses Problem zu lösen, müssen Sie einen Wert von den Requisiten zu den Daten oder der berechneten Eigenschaft einer Vue-Instanz wie folgt eingeben:
Das wird definitiv funktionieren.
quelle
Darüber hinaus für andere Personen mit folgendem Problem:
"Wenn der Requisitenwert nicht erforderlich ist und daher nicht immer zurückgegeben wird, werden die übergebenen Daten zurückgegeben
undefined
(anstatt leer)." Was den<select>
Standardwert durcheinander bringen könnte , habe ich gelöst, indem ich überprüft habe, ob der WertbeforeMount()
wie folgt eingestellt ist (und wenn nicht):JS:
Html:
quelle
Ich möchte diese Antwort geben, um zu vermeiden, dass viel Code, Beobachter und berechnete Eigenschaften verwendet werden. In einigen Fällen kann dies eine gute Lösung sein:
Requisiten bieten eine einseitige Kommunikation.
Wenn Sie einen modalen
show/hide
Knopf mit einer Requisite haben, ist die beste Lösung für mich, ein Ereignis auszusenden:Fügen Sie dann den Listener zum modalen Element hinzu:
(In diesem Fall ist die Requisite
show
wahrscheinlich unnötig, da Sie eine einfachev-if="show"
direkt auf dem Basismodal verwenden können)quelle
Ich persönlich schlage immer vor, wenn Sie die Requisiten mutieren müssen, sie zuerst an das berechnete Eigentum übergeben und von dort zurückkehren. Danach können Sie die Requisiten leicht mutieren, auch wenn Sie die Requisitenmutation verfolgen können, wenn diese von einem anderen mutiert werden Komponente auch oder wir können Sie auch sehen.
quelle
Da es sich bei Vue-Requisiten um einen Einwegdatenfluss handelt, wird verhindert, dass untergeordnete Komponenten versehentlich den Status des übergeordneten Elements ändern.
Aus dem offiziellen Vue-Dokument finden wir zwei Möglichkeiten, um diese Probleme zu lösen
Wenn untergeordnete Komponenten Requisiten als lokale Daten verwenden möchten, definieren Sie am besten eine lokale Dateneigenschaft.
Die Requisite wird als Rohwert übergeben, der transformiert werden muss. In diesem Fall ist es am besten, eine berechnete Eigenschaft anhand des Werts der Requisite zu definieren:
quelle
YES!, Mutierende Attribute in vue2 sind Anti-Pattern. ABER ... Brechen Sie einfach die Regeln, indem Sie andere Regeln verwenden, und gehen Sie weiter! Sie müssen Ihrem Komponentenattribut im Paret-Bereich den Modifikator .sync hinzufügen.
<your-awesome-components :custom-attribute-as-prob.sync="value" />
🤡 Es ist einfach, wir töten den Batman 😁
quelle
Für den Fall, dass TypeScript Ihre bevorzugte Sprache ist. der Entwicklung
und nicht
quelle
Unten ist eine Snackbar-Komponente, wenn ich die Snackbar- Variable direkt in das V-Modell wie dieses gebe, wenn es funktioniert, aber in der Konsole wird es einen Fehler als geben
Vermeiden Sie es, eine Requisite direkt zu mutieren, da der Wert bei jedem erneuten Rendern der übergeordneten Komponente überschrieben wird. Verwenden Sie stattdessen Daten oder berechnete Eigenschaften, die auf dem Wert der Requisite basieren.
Der richtige Weg, um diesen Mutationsfehler zu beseitigen, ist die Verwendung von Watcher
In der Hauptkomponente, in die Sie diese Snackbar laden, können Sie einfach diesen Code ausführen
Das hat bei mir funktioniert
quelle