在JavaScript中为Knockout Observable编写类似C#的扩展

问题描述 投票:1回答:1

请考虑以下代码:

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,当它最终得到组件时,我用初始数据执行初始化并摆脱订阅。

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

我想写一些类似C#扩展名的observable,就像使用它一样:

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个回答
2
投票

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

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

并且您可以使用此方法获取您的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());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

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

© www.soinside.com 2019 - 2024. All rights reserved.