Javascript-gebeurtenis die wordt uitgevoerd voordat de pagina wordt gewijzigd

Is er zoiets?

Ik weet dat ik mijn functie kan koppelen aan de klikgebeurtenis van alle links, maar er zijn andere situaties waarin een pagina wordt gewijzigd, zoals vernieuwen of wanneer een ander script het venster verandert.location


Uiteindelijk deed ik het door een string te sturen via postMessage van het unload-evenement, zoals dit:

$(window).bind('unload', function(e){
  window.parent.postMessage('unloading');
});

in het bovenliggende document:

$(window).bind('message', function(e){     
  if(e.originalEvent.data == 'unloading'){
   //ajax stuff here
  }
});

Het lijkt te werken. Ik had waarschijnlijk moeten vermelden dat er een iframe bij betrokken is :)

6
Zal klaar voor pagina niet werken?
toegevoegd de auteur Esteban Araya, de bron
maar wordt dat niet uitgevoerd nadat de pagina is geladen? Ik heb het eerder nodig, zodat ik een ajax-verzoek kan starten en een aantal dingen kan bijwerken en de pagina kan laden
toegevoegd de auteur Alex, de bron
Je kunt niet echt vertrouwen op de mogelijkheid om iets te doen voordat een pagina wordt gelost. De gebruiker kan bijvoorbeeld de computer abrupt afsluiten.
toegevoegd de auteur Pointy, de bron

3 antwoord

Er is de beforeunload -gebeurtenis die wordt geactiveerd wanneer de pagina wordt afgebroken (ofwel om een ​​link te volgen, of als het venster wordt gesloten, of vernieuwd, etc.). Voorbeeld:

window.onbeforeunload = function(event) {
    var s = "You have unsaved changes. Really leave?";

    event = event || window.event;
    if (event) {
       //This is for IE
        event.returnValue = s;
    }

   //This is for all other browsers
    return s;
}

Er zijn, om voor de hand liggende redenen, zeer strikte limieten voor wat u kunt doen in de handler van de beforeunload -gebeurtenis, en zoals u hierboven ziet beforeunload hebben handlers een andere handtekening dan normale event handlers. Kortom, uw code kan asynchroon niets doen, kan geen nieuwe vensters openen en kan de gebeurtenis niet annuleren. Het kan een tekenreeks retourneren, en als dat het geval is, zal de browser een venster openen met de vraag of je de pagina echt wilt verlaten en je string in die pop-up wilt opnemen.

Uit je reactie op de vraag:

Ik heb het eerder nodig, zodat ik een ajax-verzoek kan starten en een aantal dingen kan bijwerken ...

Wanneer de pagina wordt afgebroken, kunt u meestal wegkomen met een synchrone ajax-aanroep ( async: false ) mits dit niet te lang duurt. Dit is geen geweldig idee en ik zou het ten zeerste aanbevelen dit te vermijden als je kunt (bijvoorbeeld met tussentijdse saves), omdat het onder andere een vertraging introduceert bij het sluiten van de pagina. Maar als u de oproep synchroon maakt (in tegenstelling tot de standaard en sterk de voorkeur hebbende, asynchrone aanroep), kunt u dat meestal doen met de browser. Natuurlijk heeft het geen zin als de browser abrupt wordt beëindigd (crasht, wordt geforceerd gesloten door de gebruiker, enz.).

Merk op dat de async vlag wordt verouderd en verwijderd van jQuery ( ticket ). Ik denk dat ze van plan zijn om het in 1.8 af te schaffen en het in 1.9 te verwijderen, maar het is niet hyper-vrij van de blogpost en het ticket.

19
toegevoegd
niet zeker wat het verschil is tussen async vs sync?
toegevoegd de auteur Alex, de bron
@Esailija: bedankt. Wat ik bedoel is dat hoewel Chrome het tabblad uit de gebruikersinterface verwijdert, het venster en de bijbehorende structuren mogelijk niet uit het geheugen worden verwijderd, zodat de functie 'Tab opnieuw openen' snel werkt. (Of, natuurlijk, het kan goed.) Het kan dus zijn dat het verzoek na een seconde niet wordt vernietigd, ook al verdwijnt de tab uit de gebruikersinterface. of het zou kunnen dat het is. (Bedankt voor de info hierover, trouwens)
toegevoegd de auteur T.J. Crowder, de bron
@Somebodyisintrouble: Gewoon geprobeerd: ik opende een venster en navigeerde naar een site en sloot vervolgens het venster. In mijn resterende venster heb ik het tabblad "Openen opnieuw geopend" en deze heeft het venster opnieuw geopend en de site teruggezet! Merk op dat dit verschilt van de ook nuttige test van Esailija.
toegevoegd de auteur T.J. Crowder, de bron
@Esailija: Op het tabblad, was dat hoe lang het duurde voordat het tabblad uit de gebruikersinterface verdween? Omdat onthouden Chrome houdt tabbladen rond (voor de functie "opnieuw openen tabblad").
toegevoegd de auteur T.J. Crowder, de bron
@Alex: in deze context zorgt een synchroon -verzoek ervoor dat de code wordt gewacht (de browser vergrendelen tot de verzoek-complets), een asynchrone -aanroep zorgt ervoor dat JavaScript op de pagina actief blijft - later wanneer de aanvraag is voltooid, wordt uw succes - of fout -hulpprogramma aangeroepen.
toegevoegd de auteur T.J. Crowder, de bron
@Esailija: Ja, het is een van de weinige use-cases voor synchrone ajax (hoewel het introduceren van zo'n vertraging geen geweldige UX is). Zoals ik al zei, kun je niets asynchroon doen.
toegevoegd de auteur T.J. Crowder, de bron
Ik heb zojuist in Chrome getest en als u het ververst, wacht het ten minste 5 seconden (ik had sleep (5); op de server). Als u het tabblad sluit, wacht het gedurende 1 seconde (mijn benadering) en sluit het vervolgens.
toegevoegd de auteur Esailija, de bron
@Somebodyisintrouble niet als de server uw gegevens niet vroeg genoeg heeft overgenomen T.J. Crowder, ik weet niet zeker wat je bedoelt. Normaal gesproken verdwijnt het direct als ik een tabblad sluit. Met synchrone ajax wachtte het ten minste 1 seconde voordat de tab verdween.
toegevoegd de auteur Esailija, de bron
Ik weet niet zeker of de browser echt vastloopt als het verzoek te lang duurt, maar wacht niet op antwoord en sluit de pagina?
toegevoegd de auteur Esailija, de bron
@Somebodyisintrouble Ik heb een chromen venster getest waarbij het enige tabblad het testtabblad was en het duurde 1 seconde om ook het Chrome-venster te sluiten. (Normaal sluit hij onmiddellijk)
toegevoegd de auteur Esailija, de bron
Het gebruik van synchrone ajax in het evenement heeft voor mij gewerkt (daar gaat nooit sync ajax gebruiken: D)
toegevoegd de auteur Esailija, de bron
@Esailija maar zodra een ajax-verzoek wordt verzonden, werkt het ook nadat de pagina is gesloten
toegevoegd de auteur user1432124, de bron
@ T.J.Crowder wat als het venster direct wordt gesloten
toegevoegd de auteur user1432124, de bron

jQuery heeft de functie lossen :

De gebeurtenis unload wordt naar het vensterelement verzonden wanneer de gebruiker navigeert   weg van de pagina. Dit kan een van de vele dingen betekenen. De gebruiker zou kunnen   klikte op een link om de pagina te verlaten, of typte een nieuwe URL in de   adresbalk. De knoppen voor vooruit en achteruit zullen de gebeurtenis activeren.   Als u het browservenster sluit, wordt de gebeurtenis geactiveerd. Zelfs   een herladen van een pagina zal eerst een unload-evenement maken.

Merk op dat dit moet worden gebonden aan window -object in plaats van document :

$(window).unload(function() {
   //do something
});

U kunt de handler ook binden aan de beforeunload -gebeurtenis:

$(window).bind('beforeunload', function() {
   //do something, preferably ajax request etc
    return 'are you sure?';
});
5
toegevoegd
hm .. in Chrome krijg ik een foutmelding in de console: Geblokkeerde waarschuwing ('ontladen ...') tijdens het ontladen.
toegevoegd de auteur Alex, de bron
De opmerkingen op die jQuery-documentatiepagina suggereren dat deze gebeurtenis mogelijk niet betrouwbaar werkt.
toegevoegd de auteur Pointy, de bron
U hoeft bevestigen of alert niet te doen, u hoeft alleen een string in te voeren en die wordt getoond in het bevestigingsvenster. Met bevestigen etc. krijgt u Geblokkeerd bevestigen ('bent u er zeker van?') Tijdens de voorbelasting.
toegevoegd de auteur Esailija, de bron
Ik heb mijn bericht bewerkt. Ik heb dit getest in Chrome.
toegevoegd de auteur Zbigniew, de bron
@Esailija Heel erg bedankt. Ik heb dit deel gemist. Nu werkt het zoals het hoort :)
toegevoegd de auteur Zbigniew, de bron

Wanneer een pagina opnieuw wordt geladen, is alles wat er eerder was, verdwenen. Dus het lijkt erop dat waar je het over hebt iets is wat je zou doen bij DOMReady of "laden" in de nieuwe pagina, omdat je geen code "kunt pushen" van de vorige pagina naar de nieuwe context.

1
toegevoegd
Nee. Als de link naar een ander domein gaat, maakt het mij niet uit of mijn ajax-verzoek niet wordt geactiveerd. Ik hoef alleen maar een aantal (tijdelijke) dingen bij te werken, die op de volgende pagina van dezelfde site worden gebruikt ..
toegevoegd de auteur Alex, de bron
@ Somebodyisintrouble de hash-waarde maakt niet echt deel uit van de pagina; het maakt deel uit van de URL en wordt alleen overgedragen als de nieuwe URL dezelfde hash gebruikt. Als je op http://foo.bar.com/xyz#hello staat en je klikt op een link naar http://cnn.com/international , dan is de oude hash-waarde is niet beschikbaar op de nieuwe pagina.
toegevoegd de auteur Pointy, de bron
@ Somebodyisintrouble er is geen sprake van dat een manier of de andere in de vraag.
toegevoegd de auteur Pointy, de bron