【问题标题】:Is it possible to inherit ko.computed to a prototype class?是否可以将 ko.computed 继承到原型类?
【发布时间】:2015-06-23 08:20:16
【问题描述】:

假设我希望 ko.computed 具有以下行为:

  • 阅读

但我想在 ko.computed 属性中有一个内部可观察对象,例如:

this.a = ko.computed(function() {
    value: ko.observable(null),

    read: function() {
        return value;
    },

    write: function(newValue) { 
        if (newValue) {
            value(newValue);
        }
    }
});

这可能以某种方式实现吗?上面的不行。

【问题讨论】:

  • 你能解释一下“继承ko.computed到原型类”是什么意思吗?
  • 你应该更新你的标题,我的回答更针对标题“继承 ko.computed 到原型类”

标签: javascript knockout.js observable


【解决方案1】:

你可以这样做,

http://jsfiddle.net/b5stgh3L/

var myComputed = function() {
    var value = ko.observable();

    return ko.computed({         
        read: function() {
            return value();
        },
        write: function(newValue) { 
            if (newValue) {
                value(newValue);
            }
        }
    })    
};

var vm = function() {
    this.my = myComputed();
};

var instance = new vm();

instance.my("value");
instance.my(null);

console.log(instance.my());

你也可以使用原型扩展计算,就像 ko 在内部使用它

function setPrototypeOf(obj, proto) {
    obj.__proto__ = proto;
    return obj;
} 

使用喜欢(ko.utils.setPrototypeOf 未导出使用上述代码)

ko.utils.setPrototypeOf(ko.observableArray['fn'], ko.observable['fn']);

我的旧答案在这里找到可能可以帮助您如何使用原型方法

How can I create a typed collection class in Knockout mapping?

http://jsfiddle.net/xop2go2z/

【讨论】:

  • 顺便说一句,myComputed 函数可以很容易地转换为扩展函数jsfiddle.net/b5stgh3L/1
  • @Anders 您的扩展器是一个相当复杂的空操作。它实际上什么也没做。
  • 我知道我只是以有问题的代码为例
  • 但是你不能省略 if 块,这会改变行为(只提交非空值)
【解决方案2】:

看起来您想要的是一个不允许验证失败的分配的可观察对象。你可以在普通的 observable 上使用扩展器来做到这一点:

ko.extenders.constrain = function (target, option) {
    var lastValidValue = target();
    target.subscribe(function (newValue) {
        if (option(newValue)) {
            lastValidValue = newValue;
        } else {
            target(lastValidValue);
        }
    });
    return target;
};

这样称呼它以防止分配虚假值:

var notFalsy = ko.observable("Bob").extend({
    constrain: function (newValue) {
        return newValue;
    }
});

更新:上述方法在更正之前确实允许分配可能很重要。如果 observable 从不采用无效值很重要,则可以使用计算(结构很像安德斯的解决方案)。

function constrainedObservable(constraint) {
    var value = ko.observable();
    return ko.computed({
        read: value,
        write: function (newValue) {
            if (constraint(newValue)) {
                value(newValue);
            }
        }
    });
}

Demo http://jsfiddle.net/o641v37L/1/(取消注释分配以使用计算)

【讨论】:

  • 第一个代码块中的return target; 语句除了链接之外还有其他用途吗?
  • @Tyblitz 我不确定它是否有任何用途。我以为它是在分配期间进行链接的,但我把它拿出来,分配的工作原理是一样的。 jsfiddle.net/o641v37L
【解决方案3】:

这与https://stackoverflow.com/a/30506199/18771 在这里回答的问题并不完全相同,但非常接近。

底线是,不,您实际上不能在原型链中进行计算,因为该计算将在您的所有视图模型实例之间共享。

如果您打算在多个对象实例之间共享单个计算值,请继续。

如果您想创建某种类层次结构,但仍希望您的各个视图模型实例拥有自己的单独可观察对象,那么您无法通过原型来实现。


背景:JavaScript 既没有类(抽象对象描述)也没有基于类的继承(分层抽象对象描述)。 JavaScript 有对象(由构造函数产生)和原型链(对象的单链表)。原型链中的所有内容都在对象构造函数创建的所有实例之间物理共享。

【讨论】:

  • +1 用于回答“字面上”提出的问题。关于 JS 没有类的注释:这会随着 ES6 的结构发生变化还是只是语法糖?
  • @Tyblitz 语法糖。
猜你喜欢
  • 2014-02-13
  • 2014-01-15
  • 1970-01-01
  • 2013-11-22
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 2021-09-04
相关资源
最近更新 更多