当源为null/undefined时,KnockoutJS绑定

Zap*_*ila 41 binding knockout.js

是否有更短/更清晰的方法来进行null/undefined测试?

<select data-bind="options: SelectedBusinessLine() ? SelectedBusinessLine().Clusters() : [],
                               optionsText: 'Title',
                               value: SelectedCluster,
                               optionsCaption: 'Select Cluster..'">
            </select>
Run Code Online (Sandbox Code Playgroud)

代替

data-bind="options: SelectedBusinessLine() ? SelectedBusinessLine().Clusters() : [],
Run Code Online (Sandbox Code Playgroud)

我想要

data-bind="options: SelectedBusinessLine().Clusters(),
Run Code Online (Sandbox Code Playgroud)

给(或)拿()

或者至少一个更简单的空操作符检查'??' SelectedBusinessLine ?? []

或者是一个自动检查null或silent失败的绑定参数.

任何想法,如果这是可能的?

use*_*736 74

该页面提供了几种解决方案 相关部分是这一个:

保护null对象

如果你有一个包含一个对象的observable,并且想要绑定到该对象的属性,那么如果它有可能为null或未定义,则需要小心.你可以写下你的绑定:

<span data-bind="text: selectedItem() ? selectedItem().name() : 'unknown'"></span>
Run Code Online (Sandbox Code Playgroud)

有很多方法可以处理这个问题.首选方法是简单地使用模板绑定:

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>
Run Code Online (Sandbox Code Playgroud)

使用此方法,如果selectedItem为null,则它不会呈现任何内容.所以,你不会看到原始绑定中的未知.但是,它确实具有简化绑定的额外好处,因为您现在可以直接指定属性名称而不是selectedItem().name.这是最简单的解决方案.

仅仅为了探索一些选项,这里有一些选择:

您可以使用计算的observable,就像我们之前做的那样.

viewModel.selectedItemName = ko.computed(function() {
  var selected = this.selected();
  return selected ? selected.name() : 'unknown';
}, viewModel);
Run Code Online (Sandbox Code Playgroud)

然而,这又为我们可能不想要的视图模型增加了一些膨胀,我们可能不得不为许多属性重复这一点.

您可以使用自定义绑定,如:

<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; });
  }
};
Run Code Online (Sandbox Code Playgroud)

这比原来好吗?我想说可能不是.它确实避免了我们绑定中的JavaScript,但它仍然非常冗长.

另一种选择是创建一个增强的observable,它提供了一种访问属性的安全方法,同时仍允许实际值为null.看起来像:

ko.safeObservable = function(initialValue) {
  var result = ko.observable(initialValue);
  result.safe = ko.dependentObservable(function() {
    return result() || {};
  });

  return result;
};
Run Code Online (Sandbox Code Playgroud)

所以,这只是一个observable,它还公开了一个计算的observable,它将始终返回一个空对象,但实际的observable可以继续存储null.

现在,你可以绑定到它:

<div data-bind="text: selectedItem.safe().name"></div>
Run Code Online (Sandbox Code Playgroud)

当它为null时,您不会看到未知值,但是当它为null时,它至少不会导致错误selectedItem.

我认为首选的选项是在这种情况下使用模板绑定,特别是如果您要绑定许多这些属性.

  • 这里的模板示例实际上没有用 - 如果模板的"数据"部分为null,那么我就会遇到绑定错误.我能够通过对模板绑定应用"if"属性来解决这个问题:<div data-bind ="template:{if:item(),data:item(),name:'someTemplate'}"> </ DIV> (4认同)

Sim*_*ver 59

在另一个答案所引用的其他优秀页面中未提及的一种方法是使用with

<div data-bind="with: selecteditem">
    <form>
        <fieldset>
            <div>
                <label>first name</label>
                <input data-bind="value: firstname"></input>
            </div>
            <div>
                <label>lasst name</label>
                <input data-bind="value: lastname"></input>
            </div>
        </fieldset>
        <div>
            <a href="#" data-bind="click: $root.savechanges">Save</a>
        </div>
    </form>
</div>
Run Code Online (Sandbox Code Playgroud)

如果selecteditem为null,则整个UI将消失.

  • 完美.+1! (2认同)
  • 这应该是公认的答案.当前接受的答案太复杂,不能使这样简单的要求工作.这是`with`的核心功能之一. (2认同)