是否有必要在Knockout自定义绑定中取消绑定/关闭JQuery click事件?

时间:2016-11-06 13:43:25

标签: jquery knockout.js

鉴于下面的场景,是否有必要使用ko.utils.domNodeDisposal.addDisposeCallback取消绑定自定义绑定处理程序init中的click事件?或者Knockout是否有自己的机制来自动处理/解除在自定义绑定处理程序中创建的事件?

示例:

<li>
   <a id='aTagId' data-bind='something'></a>
   <button data-bind: myCustomBinding:{}>       
</li>

ko.bindingHandlers.myCustomBinding=
{
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext)
    {
        $('#aTagId').on('click', function() { /*something in here*/ });

        // Is this code necessary?      
        ko.utils.domNodeDisposal.addDisposeCallback(element, function ()
        {
            $('#aTagId').off('click');
        });
    }
}

注意:请不要问我为什么我不能将myCustomBinding放在<a>标记中:)

1 个答案:

答案 0 :(得分:1)

我认为附加到长生活对象(windowdocument等)的事件处理程序是有意义的:

ko.bindingHandlers.myBinding = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var handler = function () {};

        $(window).on("resize", handler);

        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            $(window).off("resize", handler);
        });
    })
};

另见 - http://www.knockmeout.net/2014/10/knockout-cleaning-up.html

但在你的场景中

首先当您尝试拨打off时,您的元素已被移除:

ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
   $('#aTagId').off('click'); //<== $('#aTagId').length is 0
});

您可以按如下方式重写它:

var $aTag = $('#aTagId').on('click', function() {});

ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
 $aTag.off('click');
});

但其次淘汰赛有自己的机制来自动处理/取消绑定事件。它正在运行jQuery.cleanData

// Perform cleanup needed by external libraries (currently only jQuery, but can be extended)
ko.utils.domNodeDisposal["cleanExternalData"](node);

...
"cleanExternalData" : function (node) {
   // Special support for jQuery here because it's so commonly used.
   // Many jQuery plugins (including jquery.tmpl) store data using jQuery's equivalent of domData
   // so notify it to tear down any resources associated with the node & descendants here.
   if (jQueryInstance && (typeof jQueryInstance['cleanData'] == "function"))
     jQueryInstance['cleanData']([node]);
}

https://github.com/knockout/knockout/blob/241c26ca82e6e4b3eaee39e3dc0a92f85bc1df0c/src/utils.domNodeDisposal.js#L88-L94

这样您的处理程序将自动处理

enter image description here