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

标签 javascript knockout.js knockout-3.0

考虑以下代码:

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

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

我想为 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 检索当前值在添加到原型(prototype)的方法中,但问题在于 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

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

最佳答案

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

I am not sure if this is possible to get the current value of observable inside the "extension" method

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

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

关于javascript - 在 JavaScript 中为 Knockout Observable 编写类似 C# 的扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47993260/

相关文章:

javascript - 以编程方式更新可观察值时 Knockoutjs 不更新 UI

javascript - 选择的自定义绑定(bind)无法将对象作为值处理

javascript - 单击附加表单按钮不会触发表单提交

javascript - 使用 knockout 缓存计算值

javascript - 带有选项卡式用户界面的 KnockoutJs 应用程序 : What is best practice?

javascript - 如何使用模板中的 Knockout 映射插件映射到来自服务器对象的数组?

html - 如何在 HTML 中注释掉 knockout 代码

javascript - javascript array 和 jquery set 的区别

javascript - 如何使用appcelerator构建Android服务

javascript - 将对象附加到 Javascript 数组