此页面提供了几种解决方案。相关部分是这个:
防止空对象
如果您有一个包含对象的可观察对象并且您想绑定到该对象的属性,那么您需要小心它是否有可能为空或未定义。您可以编写您的绑定,如:
<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
为 null,则它不会渲染任何内容。因此,您不会像在原始绑定中那样看到未知。但是,它确实具有简化绑定的额外好处,因为您现在可以直接指定属性名称而不是selectedItem().name
. 这是最简单的解决方案。
只是为了探索一些选项,这里有一些选择:
你可以使用一个计算的 observable,就像我们之前做的那样。
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,它提供了一种访问属性的安全方法,同时仍然允许实际值为 null。可能看起来像:
ko.safeObservable = function(initialValue) {
var result = ko.observable(initialValue);
result.safe = ko.dependentObservable(function() {
return result() || {};
});
return result;
};
因此,这只是一个 observable,它还公开了一个名为 safe 的计算 observable,它总是返回一个空对象,但实际的 observable 可以继续存储 null。
现在,您可以像这样绑定它:
<div data-bind="text: selectedItem.safe().name"></div>
当它为 null 时,您不会看到未知值,但它至少不会在selectedItem
为 null 时导致错误。
我确实认为在这种情况下首选的选项是使用模板绑定,特别是如果您有许多这些属性要绑定。