【问题标题】:Writing C#-like extensions in JavaScript for Knockout Observable在 JavaScript 中为 Knockout Observable 编写类似 C# 的扩展
【发布时间】:2017-12-28 13:30:09
【问题描述】:

考虑以下代码:

if (countriesLookup()) {
    countriesLookup().fill(initialData.Countries);
} else {
    const subscription = countriesLookup.subscribe(function (lookup) {
        lookup.fill(initialData.Countries);
        subscription.dispose();
    });
}

这里我有一个 ko.observable countriesLookup。如果在数据初始化时组件本身尚未初始化 (countriesLookup() == undefined),我订阅该 observable,当它最终获得组件时,我使用初始数据执行初始化并取消订阅。

让我们暂时忘记这种方法会导致回调地狱等,并考虑可能的方法来减少这种丑陋。

我想为 observable 编写类似 C# 扩展之类的东西,就像在使用中那样:

countriesLookup.initialize(x => x.fill(initialData.Countries));

实现应该是这样的:

ko.observable.prototype.initialize = function(initializeFunc) {
    const currentValue = ???
    if (currentValue()) {
        initializeFunc(currentValue());
    } else {
        const subscription = currentValue.subscribe(function (lookup) {
            initializeFunc(lookup);
            subscription.dispose();
        });
    }
}

显然,这不起作用,尤其是因为我不确定这是否可以在“扩展”方法中获取 observable 的当前值。

我目前正在考虑 C# 编程,我在这方面有点精通,并且非常想就如何编写这样的扩展获得一些建议。


也许我应该多解释一下我的问题。我知道可以在添加到原型的方法中使用this 检索当前值,但问题在于 observable 返回一个函数。

例如这个

String.prototype.SayHi = function SayHi() {
    return "Hi " + this + "!";
};
"blah".SayHi();      //return "Hi blah!"

工作得很好,但是这个

ko.observable.prototype.SayHi = function SayHi() {
    return "Hi " + this + "!";
};
var a = ko.observable("blah")
a.SayHi();

失败并出现以下错误:

VM543:1 Uncaught TypeError: a.SayHi is not a function at <anonymous>:1:3

我希望它增加了一些说明。

【问题讨论】:

    标签: javascript knockout.js knockout-3.0


    【解决方案1】:

    如果我明白你的意思,你的目标是为 observables 添加一个自定义函数。
    在这种情况下,您应该使用fn 而不是prototype
    看看这个链接:http://knockoutjs.com/documentation/fn.html

    我不确定这是否可以在“扩展”方法中获取 observable 的当前值

    您可以使用此方法获取可观察对象的当前值,因此您上面的示例非常接近您想要的。

    ko.observable.fn.initialize = function(initializeFunc) {
      const currentValue = this;
      if (currentValue()) {
        initializeFunc(currentValue());
      } else {
        const subscription = currentValue.subscribe(function(lookup) {
          initializeFunc(lookup);
          subscription.dispose();
        });
      }
      return this;
    }
    
    var ViewModel = function() {
      this.data = ko.observable().initialize(x => console.log("Value changed to: " + x));
      this.data("100");
    };
    
    ko.applyBindings(new ViewModel());
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"&gt;&lt;/script&gt;

    =================================
    注意:有一个关于为什么使用fn 而不是prototype 的讨论,有人指出,出于某些性能原因,最好使用extenders
    在这里阅读:https://github.com/knockout/knockout/issues/979

    【讨论】:

    • 干得好,阿德里安!非常感谢!
    猜你喜欢
    • 2014-06-29
    • 2010-09-09
    • 2015-11-05
    • 1970-01-01
    • 2012-02-07
    • 2012-03-10
    • 2016-12-19
    • 1970-01-01
    相关资源
    最近更新 更多