2016-07-28 208 views
0

addTodo被触发,我检查其中的this,上下文是浏览器窗口,而不是data对象。因此todos最终未定义。为什么我的Vue方法没有引用正确的上下文(数据)?

任何想法我失踪?

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

为什么使用addTodo:()=> {而不是addTodo:function(){} - 无论如何你的代码是正确的,this.todos应该被定义。尝试比较你的代码和示例:https://vuejs.org/examples/svg.html – Xatenev

+0

@Xatenev我想我觉得它更短,更干净。这是ES6。但是,您提到的这一点提醒我,设置上下文(this)时,ES6箭头函数与旧函数语法的行为不同,并且将其更改为旧语法可以修复问题。除非你这么做,否则我会写一个答案来解释为什么这个工作在一秒钟内完成。 –

+3

'()=>'将'this'的值更改为封闭的上下文。在这种情况下,'this'可能等于'window'。这是你的问题。如果你想简洁一些,你可以使用'addTodos(){}'而不是'addTodos:function(){}'。 –

回答

3

快速修复:don't use arrow functions to declare your Vue methods.

什么问题?

你期待的ES6箭头功能() => {}语法来设置上下文(this)一样的旧函数声明语法function() {}会。

这是为什么?

从MDN:

直到箭头的功能,每一个新的功能定义了自己的这个值(在构造函数中,在严格模式下的函数调用不确定的情况下,一个新的对象,上下文对象,如果被调用的函数作为“对象方法”等)。事实证明,这是一种面向对象的编程风格。

所以,你的方法对象应该是这样的(使用旧的函数语法):

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

} 

或者这(使用new method definition syntax

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

我不知道大约是关于Vue.js如何设置/处理上下文的情况,但是看起来您的方法正在从您的模板/ DOM中调用,并且上下文将从那里传递到您的方法中。由于箭头函数继承其上下文,因此this引用window对象。

使用实际函数声明将保留对您想要的this的适当引用。

+1

您可以改为使用'addTodo(){...}'。 –

+0

@BillCriswell你是对的 - 无论如何,这完全是es6。好决定。相应更新。 –

4

它看起来像ES6箭头语法是你的问题。将其更改为使用传统的()函数的语法,它会工作:

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

+0

啊太晚了!当我打字时,你已经明白了! :) – SteveB

+0

另外OP可以使用'addTodo()'而不是'addTodo:function(){'如果简洁是他的顾虑。 –

0

你的箭头Vue的方法已经得到this对象作为第一个参数,所以:

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

的伎俩,但我不知道,箭头的功能都在这里贡献什么。

相关问题