我有一个Vue(2.5+)组件,在其中将数据属性设置为新的Foo
对象。在点击处理程序中使用foo.bar()
会正确调用该方法,但是在尝试修改Uncaught TypeError: cannot set property 'someVariable' of null
类中的属性时会抛出Foo
。进行设置以使Foo
是对象文字而不是类,也不能解决错误。
我怀疑this
在组件和类之间发生了什么奇怪的事情?
import Foo from './foo.js'
export default {
template: `<div @click="foo.bar"></div>`,
data() {
return {
foo: new Foo()
}
},
created() {
console.log(foo); // foo is not null here
}
}
export default class Foo
{
constructor()
{
this.someVariable = 0;
}
bar(e)
{
// modify this.someVariable
}
}
但是如果我更改vue组件以通过其自己的“ methods”属性引用外部方法,它将起作用。
import Foo from './foo.js'
export default {
template: `<div @click="bar"></div>`,
data() {
return {
foo: new Foo()
}
},
methods: {
bar(e) {
this.foo.bar(e);
}
}
}
答案 0 :(得分:1)
如评论中所述,foo.bar
没有附加任何上下文:
在JS函数中,对象是对象,就像任何对象一样,它们都有自己的this
“指针”。
在评估其身体时,this
绑定到称为context
的特定对象,该对象可以是默认上下文(自动设置)或用户定义(手动设置)。
JS中的继承是通过prototype chain实现的,并且方法 应该在类的原型上定义/附加在类的原型上。因此,当您致电foo.bar()
时:
foo
将绑定到该方法bar
,然后在原型链中搜索但是方法的行为与任何其他属性一样:foo.bar
时,您获得对实际方法的引用,该方法是未绑定函数(方法的默认行为,因为它是绑定的)在对象上调用时。
因此,在这种情况下,您真正需要做的是foo.bar.bind(foo)
。
我还建议您快速了解this ES6 proposal for a bind operator及其作为Babel plugin的实现,它允许通过::foo.bar
而不是foo.bar.bind(foo)