foreach完成渲染时的自定义绑定

时间:2013-05-16 15:58:20

标签: javascript knockout.js knockout-2.0

我有一个可观察的数组,其中的项目绑定到ul。添加项目后,我需要计算整组li项的宽度,以便将ul元素的宽度设置为子li元素的总宽度

如何使用foreach绑定进行此操作?

<div>
    <h2 data-bind="visible: items().length">Test</h2>
    <ul data-bind="foreach: { data: items, afterAdd: $root.myAfterAdd }">
        <li data-bind="text: name"></li>
    </ul>
</div>

JavaScript:

var viewModel = {
    items: ko.observableArray([
        { name: "one" },
        { name: "two" },
        { name: "three" }
        ]),
    myAfterAdd: function(element) {
        if (element.nodeType === 1) {
           alert("myAfterAdd");   
        }
    },
    addItem: function() {
        this.items.push({ name: 'new' });
    }
};


ko.applyBindings(viewModel);

// once foreach has finished rendering I have to set the width 
// of the ul to be the total width of the children!

我尝试使用afterAdd,因此我可以在添加每个元素后'更新'ul的宽度,不幸的是我发现afterAdd不会触发初始项目!它只会在推送其他项目时触发......

请注意li项内的内容宽度未知:)

有关示例方案,请参阅this fiddle

3 个答案:

答案 0 :(得分:2)

我有类似的问题。您可以使用它来进行初始计算:

ko.bindingHandlers.mybinding {
        init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
            var foreach = allBindings().foreach,
                subscription = foreach.subscribe(function (newValue) {
                // do something here (e.g. calculate width/height, use element and its children)
                subscription.dispose(); // dispose it if you want this to happen exactly once and never again.
            });
        }
}

答案 1 :(得分:1)

经过大量'谷歌搜索',我找到了解决方案。使用foreach实现此目的的方法是注册自定义事件处理程序:

ko.bindingHandlers.runafter = {
    update: function (element, valueAccessor, allBindingsAccessor) {
        var value = valueAccessor();
        setTimeout(function (element, value) {
            if (typeof value != 'function' || ko.isObservable(value))
                throw 'run must be used with a function';

            value(element);
        }, 0, element, value);
    }
};

只要发生更新,该处理程序就会触发(如果值不是可观察的,则只触发一次)。

更重要的是,一旦foreach循环完成,它就会触发!

请参阅here

答案 2 :(得分:0)

你可以这样做:

var viewModel = {
    items: ko.observableArray([
        { name: "one" },
        { name: "two" },
        { name: "three" }
        ]),
    myAfterAdd: function(event) {
        if (event.originalEvent.srcElement.nodeType === 1) {
           alert("myAfterAdd");   
        }
    },
    addItem: function() {
        this.items.push({ name: 'new' });
    }
};


$('#bucket').bind('DOMNodeInserted DOMNodeRemoved', viewModel.myAfterAdd);

ko.applyBindings(viewModel);

哪个桶是ul元素

<强> See fiddle

我希望它有所帮助