45

null/未定義のテストを行うためのより短い/よりクリーンな方法はありますか?

<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(),

() を与えるか取る

または、少なくともより単純な null 演算子チェック '??' 選択したビジネスライン ?? []

または、null またはサイレント フェイルを自動チェックするバインディング パラメータ。

これが可能であれば、何かアイデアはありますか?

4

6 に答える 6

78

このページでは、いくつかのソリューションを提供します。関連する部分は次のとおりです。

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は、null の場合、何もレンダリングされません。したがって、元のバインディングのように不明は表示されません。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 を回避しますが、それでもかなり冗長です。

もう 1 つのオプションは、実際の値を null にすることを許可しながら、プロパティにアクセスするための安全な方法を提供する拡張オブザーバブルを作成することです。次のようになります。

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>

不明な値が null の場合は表示されませんが、selectedItemnull の場合は少なくともエラーは発生しません。

この場合、特にバインドするこれらのプロパティが多数ある場合は、テンプレート バインディングを使用することをお勧めします。

于 2012-07-08T23:52:24.167 に答える
4

「With」は機能します(おそらく他のものも機能します...)

しかし、「With」を使用すると、内部に条件があってもロール UI が消えたり表示されたりします...たとえば...ステータス (true/false) ボタンを設定する必要がありますが、ステータスが null でない場合のみ.. .

<!-- 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 -->

これは機能します。この場合。

しかし、Simon_Weaver が言ったように、"With" だけが機能する場合もあります。

于 2013-07-17T15:17:59.087 に答える
1

これらのソリューションのほとんどは、属性を設定している特定のケースでは機能しません。

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

ここではtemplateandwithバインディングは機能しません。アクティブな子孫がなければ、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>
于 2013-09-18T23:03:23.833 に答える
1

私はこの方法を好む

カスタム バインディングを作成する

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 ... }' でラップすることです

ただし、これにより、値呼び出しの下のすべてのエラーが停止します。「未定義」の例外のみを探すことで、カスタム バインディングを改善できます。デフォルトのテキスト オプションを追加して、このバインドを改善することもできます。

于 2013-03-06T11:32:28.537 に答える