gpt4 book ai didi

javascript - 自定义绑定(bind)中正确的依赖项跟踪

转载 作者:行者123 更新时间:2023-12-02 15:39:38 26 4
gpt4 key购买 nike

我想要实现的是以视觉方式过滤由foreach绑定(bind)生成的表行,其方式是tr元素被过滤掉的行将被隐藏,而不是从 DOM 中删除。
当用户更改过滤条件时,此方法可显着提高渲染性能。这就是为什么我不希望将 foreach 绑定(bind)到计算的可观察数组,该数组根据过滤条件进行更新。
我希望这个解决方案成为一个随时可用的构建 block ,我可以在项目的其他地方使用它。

就我对 Knockout 的熟悉程度而言,最好的方法是实现自定义绑定(bind)。

我打算使用此绑定(bind)的方式是这样的:

<tbody data-bind="foreach: unfilteredItems, visibilityFilter: itemsFilter">
<tr>
...
</tr>
</tbody>

其中 itemsFilter 是一个返回 boolean 的函数,具体取决于当前行是否可见,如下所示:

    self.itemsFilter = function (item) {
var filterFromDate = filterFromDate(), // Observable
filterDriver = self.filterDriver(); // Observable too

return item && item.Date >= filterFromDate && (!filterDriver || filterDriver === item.DriverKey);
};

这是我迄今为止的绑定(bind)实现:

/*
* 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 部分?

如果没有这个,如果 Knockout 第一次调用 update 方法时 foreach 绑定(bind)没有生成任何行,则 itemsFilter 过滤函数不会被调用。
因此,不会读取任何可观察量,并且 KO 依赖跟踪机制决定此绑定(bind)不依赖于我的 View 模型中的任何可观察量。
当过滤器可观察值(filterFromDatefilterDriver)的值发生更改时,update 将永远不会再次被调用,整个过滤也不会发生。工作。

如何改进此实现(或解决问题的整个方法),以免对过滤器函数进行丑陋的调用,这至少会使函数等待 undefined 值作为参数?

最佳答案

您可以在 tr 上使用 visible 绑定(bind),并将其绑定(bind)到使用 $data 作为参数的函数调用的结果。下面是一个小演示。您选择的值都会从表中过滤掉。

var vm = {
rows: ko.observableArray(['One', 'Two', 'Three']),
selected: ko.observable('One'),
isVisible: function(row) {
return row !== vm.selected();
}
};

ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="options:rows, value:selected"></select>
<table border="1" data-bind="foreach:rows">
<tr data-bind="visible:$parent.isVisible($data)">
<td data-bind="text:$data"></td>
</tr>
</table>

关于javascript - 自定义绑定(bind)中正确的依赖项跟踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32684610/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com