【问题标题】:Creating groups with Knockout.js foreach使用 Knockout.js foreach 创建组
【发布时间】:2023-03-05 11:17:01
【问题描述】:

我有一个 html 部分元素,它有一个 Knockout foreach 绑定到我的视图模型上的项目集合。这可以很好地将集合的每个项目呈现到页面垂直下方的 div 上。我现在希望项目根据窗口大小按行分组,因此项目在桌面浏览器上显示为 4 行,但在移动设备上每行只有 1 个。

我确实通过在视图模型中创建组并将我的视图元素与 foreach 绑定到此组属性来实现这一点。这种方法的问题是我的视图模型现在有我认为的一堆视图逻辑,并直接引用窗口对象。我不认为这是不对的。

我已经有一个单独的 js 文件,其中包含特定于视图的逻辑,即用于“slideVisible”之类的自定义 Knockout 绑定。如何将分组逻辑从我的视图模型中移出并移到该文件中?如果未在视图模型中完成分组,我猜我将无法使用 Knockout 的 foreach 绑定?

【问题讨论】:

    标签: mvvm knockout.js


    【解决方案1】:

    如果您需要在 KO 中动态执行此操作,那么这里是一个绑定示例,它包装了普通的 foreach 绑定并创建一个动态计算的计算,该计算返回一个基于“计数”的具有行/列的结构可观察到的。

    ko.bindingHandlers.foreachGroups = {
        init: function(element, valueAccessor) {
             var groupedItems,
                 options = valueAccessor();
    
            //create our own computed that transforms the flat array into rows/columns
            groupedItems = ko.computed({
                read: function() {
                    var index, length, group,
                        result = [],
                        count = +ko.utils.unwrapObservable(options.count) || 1,
                        items = ko.utils.unwrapObservable(options.data);
    
                    //create an array of arrays (rows/columns)
                    for (index = 0, length = items.length; index < length; index++) {
                        if (index % count === 0) {
                           group = [];
                           result.push(group);
                        }
    
                        group.push(items[index]);
                    }
    
                    return result;
                },
                disposeWhenNodeIsRemoved: element
            });  
    
            //use the normal foreach binding with our new computed
            ko.applyBindingsToNode(element, { foreach: groupedItems });
    
            //make sure that the children of this element are not bound
            return { controlsDescendantBindings: true };
        }
    };
    

    你会像这样使用它:

    <div data-bind="foreachGroups: { data: items, count: count }">
        <ul data-bind="foreach: $data">
            <li data-bind="text: $data"></li>
        </ul>
    </div>
    

    这是一个示例:http://jsfiddle.net/rniemeyer/F48XU/

    不过,对于您的具体情况,我可能会:

    • 删除count 选项,只需传入项目
    • init 函数中创建您自己的count observable。
    • 添加一个 resize 事件处理程序,该处理程序运行您的逻辑并适当地更新 count observable。

    它可能看起来像(填写您的特定调整大小逻辑):

    ko.bindingHandlers.foreachGroups = {
        init: function(element, valueAccessor) {
             var groupedItems,
                 data = valueAccessor(),
                 count = ko.observable(1);
    
            ko.utils.registerEventHandler(window, "resize", function() {
               //run your calculation logic here and update the "count" observable with a new value
            });
    
            //create our own computed that transforms the flat array into rows/columns
            groupedItems = ko.computed({
                read: function() {
                    var index, length, group,
                        result = [],
                        itemsPerRow = +ko.utils.unwrapObservable(count) || 1,
                        items = ko.utils.unwrapObservable(data);
    
                    //create an array of arrays (rows/columns)
                    for (index = 0, length = items.length; index < length; index++) {
                        if (index % itemsPerRow === 0) {
                           group = [];
                           result.push(group);
                        }
    
                        group.push(items[index]);
                    }
    
                    return result;
                },
                disposeWhenNodeIsRemoved: element
            });  
    
            //use the normal foreach binding with our new computed
            ko.applyBindingsToNode(element, { foreach: groupedItems });
    
            //make sure that the children of this element are not bound
            return { controlsDescendantBindings: true };
        }
    };
    

    【讨论】:

    • 请注意,给定形式的解决方案将在分组点创建一个新的绑定上下文,因此 $root 和父上下文变得未定义。查看this question 上的答案以查看保留原始绑定上下文的修改。
    猜你喜欢
    • 2012-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多