这个页面提供了几种解决方案。相关部分是:
防止 null 对象
如果您有一个包含对象的可观察对象,并且您想要绑定到该对象的属性,那么如果存在为 null 或未定义的情况,则需要小心。您可以编写如下绑定:
<span data-bind="text: selectedItem() ? selectedItem().name() : 'unknown'"></span>
有多种处理此问题的方法。首选方式是简单地使用模板绑定:
var viewModel = {
items: ko.observableArray(),
selectedItem: ko.observable()
};
<ul data-bind="template: { name: 'editorTmpl', data: selectedItem }"></ul>
<script id="editorTmpl" type="text/html">
<li>
<input data-bind="value: name" />
</li>
</script>
使用这种方法,如果selectedItem
为空,则不会渲染任何内容。因此,您将不会像在原始绑定中那样看到未知的结果。但是,它有一个额外的好处,可以简化绑定,因为现在您可以直接指定属性名称,而不需要selectedItem().name
。这是最简单的解决方案。
只是为了探索一些选项,这里有几个替代方案:
您可以像以前一样使用计算可观察对象。
viewModel.selectedItemName = ko.computed(function() {
var selected = this.selected();
return selected ? selected.name() : 'unknown';
}, viewModel);
然而,这会给我们的视图模型增加一些臃肿的代码,而且我们可能需要为许多属性重复这个过程。
你可以使用自定义绑定,比如:
<div data-bind="safeText: { value: selectedItem, property: 'name', default: 'unknown' }"></div>
ko.bindingHandlers.safeText = {
update: function(element, valueAccessor, allBindingsAccessor) {
var options = ko.utils.unwrapObservable(valueAccessor()),
value = ko.utils.unwrapObservable(options.value),
property = ko.utils.unwrapObservable(options.property),
fallback = ko.utils.unwrapObservable(options.default) || "",
text;
text = value ? (options.property ? value[property] : value) : fallback;
ko.bindingHandlers.text.update(element, function() { return text; });
}
};
这个方案比原来的好吗?我认为可能不是。它确实避免了我们绑定中的JavaScript,但仍然相当冗长。
另一个选项是创建一个增强型的observable,提供一种安全访问属性的方式,同时仍允许实际值为空。可以像这样:
ko.safeObservable = function(initialValue) {
var result = ko.observable(initialValue);
result.safe = ko.dependentObservable(function() {
return result() || {};
});
return result;
};
所以,这只是一个可观察对象,同时还公开了一个计算的可观察对象,名为safe,它将始终返回一个空对象,但实际的可观察对象仍然可以存储null。
现在,你可以像这样绑定它:
<div data-bind="text: selectedItem.safe().name"></div>
当selectedItem
为null时,您将看不到未知值,但它至少不会导致错误。
我认为,在这种情况下,首选选项是使用模板绑定,特别是如果您有许多这些属性要绑定。