【问题标题】:Knockout binding handler teardown function?淘汰赛绑定处理程序拆卸功能?
【发布时间】:2012-04-25 21:42:20
【问题描述】:

我有一个淘汰绑定处理程序,它使用 plupload 进行拖放和 ajax 上传。

为了使用 plupload 脚本,我创建了一个 plupload 实例,该实例又将事件侦听器绑定到 DOM 元素。

效果很好。

但是,我有一个“文件夹”列表,当我单击一个文件夹时,我会显示该文件夹中的文件列表。我通过使用 foreach 绑定 selectedFolder().documents 来重用相同的 DOM 元素。

我遇到的问题是,在我的绑定处理程序中,我在 init 函数中完成了所有的 plupload 工作,并且由于我重用了 DOM 元素,它们获得了多个绑定到它们的事件处理程序。这会导致将拖放事件发送到所有处理程序。这意味着如果我在渲染文件列表中放置一个文件,drop 事件也会在所有之前渲染的文件列表上触发。

我正在寻找的是绑定处理程序中的某种拆卸或清理功能,这样我就可以在文件列表未呈现时取消注册所有事件(这是一个词吗?)。

也许我们无法检测到未渲染?那我该如何处理呢?我不希望有一个全局实例,因为这会阻止我同时在多个地方使用绑定。

很抱歉没有给你任何代码。我在手机自动取款机上。

干杯!

【问题讨论】:

    标签: javascript knockout.js


    【解决方案1】:

    您可以注册一个处理程序,该处理程序将在 KO 删除元素时执行(例如重新渲染模板时)。它看起来像:

        //handle disposal (if KO removes by the template binding)
        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            $(element).datepicker("destroy");
        });
    

    因此,在您的“init”函数中,您将为被绑定的元素注册一个 dispose 回调,并且您将有机会运行您想要的任何清理代码。

    【讨论】:

    • 那肯定能解决我的问题。可惜它没有被称为 unrender。谢谢 RP!
    • 如果您正在与其他执行自己的 DOM 操作的库(在单页应用程序中很常见)混合使用,那么您可能需要考虑下面的 jQuery 方法,该方法会触发任何 DOM 删除(不仅仅是那些由淘汰赛触发的)。如果您已经引用了 jQuery,则很有用。
    【解决方案2】:

    我相信这里提供的解决方案只有在 Knockout 是删除 DOM 节点(即,当它重新设置模板时)时才有效。我很难让它在某些条件下触发。在某些情况下,无论您的元素如何被删除,您都需要执行回调;无论是使用 Knockout,还是通过 jQuery.html() 等(尤其是在单页应用程序中)。

    在 jQuery 的帮助下,我酝酿了一种不同的方法来添加这样的钩子。使用特殊事件 API(很好地描述了 here),您可以添加一个方法,当来自 DOM 节点的特定事件是 removed 时执行(在拆卸时发生的事情)。

    如果您将 Knockout 与 jQuery 结合使用,您可以将其包装到一个敲除绑定中,如下所示:

    ko.bindingHandlers.unload = {
        init: function (element, valueAccessor) {
            var eventName = 'your_unique_unLoad_event'; // Make sure this name does not collide
            if (!$.event.special[eventName]) {
                $.event.special[eventName] = {
                    remove: function (o) {
                        o.data.onUnload()
                    }
                };
            }
            $(element).on(eventName, { onUnload: valueAccessor()}, $.noop);
        }
    };
    

    然后你可以像这样在任何元素上使用它:

    <div id="withViewModelMethod" data-bind="unload: aMethodOnMyViewModel" />
    <div id="withInLineMethod" data-bind="unload: function() { /* ... */ }" />
    

    我欠这个SO post的功劳。

    【讨论】:

    • 我不知道你是怎么得到这个 var eventName = '_unique_unLoadEventName____12345'; 只是想了解一下,因为我遇到过类似的情况。
    • 那只是我从帽子里抽出来的一根绳子。它可以是你想要的任何东西,我只是想确保它是独一无二的,并且不会与任何其他插件或添加自己的事件处理程序的 3rd 方代码发生冲突。这个例子有点夸张了..
    • 也许只是将 '_unique_unLoadEventName____12345' 更改为 'your_unique_unLoad_event'
    猜你喜欢
    • 1970-01-01
    • 2014-11-29
    • 2016-01-22
    • 2015-03-23
    • 1970-01-01
    • 1970-01-01
    • 2014-05-29
    • 2017-10-24
    相关资源
    最近更新 更多