2016-07-28 3 views
0

Wenn addTodo ausgelöst wird und ich this darin überprüfen, ist der Kontext das Browserfenster, nicht das data Objekt. So endet todos undefined.Warum bezieht sich meine Vue-Methode nicht auf den richtigen Kontext (Daten)?

Irgendeine Idee, was ich vermisse?

HTML:

<div id="todo-list"> 
    <input type="text" v-model="newTodo"> 
    <button v-on:click="addTodo">Add</button> 
    <ul> 
    <li v-if="todos.length" v-for="todo in todos" class="todo-item"> 
     {{ todo }} 
    </li> 
    </ul> 
</div> 

JS:

new Vue({ 
    el: '#todo-list', 
    data: { 
    todos: [], 
    newTodo: '' 
    }, 
    methods: { 
    addTodo:() => { 
     this.todos.push(this.newTodo); 
     this.clearNewTodo(); 
    }, 
    clearNewTodo:() => { 
     this.newTodo = ''; 
    } 
    } 
}); 
+0

Warum verwenden Sie addTodo:() => {anstelle von addTodo: function() {} - wie auch immer Ihr Code korrekt ist, sollte this.todos defined definiert werden.Versuchen Sie, Ihren Code mit dem Beispiel zu vergleichen: https://vuejs.org/examples/svg.html – Xatenev

+0

@ Xatenev Ich denke, ich finde es kürzer und sauberer. Es ist ES6. Aber Ihre Erwähnung erinnerte mich daran, dass sich die ES6-Pfeilfunktionen bei der Einstellung des Kontextes nicht wie die alte Funktionssyntax verhalten (...) und ... das Ändern der alten Syntax das Problem behebt. Ich werde eine Antwort schreiben, warum das in einer Sekunde funktioniert, es sei denn, du tust es. –

+3

'() =>' ändert den Wert von 'this 'in den umgebenden Kontext. In diesem Fall kann "this" gleich "window" sein. Da ist dein Problem. Wenn Sie etwas knappes wollen, können Sie 'addTodos() {}' anstelle von 'addTodos: function() {}' verwenden. –

Antwort

3

Quick Fix: don't use arrow functions to declare your Vue methods.

Was ist das Problem?

Sie erwarten die ES6 Pfeilfunktion () => {} Syntax, um den Kontext (this) das gleiche wie die alte Funktion Deklaration Syntax function() {} setzen würde.

Warum ist das ein Problem?

Von MDN:

Bis Pfeil Funktionen, jede neue Funktion einen eigenen diesen Wert definiert (ein neues Objekt bei einem Konstruktor, undefiniert im Strict-Modus Funktionsaufrufen, das Kontextobjekt, wenn die Funktion aufgerufen wird als "Objektmethode" usw.). Dies erwies sich bei einem objektorientierten Programmierstil als ärgerlich.

Also, Objekt Ihre Methoden sollte wie folgt aussehen (die alte Funktion Syntax):

methods: { 
    addTodo: function() { 
     this.todos.push(this.newTodo); 
     this.clearNewTodo(); 
    }, 
    clearNewTodo: function() { 
     this.newTodo = ''; 
    } 

} 

Oder diese (mit dem new method definition syntax)

methods: { 
    addTodo() { 
     this.todos.push(this.newTodo); 
     this.clearNewTodo(); 
    }, 
    clearNewTodo() { 
     this.newTodo = ''; 
    } 
    } 

Ich weiß nicht ein Darüber, wie Vue.js den Kontext an diesem Punkt einstellt/handhabt, sieht es so aus, als ob Ihre Methode aus Ihrer Vorlage/dem DOM aufgerufen wird und der Kontext von dort in Ihre Methode übernommen wird. Da die Pfeilfunktion ihren Kontext erbt, bezieht sich this auf das Objekt window.

Die Verwendung tatsächlicher Funktionsdeklarationen wird einen korrekten Verweis auf die gewünschte this beibehalten.

+1

Sie können stattdessen 'addTodo() {...}' tun. –

+0

@BillCriswell du hast Recht - das ist voll es6 sowieso. Guter Ruf. Entsprechend aktualisiert. –

4

Es sieht aus wie die ES6 Pfeil Syntax Ihr Problem. Ändern Sie die traditionelle Funktion() Syntax verwenden und es wird funktionieren:

addTodo: function() { 
 
    this.todos.push(this.newTodo); 
 
    this.clearNewTodo(); 
 
}, 
 
clearNewTodo: function() { 
 
    this.newTodo = ''; 
 
}

+0

ahh zu spät! Du hast es herausgefunden, während ich es eingegeben habe! :) – SteveB

+0

Alternativ kann OP 'addTodo()' anstelle von 'addTodo: function() {' verwenden, wenn es um die Kurzsichtigkeit geht. –

0

Ihr Pfeil Vue Methoden bereits erhalten die this Objekt als ersten Parameter, so:

methods: { 
    addTodo: (_this) => { 
     _this.todos.push(_this.newTodo); 
     _this.clearNewTodo(); 
    }, 
    clearNewTodo: (_this) => { 
     _this.newTodo = ''; 
    } 
    } 

der Trick funktioniert, aber ich bin nicht sicher, dass Pfeil Funktionen etwas beitragen hier.

Verwandte Themen