装饰在Vue中调用的函数弄乱“ this”绑定?

时间:2019-03-16 20:21:18

标签: javascript vue.js decorator

我的Vue应用程序正在使用一个普通的JS对象来集中数据库调用。我想控制台记录呼叫。为此,我正在装饰对象的方法,如下所示:

const Caller = {
    callingDB (arg1, arg2) { return ... } //Promise-wrapped db call here
}
const decorator = f => (...args) => {
    return f(...args).then(res => console.log(`Invoked method ${f.name} with ${args} for result: ${res}`))
}

Caller.callingDB = decorator(Caller.callingDB)

在几个Vue组件中,我具有调用上述普通对象方法的组件方法,例如: ...

methods: {
 cMethod() { this.Caller.callingDB(arg1, arg2) }
}

但是有一个警告:一旦装饰了Caller.callingDB方法,由于未定义“ this”而引发错误-我的应用程序中的数据流依赖于通过上述方法链接的db调用,所有这些都以类似的方式被调用。一切正常,无需装饰。

我不明白为什么会发生这些错误。关于如何重写装饰器以保留所有后续此限制调用的提示?还是我错过了这些错误的根源?

2 个答案:

答案 0 :(得分:1)

const decorator = f => (...args) => {
    return f.apply(Caller, args).then(res => console.log(`Invoked method ${f.name} with ${args} for result: ${res}`))
}

js中的函数具有方法apply,该方法将this值作为第一个参数,并将arguments数组作为第二个参数。

这是修改后的代码https://jsfiddle.net/435h2gwp/的小提琴

答案 1 :(得分:1)

扩展@ chris.va.rao的答案:

无需对“ Caller”对象进行硬编码:

const Caller = {
        foo() {
        return new Promise((resolve) => {
        setTimeout(() => {
            this.counter = this.counter || 1;
          resolve(this.counter);
        }, 1000);
      });
    },
    callingDB(arg1, arg2) {
      return this.foo();
    } //Promise-wrapped db call here
}
function decorator (f) {

    return (...args) => f.apply(this,[...args])
    .then(res => console.log(`Invoked method ${f.name} with ${args} for result: ${res}`))
}


Caller.callingDB = decorator.bind(Caller)(Caller.callingDB);

Caller.callingDB(1, 2, 3);

fiddle