在这个例子中,我有一个对象得到了一个name
作为string
参数,还有一个函数只记录this
const me = reactive({
name: "foo",
sayHi: function () {
console.log("Hi I am : ", this);
},
});
在模板中,我指定了另一个组件,该组件在创建3000ms后会发出事件sayHi
。该组件创建两次:
<Comp :name="me.name" @sayHi="me.sayHi"/>
<Comp :name="me.name" @sayHi="me.sayHi()"/>
我有点理解这里解释的带括号和不带括号的事件处理程序之间的区别,但我不明白为什么第一个中的this
是undefined
,而第二个中的是我所期望的对象本身。
当v-on
指令与@sayHi="me.sayHi()"
内联表达式一起提供时,它会被一个函数包装,并编译为类似于:
el.addEventListener('sayHi', $event => { vm.me.sayHi() })
当一个值是像@sayHi="me.sayHi"
这样的函数值时,事件处理程序本身就是一个函数:
el.addEventListener('sayHi', vm.me.sayHi)
正如本问题中所解释的,当this
上下文的方法用作回调时,它不是父对象,当它作为事件处理程序传递时,就会发生这种情况。函数应显式绑定到所需上下文,以将其作为this
接收。
与此问题的区别在于sayHi
不是组件方法。Vue选项API中的组件methods
内部绑定到组件实例,这不适用于组合API。
sayHi
应明确引用无功值,而不是使用this
:
const me = reactive({
name: "foo",
sayHi: () => {
console.log("Hi I am : ", me.name);
},
});
使用sayHi
函数作为反应对象的方法没有任何好处,它被Vue-reactive API忽略了。除非me
是一个对象是有原因的,例如它被传递给其他组件,否则状态和函数可以被分离:
const me = ref("foo")
const sayHi = () => {
console.log("Hi I am : ", me.value);
};
事件调用以不同方式编译
// <Comp :name="me.name" @sayHi="me.sayHi"/>
let fn = me.sayHi
fn($event) // `this` is undefined us you just calling a function
和
// <Comp :name="me.name" @sayHi="me.sayHi()"/>
// or
// <Comp :name="me.name" @sayHi="() => me.sayHi()"/>
let fn = () => me.sayHi()
fn($event) // `this` is `me` as you are calling an object method