我认为这一定是一种常见的情况,我想知道在 Knockout 中是否有一个公认的如何处理这个问题的约定。您有一个“是-否”下拉菜单(或一对单选按钮),它的默认值是一个空白项(或两个都未选中,对于单选按钮)。用户必须做出选择才能继续。
这并不能完美地映射到模型中的布尔值,因为实际上存在三个可能的值。真假,没有用户选择。在 C# 中,您可能会考虑使用可为空的布尔值,而在 Java 中,您可能会使用java.lang.Boolean。在这两种情况下,“null”都可能表示没有用户选择。
JavaScript 没有可空值,但由于它不强制使用变量类型,因此您可以采用特定变量可以为 null、true 或 false 的约定,并以与 C# 或 java 中的可空布尔值类似的方式使用它.lang.布尔值。
首先,存在绑定到布尔值的问题。默认情况下,Knockout 希望所有绑定值都是字符串类型。这在此处和此处进行了讨论,RP Niemeyer 提供的解决方案是使用自定义绑定,如下所示:(此示例的链接到 JS Fiddle)
ko.bindingHandlers.booleanValue = {
init: function(element, valueAccessor, allBindingsAccessor) {
var observable = valueAccessor(),
interceptor = ko.computed({
read: function() {
return observable().toString();
},
write: function(newValue) {
observable(newValue === "true");
}
});
ko.applyBindingsToNode(element, { value: interceptor });
}
};
所以我以此为出发点,我想出了这个自定义绑定。它似乎工作。我对社区对此方法的反馈感兴趣。签出jsfiddle 以自己进行试验。这有什么缺点和/或可扩展性问题吗?
ko.bindingHandlers.nullableBooleanValue = {
init: function(element, valueAccessor, allBindingsAccessor) {
var observable = valueAccessor(),
interceptor = ko.computed({
read: function() {
console.log(observable());
console.log(typeof(observable()));
var result = null;
if(observable() === true){
result = "true";
} else if(observable() === false){
result = "false";
} else { // Default is null, which represents no user selection
result = "null";
}
console.log("transforming on read:")
console.log(typeof(observable()));
console.log(observable());
console.log(typeof(result));
console.log(result);
return result;
},
write: function(newValue) {
var result = null;
if(newValue === "true"){
result = true;
} else if(newValue === "false"){
result = false;
} else { // Default is null, which represents no user selection
result = null;
}
console.log("transforming on write:")
console.log(typeof(newValue));
console.log(newValue);
console.log(typeof(result));
console.log(result);
observable(result);
}
});
ko.applyBindingsToNode(element, { value: interceptor });
}
};
var model = {
state: ko.observable(null)
};
ko.applyBindings(model);