knockout.js 当源为空/未定义时敲除JS绑定

bjg7j2ky  于 2022-11-10  发布在  其他
关注(0)|答案(6)|浏览(107)

是否 有 更 短/更 清晰 的 方法 来 进行 空/未 定义 测试 ?

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

中 的 每 一 个
而 不是

data-bind="options: SelectedBusinessLine() ? SelectedBusinessLine().Clusters() : [],

格式
我 想

data-bind="options: SelectedBusinessLine().Clusters(),

格式
差不多 ( )
或者 至少 使用 一 个 更 简单 的 空 运算 符 检查 ' ? ? ' SelectedBusinessLine ? ? [ ]
或 自动 检查 空 值 或 静默 失败 的 绑定 参数 。
有 什么 想法 , 如果 这 是 可能 的 ?

pzfprimi

pzfprimi1#

This page提供了几种解决方案。相关部分如下:
防止空对象
如果你有一个包含一个对象的可观察对象,并且你想绑定到这个对象的属性,那么你需要小心它是否有可能是空的或者未定义的。你可以这样写你的绑定:

<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,那么它就不会呈现任何内容。因此,您不会像在原始绑定中那样看到unknown。然而,它确实有简化绑定的额外好处,因为您现在可以直接指定属性名而不是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,但它仍然相当冗长。
另一个选择是创建一个扩展的可观察性,它提供了一种安全的方式来访问属性,同时仍然允许实际值为空。

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为空时,它至少不会导致错误。
我确实认为在这种情况下,首选的选项是使用模板绑定,特别是当您有许多这样的属性要绑定时。

2ic8powd

2ic8powd2#

一种在excellent page中没有提到的方法被另一个答案引用是使用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>

如果selecteditem为空,则整个UI将消失。

lnlaulya

lnlaulya3#

“With”起作用(可能其他的也起作用...)
但是,使用“With”时,即使存在条件,角色UI也会消失/出现...例如...我需要设置一个Status(true/false)按钮,但前提是Status不为空...

<!-- ko ifnot: Status() == null -->
<span data-bind="if: Status">
    <a class="rk-button rk-red-action" data-bind="click: changeStatus"><i class="rk-ico rk-ico-save"></i>Desativar</a>
</span>
<span data-bind="ifnot: Status">
    <a class="rk-button rk-black-action" data-bind="click: changeStatus"><i class="rk-ico rk-ico-save"></i>Ativar</a>
</span>
<!-- /ko -->

这很管用,在这种情况下.
但有时只是“与”的作品就像西蒙韦弗说!

juzqafwq

juzqafwq4#

上面的大多数解决方案对我来说都不是现成的,因为我只想将其应用于foreach中的单个元素,所以我对公认的答案的方法做了一点修改:

<span data-bind="text: ((typeof info).localeCompare('undefined')) ? info : ''"></span>
3xiyfsfu

3xiyfsfu5#

我更喜欢这种方法
创建自定义绑定

ko.bindingHandlers.safeText = {
    update: function (element, valueAccessor, allBindingsAccessor) {
        try {
            var tryGetValue = valueAccessor()();
            ko.bindingHandlers.text.update(element, valueAccessor());
        } catch (e) {
            ko.bindingHandlers.text.update(element, function () { return ""; });
        }
    }
};

用途

data-bind="safeText: function() { return my().nested.object.property; }

您需要添加的唯一额外内容是使用“function(){ return...}” Package 原始值
但是,这将停止值调用下的所有错误。您可以通过仅查找“未定义”异常来改进自定义绑定。您也可以通过添加默认文本选项来改进此绑定。

drnojrws

drnojrws6#

这些解决方案中的大多数在特定情况下对我不起作用,在这种情况下,我正在设置一个属性:

<div role="combobox" data-bind="attr: {
  'aria-activedescendant': activedescendant() ? activedescendant().id : null
}">
  ...
</div>

templatewith绑定在这里不起作用,因为如果我没有一个活动的后代,那么我的div将是空的。

ko.observable.fn.get = function (propertyName, defaultValue) {
    var
    self = this(),
    propertyValue;

    if (self != null) {
        propertyValue = ko.unwrap(self[propertyName]);
    }

    return propertyValue || defaultValue;
}

它允许我将绑定更改为:

<div role="combobox" data-bind="attr: {
  'aria-activedescendant': activedescendant.get('id')}">
  ...
</div>

相关问题