Ich mache mit Laravel und Vue ein Warenkorbsystem. Wenn ich einen Artikel in den Warenkorb lege, wird eine Bestätigungsmeldung angezeigt, indem eine Vue-Variable umgeschaltet wird, die von einem v-if überwacht wird:
<div class="alert alert-success" v-if="basketAddSuccess" transition="expand">Added to the basket</div>
Und der JS:
addToBasket: function(){
item = this.product;
this.$http.post('/api/buy/addToBasket', item);
this.basketAddSuccess = true;
}
(Und ja, ich werde dies in Kürze in einem Dann-Fang hinzufügen).
Dies funktioniert gut und die Meldung wird angezeigt. Ich möchte jedoch, dass die Nachricht nach einer bestimmten Zeit wieder verschwindet, beispielsweise nach einigen Sekunden. Wie kann ich das mit Vue machen? Ich habe es versucht, setTimeOut
aber Vue scheint es nicht zu mögen und sagt, es sei undefiniert.
EDIT: Ich habe falsch geschrieben setTimeout
wie ein Idiot. Es funktioniert jedoch immer noch nicht:
Meine Funktion ist jetzt:
addToBasket: function(){
item = this.photo;
this.$http.post('/api/buy/addToBasket', item);
this.basketAddSuccess = true;
setTimeout(function(){
this.basketAddSuccess = false;
}, 2000);
}
javascript
vue.js
flurpleplurple
quelle
quelle
setTimeout(()=>{ this.basketAddSuccess = false; }, 2000);
this
innerhalb dersetTimeout
bezieht sich nicht auf das Hauptobjekt.this
sollte sich auf den richtigen Bereich beziehen. Dies war ein Problem, das zuvor mit dem typischen gelöst wurdevar self=this
. Bitte korrigiere mich wenn ich falsch liege. Nicht getestet.Antworten:
Pfeilfunktion
Der beste und einfachste Weg, um dieses Problem zu lösen, ist die Verwendung einer Pfeilfunktion
() => {}
:addToBasket() { var item = this.photo; this.$http.post('/api/buy/addToBasket', item); this.basketAddSuccess = true; // now 'this' is referencing the Vue object and not the 'setTimeout' scope setTimeout(() => this.basketAddSuccess = false, 2000); }
Dies funktioniert , weil die
this
Pfeilfunktionen an den gebundenenthis
seinen umschließenden Umfang - in Vue, dass die Eltern / umschließenden Komponente ist. Innerhalb einer traditionellen Funktion, die von aufgerufen wirdsetTimeout
, wird jedochthis
auf daswindow
Objekt verwiesen (weshalb beim Versuch,this.basketAddSuccess
in diesem Kontext auf etwas zuzugreifen , Fehler aufgetreten sind).Argument übergeben
Eine andere Möglichkeit, dies zu tun, besteht darin,
this
als Argument an Ihre Funktion durchsetTimeout
den Prototyp zu übergeben , der dessensetTimeout(callback, delay, arg1, arg2, ...)
Form verwendet:addToBasket() { item = this.photo; this.$http.post('/api/buy/addToBasket', item); this.basketAddSuccess = true; //Add scope argument to func, pass this after delay in setTimeout setTimeout(function(scope) { scope.basketAddSuccess = false; }, 2000, this); }
(Es ist jedoch anzumerken, dass die Arg-Passing-Syntax nicht mit IE 9 und niedriger kompatibel ist.)
Lokale Variable
Ein anderer möglicher , aber weniger beredter und weniger ermutigter Weg besteht darin, sich
this
an eine Var außerhalb von zu bindensetTimeout
:addToBasket() { item = this.photo; this.$http.post('/api/buy/addToBasket', item); this.basketAddSuccess = true; //Declare self, which is accessible inside setTimeout func var self = this; setTimeout(function() { self.basketAddSuccess = false; }, 2000); }
Die Verwendung einer Pfeilfunktion würde die Notwendigkeit dieser zusätzlichen Variablen jedoch vollständig beseitigen und sollte wirklich verwendet werden, es sei denn, etwas anderes verhindert ihre Verwendung.
quelle
Nachdem ich auf dasselbe Problem gestoßen war, landete ich in diesem Thread. Für die zukünftige Generation: Die aktuell am häufigsten gewählte Antwort versucht, "dies" an eine Variable zu binden, um zu vermeiden, dass der Kontext beim Aufrufen der im setTimeout definierten Funktion geändert wird.
Ein alternativer und empfohlener Ansatz (unter Verwendung von Vue.JS 2.2 und ES6) besteht darin, eine Pfeilfunktion zu verwenden, um den Kontext an das übergeordnete Element zu binden (im Grunde "this" von "addToBasket" und "this" von "setTimeout") würde sich immer noch auf dasselbe Objekt beziehen):
addToBasket: function(){ item = this.photo; this.$http.post('/api/buy/addToBasket', item); this.basketAddSuccess = true; setTimeout(() => { this.basketAddSuccess = false; }, 2000); }
quelle
Fügen Sie bind (this) zu Ihrer setTimeout-Rückruffunktion hinzu
setTimeout(function () { this.basketAddSuccess = false }.bind(this), 2000)
quelle
ES6 kann 'dies' binden
setTimeout(() => { },5000);
quelle
Sie können Vue.nextTick verwenden
addToBasket: function(){ item = this.photo; this.$http.post('/api/buy/addToBasket', item); this.basketAddSuccess = true; Vue.nextTick(() =>{ this.basketAddSuccess = false; }); }
quelle
vuejs 2
Fügen Sie dies zuerst zu den Methoden hinzu
methods:{ sayHi: function () { var v = this; setTimeout(function () { v.message = "Hi Vue!"; }, 3000); }
Rufen Sie danach diese Methode auf gemountet auf
mounted () { this.sayHi() }
quelle
Kevin Muchwat oben hat die BESTE Antwort, trotz nur 10 positiven Stimmen und nicht ausgewählter Antwort.
setTimeout(function () { this.basketAddSuccess = false }.bind(this), 2000)
Lassen Sie mich erklären, warum.
"Pfeilfunktion" ist ECMA6 / ECMA2015. Es ist perfekt in kompilierten Code- oder kontrollierten Client-Situationen (Cordova-Telefon-Apps, Node.js) gültig und nett und prägnant. Es wird wahrscheinlich sogar Ihre Tests bestehen!
Microsoft hat jedoch in seiner unendlichen Weisheit entschieden, dass Internet Explorer ECMA2015 NIEMALS UNTERSTÜTZEN wird!
Ihr neuer Edge-Browser funktioniert, aber das ist nicht gut genug für öffentlich zugängliche Websites.
Das Ausführen einer Standardfunktion () {} und das Hinzufügen von .bind (this) ist jedoch die ECMA5.1-Syntax (die vollständig unterstützt wird) für genau dieselbe Funktionalität.
Dies ist auch bei Ajax / Post .then / else-Aufrufen wichtig. Am Ende Ihrer .then (Funktion) {}) müssen Sie (dies) auch dort binden, also: .then (Funktion () {this.flag = true} .bind (this))
Ich hätte dies als Kommentar zu Kevins Antwort hinzugefügt, aber aus irgendeinem dummen Grund braucht es weniger Punkte, um Antworten zu posten, als um Kommentare zu Antworten
MACHEN SIE NICHT DEN GLEICHEN FEHLER, DEN ICH GEMACHT HABE!
Ich habe auf einem Mac codiert und den Kommentar mit 48 Punkten verwendet, der großartig funktioniert hat! Bis ich einige Anrufe bei meinen Skripten bekam, die fehlschlugen und ich nicht herausfinden konnte, warum. Ich musste zurückgehen und Dutzende Aufrufe von der Pfeilsyntax auf function () {}. Bind (this) syntax aktualisieren.
Zum Glück habe ich diesen Thread wieder gefunden und die richtige Antwort bekommen. Kevin, ich bin für immer dankbar.
Gemäß der "Akzeptierten Antwort" gibt es andere potenzielle Probleme im Zusammenhang mit zusätzlichen Bibliotheken (Probleme beim ordnungsgemäßen Zugriff auf / Aktualisieren von Vue-Eigenschaften / -Funktionen)
quelle
bind(this)
Wenn Sie Pfeilfunktionen verwenden, ist dies nicht erforderlich :setTimeout( ()=> { // some code }, 500)
quelle
Wenn Sie dieses Schlüsselwort in Ihrer Funktion verwenden möchten, müssen Sie die Funktion setTimeout in ES6 schreiben
setTimeout(() => { this.filters.max_budget_gt_eq = this.budgetHigherValue; }, 1000);
quelle
Pfeilfunktion
Der beste und einfachste Weg, um dieses Problem zu lösen, ist die Verwendung einer Pfeilfunktion
() => {}
:addToBasket() { var item = this.photo; this.$http.post('/api/buy/addToBasket', item); this.basketAddSuccess = true; // now 'this' is referencing the Vue object and not the 'setTimeout' scope setTimeout(() => this.basketAddSuccess = false, 2000); }
Dies funktioniert , weil die
this
Pfeilfunktionen an den gebundenenthis
seinen umschließenden Umfang - in Vue, dass die Eltern / umschließenden Komponente ist. Innerhalb einer traditionellen Funktion, die von aufgerufen wirdsetTimeout
, wird jedochthis
auf daswindow
Objekt verwiesen (weshalb beim Versuch,this.basketAddSuccess
in diesem Kontext auf etwas zuzugreifen , Fehler aufgetreten sind).Argument übergeben
Eine andere Möglichkeit, dies zu tun, besteht darin,
this
als Argument an Ihre Funktion durchsetTimeout
den Prototyp zu übergeben , der dessensetTimeout(callback, delay, arg1, arg2, ...)
Form verwendet:addToBasket() { item = this.photo; this.$http.post('/api/buy/addToBasket', item); this.basketAddSuccess = true; //Add scope argument to func, pass this after delay in setTimeout setTimeout(function(scope) { scope.basketAddSuccess = false; }, 2000, this); }
(Es ist jedoch anzumerken, dass die Arg-Passing-Syntax nicht mit IE 9 und niedriger kompatibel ist.)
quelle
benutze
this.animationStop
, nicht benutze this.animationStop()animationRun(){ this.sliderClass.anim = true; setTimeout(this.animationStop, 500); },
quelle
Es ist wahrscheinlich ein Umfangsproblem. Versuchen Sie stattdessen Folgendes:
addToBasket: function(){ item = this.photo; this.$http.post('/api/buy/addToBasket', item); this.basketAddSuccess = true; var self = this; setTimeout(function(){ self.basketAddSuccess = false; }, 2000); }
quelle