私が達成しようとしているのは、フィルタリングされた行の要素がDOMから削除されるのではなく非表示になるように、バインディングによって生成されたテーブル行を視覚的にフィルタリングすることです。foreach
このアプローチにより、ユーザーがフィルター条件を変更したときのレンダリング パフォーマンスが大幅に向上します。これが、フィルター条件に応じて更新される計算された監視可能な配列に をバインドしたくない理由です。
このソリューションを、プロジェクトの他の場所で使用できる、すぐに使用できるビルディング ブロックにしたいと考えています。tr
foreach
私が Knockout に精通している限り、最善の方法はカスタム バインディングを実装することです。
このバインディングを使用するつもりだった方法は、次のようなものです。
<tbody data-bind="foreach: unfilteredItems, visibilityFilter: itemsFilter">
<tr>
...
</tr>
</tbody>
whereは、次のように、現在の行が表示されるかどうかに応じてitemsFilter
返される関数です。boolean
self.itemsFilter = function (item) {
var filterFromDate = filterFromDate(), // Observable
filterDriver = self.filterDriver(); // Observable too
return item && item.Date >= filterFromDate && (!filterDriver || filterDriver === item.DriverKey);
};
私がこれまでに持っているバインディングの実装は次のとおりです。
/*
* Works in conjunction with the 'foreach' binding and allows to perform fast filtering of generated DOM nodes by
* hiding\showing them rather than inserting\removing DOM nodes.
*/
ko.bindingHandlers.visibilityFilter = {
// Ugly thing starts here
init: function (elem, valueAccessor) {
var predicate = ko.utils.unwrapObservable(valueAccessor());
predicate();
},
// Ugly thing ends
update: function (elem, valueAccessor) {
var predicate = ko.utils.unwrapObservable(valueAccessor()),
child = ko.virtualElements.firstChild(elem),
visibleUpdater = ko.bindingHandlers.visible.update,
isVisible,
childData,
trueVaueAccessor = function () { return true; },
falseVaueAccessor = function () { return false; };
while (child) {
if (child.nodeType === Node.ELEMENT_NODE) {
childData = ko.dataFor(child);
if (childData) {
isVisible = predicate(childData, child);
visibleUpdater(child, isVisible ? trueVaueAccessor : falseVaueAccessor);
}
}
child = ko.virtualElements.nextSibling(child);
}
}
};
ko.virtualElements.allowedBindings.visibilityFilter = true;
init
オブジェクトを渡さずに述語を呼び出すという醜い部分がわかりますか?
foreach
これがないと、Knockout がupdate
メソッドを最初に呼び出すまでにバインドによって生成された行がない場合、itemsFilter
フィルター関数は呼び出されません。
したがって、オブザーバブルは読み取られず、KO 依存関係追跡メカニズムは、このバインディングがビュー モデル内のオブザーバブルに依存していないと判断します。
また、フィルター オブザーバブル (filterFromDate
およびfilterDriver
) の値が変更さupdate
れると、 が再び呼び出されることはなく、フィルター処理全体が機能しません。
少なくとも関数がパラメーターとして値を待機するようにするフィルター関数への醜い呼び出しを行わないように、この実装(または問題へのアプローチ全体)を改善するにはどうすればよいundefined
ですか?