是否可以将ko.computed继承到原型class?
Is it possible to inherit ko.computed to a prototype class?
假设我希望 ko.computed 具有以下行为:
- 阅读
- 写
但我想在 ko.computed 属性 内部有一个内部可观察对象,例如:
this.a = ko.computed(function() {
value: ko.observable(null),
read: function() {
return value;
},
write: function(newValue) {
if (newValue) {
value(newValue);
}
}
});
这在某种程度上可能吗?以上都不行。
你可以做到,
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());
你也可以扩展计算使用原型,就像在内部使用它一样
function setPrototypeOf(obj, proto) {
obj.__proto__ = proto;
return obj;
}
已使用喜欢(ko.utils.setPrototypeOf
未导出使用以上代码)
ko.utils.setPrototypeOf(ko.observableArray['fn'], ko.observable['fn']);
我在此处找到的旧答案 可能会帮助您了解如何使用 proto approuch
How can I create a typed collection class in Knockout mapping?
这与此处 回答的问题不完全相同,但非常接近。
最重要的是,不,您实际上不能在原型链中进行计算,因为该计算将在所有视图模型实例之间共享。
如果您打算在多个对象实例之间共享一个计算,请继续。
如果您想创建某种 class 层次结构,但仍希望您的各个视图模型实例具有自己的单独可观察对象,那么您无法通过原型来实现。
背景:JavaScript既没有classes(抽象对象描述)也没有基于class的继承(分层抽象对象描述)。 JavaScript 有对象(由构造函数产生)和原型链(对象的单链表)。原型链中的所有内容都在对象构造函数创建的所有实例之间物理共享。
看起来你想要的是一个不允许验证失败的赋值的可观察对象。你可以在普通的可观察对象上使用扩展器来做到这一点:
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);
}
}
});
}
Demo http://jsfiddle.net/o641v37L/1/(取消注释分配以使用计算)
假设我希望 ko.computed 具有以下行为:
- 阅读
- 写
但我想在 ko.computed 属性 内部有一个内部可观察对象,例如:
this.a = ko.computed(function() {
value: ko.observable(null),
read: function() {
return value;
},
write: function(newValue) {
if (newValue) {
value(newValue);
}
}
});
这在某种程度上可能吗?以上都不行。
你可以做到,
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());
你也可以扩展计算使用原型,就像在内部使用它一样
function setPrototypeOf(obj, proto) {
obj.__proto__ = proto;
return obj;
}
已使用喜欢(ko.utils.setPrototypeOf
未导出使用以上代码)
ko.utils.setPrototypeOf(ko.observableArray['fn'], ko.observable['fn']);
我在此处找到的旧答案 可能会帮助您了解如何使用 proto approuch
How can I create a typed collection class in Knockout mapping?
这与此处
最重要的是,不,您实际上不能在原型链中进行计算,因为该计算将在所有视图模型实例之间共享。
如果您打算在多个对象实例之间共享一个计算,请继续。
如果您想创建某种 class 层次结构,但仍希望您的各个视图模型实例具有自己的单独可观察对象,那么您无法通过原型来实现。
背景:JavaScript既没有classes(抽象对象描述)也没有基于class的继承(分层抽象对象描述)。 JavaScript 有对象(由构造函数产生)和原型链(对象的单链表)。原型链中的所有内容都在对象构造函数创建的所有实例之间物理共享。
看起来你想要的是一个不允许验证失败的赋值的可观察对象。你可以在普通的可观察对象上使用扩展器来做到这一点:
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);
}
}
});
}
Demo http://jsfiddle.net/o641v37L/1/(取消注释分配以使用计算)