2012-04-25 12 views
24

Ich habe einen Knockout-Binding-Handler, der plupload für Drag & Drop und Ajax-Uploads verwendet.Knockout binding handler teardown funktion?

Um das plupload-Skript zu verwenden, erstelle ich eine Instanz von plupload, die wiederum Ereignis-Listener an DOM-Elemente bindet.

Das funktioniert gut.

Ich habe jedoch eine Liste von "Ordnern" und wenn ich auf einen Ordner klicke, zeige ich eine Liste von Dateien in diesem Ordner an. Ich verwende die gleichen DOM-Elemente dafür, indem ich selectedFolder(). Dokumente mit foreach binde.

Das Problem, das ich habe, ist, dass in meinem Bindungshandler ich alle meine plupload Sachen in der init Funktion mache und da ich die DOM Elemente wiederverwende, bekommen sie mehrere Ereignishandler, die an sie gebunden sind. Dadurch werden die Drag & Drop-Ereignisse an alle Handler gesendet. Wenn ich also eine Datei in die Liste der gerenderten Dateien verschiebe, wird das Ereignis drop auch auf allen zuvor gerenderten Dateilisten ausgelöst.

Was ich suche ist eine Art Teardown oder Cleanup-Funktion im Bindungs-Handler, so dass ich alle Ereignisse aufheben kann, wenn eine Dateiliste ungerendert wird (ist das ein Wort?).

Vielleicht können wir das Unrendering nicht erkennen? Wie würde ich das dann handhaben? Ich würde es vorziehen, keine globale Instanz zu haben, da dies mich daran hindern würde, die Bindung an mehreren Orten gleichzeitig zu verwenden.

Es tut uns leid, Ihnen keinen Code zu geben. Ich bin auf meinem Handy atm.

Prost!

Antwort

32

Sie können einen Handler registrieren, der immer dann ausgeführt wird, wenn KO Elemente entfernt (z. B. wenn eine Vorlage erneut gerendert wird). Es sieht aus wie:

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

in Ihrem „init“ -Funktion So würden Sie einen dispose Rückruf für das Element registrieren, die gebunden wird, und Sie würden die Möglichkeit haben, zu laufen, was clean-up Code, den Sie mögen.

+0

Das würde definitiv mein Problem lösen. Schade, dass es nicht als Unrender genannt wurde. Danke RP! –

+0

Wenn Sie sich mit anderen Bibliotheken zusammenschließen, die ihre eigene DOM-Manipulation durchführen (was in einseitigen Anwendungen üblich ist), sollten Sie die jQuery-Methode unterhalb berücksichtigen, die für jede DOM-Entfernung ausgelöst wird (nicht nur die durch Knockout ausgelösten). Nützlich, wenn Sie bereits auf jQuery verweisen. –

3

Ich glaube, die hier zur Verfügung gestellte Lösung wird nur funktionieren, wenn Knockout derjenige ist, der den DOM-Knoten entfernt (dh wenn es Vorlagen rejigs). Es fiel mir schwer, es unter bestimmten Bedingungen auszulösen. Es kann Situationen geben, in denen Sie einen Callback ausführen müssen, unabhängig davon, wie Ihr Element entfernt wurde. Sei es mit Knockout, oder über jQuery.html(), etc. (besonders in einer einzelnen Seitenanwendung).

Ich gebraut einen anderen Ansatz für das Hinzufügen eines solchen Hook mit ein wenig Hilfe von jQuery. Unter Verwendung der speziellen Ereignis-API (die gut beschrieben sind here), können Sie eine Methode hinzufügen, die ausgeführt wird, wenn ein bestimmtes Ereignis removed von einem DOM-Knoten ist (etwas, das auf Teardown geschieht).

Wenn Sie Knockout in Verbindung mit jQuery verwenden, können Sie diese in eine Knockout wickeln Bindung etwas wie folgt aussehen:

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); 
    } 
}; 

Sie können diese dann verwenden, um auf ein beliebiges Element wie folgt aus:

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

Ich schulde diese SO post Credits.

+0

Ich bin nicht sicher, wie Sie das bekommen haben ** var eventName = '_unique_unLoadEventName ____ 12345'; ** Ich versuche nur zu verstehen, weil ich in eine ähnliche Situation geraten bin. – nimgrg

+0

Das ist nur eine Schnur, die ich aus einem Hut gezogen habe. Es kann alles sein, was Sie wollen, ich wollte nur sicherstellen, dass es einzigartig ist und nicht mit anderen Plugins oder Drittanbieter-Code kollidieren, die ihre eigenen Event-Handler hinzufügen würde. Es ist leicht übertrieben in diesem Beispiel .. –

+0

vielleicht ändern Sie einfach '_unique_unLoadEventName____12345' zu 'your_unique_unLoad_event' –

Verwandte Themen