【问题标题】:Add mixin with ko.computed to knockout viewmodel将带有 ko.computed 的 mixin 添加到淘汰视图模型
【发布时间】:2015-01-26 17:29:15
【问题描述】:

阅读本文后: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 对我来说是新的,所以我可能在这里遗漏了一些明显的东西。

【问题讨论】:

    标签: javascript knockout.js mixins


    【解决方案1】:

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

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

    取决于您的SenderActor.protototype 中是否有employees 或其原型链,此代码会或不会产生错误。

    现在我假设这种行为不是你所关注的。

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

    【讨论】:

    • 很好的答案让我找到了我的解决方案。由于我无权更改构造函数(它是从服务器动态生成的),我需要以另一种方式添加这些方法。详情见我的回答。
    • 我会奖励你答案,因为它帮助我找到了解决方案。
    【解决方案2】:

    当你通过一个函数创建新对象时,比如 new asActor(),会有一个默认值为你返回——神奇的“this”。刚运行函数时必须添加return语句。

    我已经测试了你的代码,没有问题,但是运行 asActor 没有返回值。

    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;
    };
    

    【讨论】:

      【解决方案3】:

      正如奥尔加所说,在原型本身上创建一个计算并不是我的真正意图。我选择的解决方案是使用 Base 类:

      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);
      

      【讨论】:

      • 简洁的解决方案。为了完整起见,请添加用于继承 Base 的代码。 Base.call(Cat.prototype) 为我工作。
      • 好点,我忘了...要继承 Base 我在定义 SenderActor 构造函数后添加 SenderActor.prototype = new Base();
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-20
      • 1970-01-01
      • 2015-07-27
      • 1970-01-01
      • 2014-07-26
      • 2019-02-05
      • 2012-08-02
      相关资源
      最近更新 更多