Vue中this的绑定
之前写过一篇文章 ES6与React中this完全解惑 其实Vue也是相同的道理。在Vue的官方文档中提到:
不要在选项属性或回调上使用箭头函数,比如 created: () => console.log(this.a) 或 vm.$watch('a', newValue => this.myMethod())。因为箭头函数是和父级上下文绑定在一起的,this 不会是如你所预期的 Vue 实例,经常导致 Uncaught TypeError: Cannot read property of undefined 或 Uncaught TypeError: this.myMethod is not a function 之类的错误。
箭头函数里this是相同的道理,我更推荐MDN里对箭头函数this的说明“箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承 this
”
this.aaa = 3 new Vue({ data: { a: 1 }, created: () => console.log(this) })
这段代码在浏览器执行后,输出的this是window对象。
箭头函数中,this引用的是定义箭头函数的上下文。
箭头函数中this,须通过查找作用域链来决定其值,箭头函数内部的this
指向是固定的。如果箭头函数被非箭头函数包含,则this是最近一层非箭头函数的this;否则,this的值会被设置为全局对象。
普通函数都有自己的this,Vue实例化被调用时都能正确指向组件实例。但箭头函数没有自己的this,它只能去找父级作用域中的this。这个父级作用域是谁呢?是组件实例吗?我们知道作用域只有两种:全局作用域和函数作用域(以及ES6里条件判断等新增的块级作用域)。回到我们写的vue代码,它本质就是一个对象(具体一点,是一个组件的配置对象,这个对象里面有data、mounted、methods等属性)也就是说,我们在一个对象里面去定义方法,因为对象不构成作用域,所以这些方法的父作用域都是全局作用域。箭头函数要去寻找this,就只能找到全局作用域中的this——window对象了。
new Vue({ el: '#app', data: { a: 3, }, mounted: function () { (() => { console.log(this.a) // 打印3 该箭头函数的this指向mounted函数作用域里的this,mounted函数的this是经过Vue处理的为Vue实例。 // 但若直接把mounted函数改成箭头函数就会出问题,会向外层找作用域里this,ES5模式下是window. })() } }) class Clock extends Component { constructor(props) { this.state = { time: 1 } } componentDidMount() { this.setState({time: this.state.time + 1}, () => { console.log(this.state.time) //打印2 该箭头函数的this指向componentDidMount函数作用域里的this。 }) } }