假设我希望ko.computed具有以下行为:
但是我希望在ko.computed属性中有一个内部observable,类似于:
this.a = ko.computed(function() {
value: ko.observable(null),
read: function() {
return value;
},
write: function(newValue) {
if (newValue) {
value(newValue);
}
}
});
这有可能以某种方式吗?以上不起作用。
答案 0 :(得分:3)
你可以这么做,
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使用它internaly
function setPrototypeOf(obj, proto) {
obj.__proto__ = proto;
return obj;
}
使用过的(ko.utils.setPrototypeOf
未导出使用上面的代码)
ko.utils.setPrototypeOf(ko.observableArray['fn'], ko.observable['fn']);
我在这里找到的旧答案可以帮助您如何使用原型approuch
How can I create a typed collection class in Knockout mapping?
答案 1 :(得分:2)
这与{(3}}所回答的问题不完全相同,但它非常接近。
底线是,不,你实际上在原型链中没有计算,因为计算结果会在你所有的viewmodel实例之间共享。
如果你打算在多个对象实例之间共享一个计算单个,请继续。
如果您想创建某种类层次结构,但仍希望您的各个viewmodel实例具有各自的可观察对象,那么您无法通过原型完成。
背景:JavaScript既没有类(抽象对象描述)也没有基于类的继承(分层抽象对象描述)。 JavaScript具有对象(由构造函数生成)和原型链(单个链接的对象列表)。原型链中的所有内容都在对象构造函数创建的所有实例之间进行物理共享。
答案 2 :(得分:2)
看起来你想要的是一个不会允许无法通过验证的分配的可观察对象。您可以使用普通可观察量的扩展器来实现此目的:
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永远不会使用无效值,则可以使用计算(结构很像Anders'解决方案)。
function constrainedObservable(constraint) {
var value = ko.observable();
return ko.computed({
read: value,
write: function (newValue) {
if (constraint(newValue)) {
value(newValue);
}
}
});
}
演示http://jsfiddle.net/o641v37L/1/(取消注释使用计算的分配)