Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 自定义绑定中的正确依赖性跟踪_Javascript_Knockout.js_Javascript Databinding - Fatal编程技术网

Javascript 自定义绑定中的正确依赖性跟踪

Javascript 自定义绑定中的正确依赖性跟踪,javascript,knockout.js,javascript-databinding,Javascript,Knockout.js,Javascript Databinding,我试图实现的是可视化地过滤由foreach绑定生成的表行,过滤掉的行的tr元素将被隐藏,而不是从DOM中删除。 当用户更改过滤器条件时,此方法可显著提高渲染性能。这就是为什么我不希望将foreach绑定到根据过滤条件更新的计算可观察数组。 我希望这个解决方案成为我可以在项目的其他地方使用的现成构建块 就我所熟悉的Knockout而言,最好的方法是实现自定义绑定 我打算使用这种绑定的方式如下: <tbody data-bind="foreach: unfilteredItems, visib

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

就我所熟悉的Knockout而言,最好的方法是实现自定义绑定

我打算使用这种绑定的方式如下:

<tbody data-bind="foreach: unfilteredItems, visibilityFilter: itemsFilter">
    <tr>
    ...
    </tr>
</tbody>
    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
部分使用谓词调用,而不向其传递对象

如果没有这一点,如果在第一次敲除调用
update
方法时,
itemsFilter
filter函数不会调用
foreach
绑定生成的行。
因此,不会读取任何观察值,并且KO依赖项跟踪机制决定此绑定不依赖于我的视图模型中的任何观察值。
当过滤器可观测值(
filterFromDate
filterDriver
)发生更改时,
update
将不再被调用,整个过滤将无法工作


如何改进此实现(或问题的整个解决方法)为了避免对筛选函数进行丑陋的调用,这至少会使函数等待一个
未定义的
值作为参数?

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

var-vm={
行数:ko.observearray(['1','2','3']),
选定:可观察的(“一”),
isVisible:函数(行){
返回行!==vm.selected();
}
};
ko.应用绑定(vm)


似乎您可以在
tr
元素上使用一个
可见的
绑定。@Roy:我需要将它绑定到哪些可观察对象?这是一个非常简单的方法,它工作起来很有魅力!非常感谢。非常感谢你的帮助!