将带有 ko.computed 的 mixin 添加到 knockout viewmodel

Add mixin with ko.computed to knockout viewmodel

读完这篇文章后:A fresh look at javascript mixins我想将一些常见的淘汰计算函数移动到一个 mixin 中,并将其混合到需要该功能的每个视图模型中。

首先是mixin函数

var asActor = function() {
    this.nrOfEmployees = ko.computed(function () {
        if (this.employees())
            return this.employees().length;
        return 0;
    }, this).extend({ throttle: 20 });
    this.nrOfAddresses = ko.computed(function () {
        if (this.addresses())
            return this.addresses().length;
        return 0;
    }, this).extend({ throttle: 20 })
};

然后调用将 mixin 混合到目标对象原型中

asActor.call(SenderActor.prototype);
asActor.call(ReceiverActor.prototype);

我的问题似乎是 this(或 self 设置为 this在视图模型中)指向 windows 对象而不是视图模型。有任何想法吗? Javascript mixins 对我来说是新手,所以我可能遗漏了一些明显的东西。

当您通过函数创建新对象时,例如 new asActor(),将为您提供一个默认值 return - 神奇的 "this"。当你只是 运行 一个函数时,你必须添加一个 return 语句。

我测试了你的代码,它没有问题,但是 运行ning asActor 没有 return 值。

var asActor = function() {
  this.nrOfEmployees = ko.computed(function () {
      if (this.employees())
        return this.employees().length;
    return 0;
  }, this).extend({ throttle: 20 });
  this.nrOfAddresses = ko.computed(function () {
    if (this.addresses())
        return this.addresses().length;
    return 0;
  }, this).extend({ throttle: 20 })

  return this;
};

asActor.call(SenderActor.prototype); 执行以下操作 -

  1. 它调用 asActor 并将 SenderActor.protototype 对象作为 this
  2. 传递
  3. this.nrOfEmployees = ko.computed(...)SenderActor.protototype
  4. 中创建一个 ko.computed
  5. 它在相同的上下文中评估计算 this 仍然指向 SenderActor.protototype

根据您是否在 SenderActor.protototype 或其原型链中包含 employees,此代码是否会产生错误。

现在我假设这种行为不是你想要的。

在 SenderActor 构造函数中尝试 运行 asActor.call(this);

正如 Olga 所说,在原型本身上创建计算并不是我的本意。我选择的解决方案是使用 Base class:

var Base = function () {
    var extenders = [];

    this.extend = function (extender) {
        extenders.push(extender);
    };

    this.init = function () {
        var self = this; // capture the class that inherits off of the 'Base' class

        ko.utils.arrayForEach(extenders, function (extender) {

            // call each extender with the correct context to ensure all
            // inheriting classes have the same functionality added by the extender
            extender.call(self);
        });
    };
};

在生成代码中,我在所有视图模型构造函数中添加了 this.Init() 调用

最后,我在每个视图模型上调用了 .extend 函数,将这些函数混合在一起:

SenderActor.prototype.extend(asActor);
ReceiverActor.prototype.extend(asActor);