2016-08-30 4 views
1

Ich möchte überprüfen, ob jedes Mal, wenn sich die URL geändert hat, ich ein Ereignis auslösen würde. Da gibt es keine pushstate Ereignis folge ich diesem Rat How to get notified about changes of the history via history.pushState?Wie kann sichergestellt werden, dass das Ereignis nur einmal hinzugefügt wird?

(function(history) { 
    var pushState = history.pushState; 
    history.pushState = function(state) { 
    if (typeof history.onpushstate == "function") { 
     history.onpushstate({ 
     state: state 
     }); 
    } 
    return pushState.apply(history, arguments); 
    } 

    function e(event) { 
    console.log("location: " + document.location + ", state: " + JSON.stringify(event.state)); 
    } 
    window.addEventListener('popstate', e); 
    history.onpushstate = e; 
})(window.history) 

jedoch meine lib erlaubt mutliple Instanzen. Wenn ich meine Bibliothek mehrere Male initialisiere, würde ich Nachrichten erhalten, je nachdem wie oft die Bibliothek initialisiert wurde. Ist es trotzdem möglich, dass ich sicherstellen kann, dass nur ein Ereignis angehängt ist, obwohl ich dieses Snippet mehrmals ausgeführt habe?

+0

Sie können eine Schutzvariable wie 'window.pushStateEventCaptured' verwenden und ihren Wert überprüfen, bevor Sie einen Ereignislistener hinzufügen. – Phylogenesis

+2

AFAIK gibt es keine native JS Weise, Listener auf dem gegebenen DOM Element abzurufen (was elegantere Lösung wäre). Wenn Sie das gesagt haben, was verhindert, dass Sie 'if (! Window.isHistoryApplied) ausführen (function (history) {window.isHistoryApplied = true'? – eithed

+0

Haben Sie dies überprüft, weil [irgendwelche ** exakten ** Duplikate verworfen werden sollten] (http : //stackoverflow.com/a/28607536/542251) – Liam

Antwort

1

Eine Möglichkeit, dies zu erreichen, könnte die Verwendung eines zwischengeschalteten Objekts sein. Auf diese Weise können Sie das Ereignis in der Instanz steuern, die Sie entfernen möchten, und es kann problemlos für andere ähnliche Anwendungsfälle erweitert werden. Ich habe eine öffentliche isBound-Boolesche Instanz einer Instanz hinzugefügt, in der Sie überprüfen möchten, ob das Ereignis abonniert wurde.

(function(history) { 
    var pushState = history.pushState; 

    function e(event) { 
    console.log("location: " + document.location + ", state: " + JSON.stringify(event.state)); 
    } 

    function proxyPopstateEvent (evt) { 
    history.pushState = function(state) { 
     if (typeof history.onpushstate == "function") { 
     history.onpushstate({ 
      state: state 
     }); 
     } 
     return pushState.apply(history, arguments); 
    } 

    var proxy = function (e) { 
     this.event = e; 
     this.isBound = false; 

     this.bindPopstateEvent = function() { 
     window.addEventListener('popstate', this.event); 
     history.onpushstate = this.event; 
     this.isBound = true; 
     } 

     this.removePopstateEvent = function() { 
     window.removeEventListener('popstate', this.event); 
     history.onpushstate = {}; 
     } 
    }; 
    window.popstateEventProxy = new proxy(evt); 
    window.popstateEventProxy.bindPopstateEvent(); 
    } 

    if (!window.popstateEventProxy) { 
    proxyPopstateEvent(e); 
    } 
})(window.history) 
+0

Danke, es scheint, als gäbe es keine Möglichkeit, dies zu erreichen, ohne das globale' window' Objekt zu verwenden? – toy

+0

Vielleicht habe ich mit ES6 diese Möglichkeit nicht untersucht. Da Sie eine Bibliothek entwerfen, habe ich eine ES5-Einschränkung angenommen, obwohl es in einer Bibliothekseinstellung etwas unwahrscheinlich erscheint. Aber ich fühle deinen Schmerz, es ist immer eine Schande, den globalen Namensraum zu verschmutzen. – Yoda

Verwandte Themen