Knockout 和 JQueryUI 绑定不调用更新回调

Knockout and JQueryUI binding does not call update callback

当使用自定义绑定创建 foreach 绑定时,"update:" 回调在将新元素推送到视图模型时未被调用。 但是,正在创建新的跨度(不是手风琴)项目。

<div data-bind="foreach:items, koAccordion: {}">
<div>
<span data-bind="text: id"></span>
</div>
<div>
<span data-bind="text: name"></span>
</div>
</div>

脚本:

    ko.bindingHandlers.koAccordion = {
         init:function(element, valueAccessor, allBindingsAccessor, viewModel,bindingContext) {
                console.log("INITIALIZATION CALLBACK");
                $(element).accordion();
            },
    update:function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
                console.log("UPDATING CALLBACK");
                $(element).accordion('destroy').accordion();
            }
    };
function Item(id,name,description){
    this.id = ko.observable(id);
    this.name = ko.observable(name);
    this.description = ko.observable(description);
}


var viewModel = {
    items:ko.observableArray([new Item("New Id","New Name","New Description")]),
    addItem:function(id,name,description){
        viewModel.items.push(new Item(id,name,description))
    }    
};


ko.applyBindings(viewModel);

绑定的 update() 函数在其依赖项更改时被调用。

这意味着您必须在 update() 的正文中触发 knockout 的依赖项跟踪。这通常是通过生成可观察对象的基础值(换句话说,通过调用它)来实现的。

通常您也会在函数内部使用该值,但在这种情况下您只需要该步骤以便依赖项跟踪注意到有一个订阅者。

这会起作用:

<!--                                         pass observable here -->
<div data-bind="foreach: items, koAccordion: items">
    <div>
        <span data-bind="text: id"></span>
    </div>
    <div>
        <span data-bind="text: name"></span>
    </div>
</div>

ko.bindingHandlers.koAccordion = {
    init: function (element, valueAccessor) {
        $(element).accordion();

        // properly destroy the widget when the element gets removed
        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            $(element).accordion('destroy');
        });
    },
    update: function (element, valueAccessor) {
        // unwrap the observable: this registers an implicit subscription
        ko.unwrap(valueAccessor());
        $(element).accordion('refresh');
    }
};

但本质上您可以完全跳过 update 回调并改用显式订阅:

ko.bindingHandlers.koAccordion = {
    init: function (element, valueAccessor) {
        var items = valueAccessor(),
            subscription;

        $(element).accordion();

        // set up an explicit subscription
        subscription = items.subscribe(function () {
            $(element).accordion('refresh');
        });

        // properly destroy the widget when the element gets removed
        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            subscription.dispose();
            $(element).accordion('destroy');
        });
    }
};

也就是说,您应该使用成熟的 jQueryUI 自定义绑定库,而不是自己动手:http://gvas.github.io/knockout-jqueryui/