7

id Powiedzmy, że jestem na/strona = 1post-redirect-get (PRG) ponowne wstawienie samą stronę w historii w przeglądarkach WebKit

Potem przejdź do/strony id = 2

I dokonuję zmiany na tej stronie, która implementuje wpis, a następnie przekierowuje z powrotem do/page? Id = 2

Mogę nacisnąć raz przycisk wstecz i powrócić do/page? Id = 1, ale w przeglądarce Chrome i Safari na iPhonie muszę dwukrotnie nacisnąć przycisk Wstecz, ponieważ/page? id = 2 jest w historii przeglądarki dwukrotnie. (Gdybym zrobił wiele postów od id = 2, musiałbym nacisnąć wielokrotnie przycisk powrotu, by w końcu powrócić do id = 1).

Pod pewnymi względami wydaje się to normalnym zachowaniem przeglądarki, ponieważ GET jest po prostu wrzucony do historii, ale ponieważ adres URL jest identyczny z poprzednim wpisem, powoduje to słabą wygodę użytkownika, której zwykle unikają inne aplikacje internetowe ... i jest naturalnie omijany w Firefoksie. Czy jest to nieunikniony błąd w przeglądarkach Webkit, czy mogę wdrożyć PRG w inny sposób, aby tego uniknąć?

btw- zachowanie wydaje się być taka sama przekierowanie z 302 lub 303.

UPDATE: Mam wyśmiewali się przykładowy kod ... nie wiem, czy jest to platforma gdzie jak jsfiddle mogę przesłać to, aby zobaczyć w akcji:

form.php:

id=<?=$_REQUEST['id']?> 
<form action="submit.php" method="post"> 
<input type="hidden" name="id" value="<?=$_REQUEST['id']?>"> 
<input type="submit" value="submit"> 
</form> 

submit.php:

<?php 
header("Location: form.php?id=" . $_REQUEST['id']); 
die($_REQUEST['id']); 
?> 

Jeśli uruchamiam na form.php? Id = 4 (wystarczy umieścić go w historii przeglądarki), a następnie przejdź do form.php? Id = 5, a następnie naciśnij przycisk submit (tak, jakby dokonać zmiany w bazie danych), w Firefoksie otrzymuję po jednym wpisie w historii dla każdego; w Chrome otrzymuję jedną pozycję dla id = 4, a następnie dwie pozycje dla id = 5. Dlaczego różnica w zachowaniu? Uważam, że zachowanie Firefoksa jest lepsze, ponieważ dwukrotne trafienie w celu uniknięcia id = 5 jest sprzeczne z intuicją użytkownika.

Odpowiedz

1

Chociaż nie jest to wyjaśnienie tego, co się dzieje, mam sposób obejścia tego, którego używam we wszystkich moich aplikacjach. Pierwsza część kodu:

form.php będzie wyglądać następująco:

id=<?=$_REQUEST['id']?> 
<form action="submit.php" target="iframe" method="post"> 
    <input type="hidden" name="id" value="<?=$_REQUEST['id']?>"> 
    <input type="submit" value="submit"> 
</form> 

submit.php tak:

<?php 
    header("Location: form.php?id=" . $_REQUEST['id']); 
    die($_REQUEST['id']); 
? 
<script> 
    window.parent.location.reload(); 
</script> 

To dokumenty z kilku dodatkowych rzeczy w tagu <form> i nowiutki <script> tag.

Chciałbym również mieć iframe gdzieś w dokumencie tak:

<iframe name="iframe"></iframe> 

więc wytłumaczyć. Zamiast przechodzić do nowej witryny iz powrotem za każdym razem, gdy trzeba dokonać zmiany, wystarczy załadować submit.php w iframe w istniejącym dokumencie. Stąd część target="iframe".

Po załadowaniu iframe, oznacza to, że zmiany zostały wprowadzone, odświeżasz oryginalną stronę, aby odzwierciedlić te zmiany, a więc część window.parent.location.reload();. Ponieważ strona po prostu przeładowuje się, nie umieszcza drugiej pozycji w historii.

Mam nadzieję, że pomógł Ci :)

+0

Dziękuję. Rozumiem, jak to działa, ale wow, dość okrężne podejście, wymagające elementów iframe, javascript itp. Do prostego przesyłania formularzy (i mając nadzieję, że przeglądarka nie zanieczyszcza swojej historii z powodu elementu iframe). Nadal mam nadzieję, że ktoś może odnieść się do podstawowej mechaniki zachowania historii przeglądarki podczas standardowego PRG w Webkit i sprawdzić, czy istnieje bardziej bezpośrednia poprawka do rozwiązania problemu. – dlo

+0

Dzięki za miły komentarz. I tak, byłoby miło uzyskać prawdziwe wyjaśnienie, jak działają mechanizmy. –

+0

Tak, raz zepsułem się, gdy zadałem pytanie dotyczące Firefoksa i ktoś, kto rzeczywiście jest w zespole programistów Firefoksa, odpowiedział. :) – dlo

1

Doświadczyliśmy również ten sam problem i nawet po zbadaniu przez kilka dni nie znalazłem „łatwe” rozwiązania. Najbliższą rzeczą, którą znalazłem była ta Webkit Bugzilla ticket, która według jej wyglądu nie wydaje się być bardzo priorytetem. Jak wspomniałeś, IE i Firefox zachowują się dobrze.

Ponieważ mamy własny przycisk Wstecz w aplikacji, udało nam się rozwiązać problem, używając magazynu sesji i sprawdzając go po załadowaniu strony. Kod maszynopis jest następujący:

class DoubleHistoryWorkaround { 

    // key of the attribute we store the URL we where on when clicking on the back button 
    private static comingFromLabel = "comingFromURL"; 
    // key of the attribute of the flag denoting whether we set a valid comingFromURL 
    private static comingFromFlag = "comingFromSet"; 

    constructor() { 
     this.checkLocation(); 
    } 

    /** 
    * Checks the URL we saved in the session and goes a further step back 
    * in the history if the first back button brought us to the same page again. 
    */ 
    private checkLocation() { 
     let doubleEntry : boolean; 
     // have we set a comingFromURL? 
     let comingFromSet = window.sessionStorage.getItem(DoubleHistoryWorkaround.comingFromFlag); 
     if (comingFromSet) { 

      // is the set comingFromURL the same as our current page? 
      let currentURL = window.location.href; 
      let comingFromURL = window.sessionStorage.getItem(DoubleHistoryWorkaround.comingFromLabel); 
      if (currentURL === comingFromURL) { 
       // double history entry detected 
       doubleEntry = true; 

       // before we skip we save our location ourselves, since we might still navigate 
       // to the same page again (in case of triple identical history entries) 
       DoubleHistoryWorkaround.saveLocation(); 

       // skip this page 
       history.back(); 
      } 
     } 

     // reset the location entry unless we just set it ourselves 
     if (!doubleEntry) { 
      this.resetLocation(); 
     } 
    } 

    /** 
    * Saves the current location in the session storage. 
    */ 
    public static saveLocation() { 
     window.sessionStorage.setItem(DoubleHistoryWorkaround.comingFromFlag, "true"); 
     window.sessionStorage.setItem(DoubleHistoryWorkaround.comingFromLabel, window.location.href); 
    } 

    /** 
    * Removes the set location from the session storage. 
    */ 
    private resetLocation() { 
     window.sessionStorage.setItem(DoubleHistoryWorkaround.comingFromFlag, "false"); 
     window.sessionStorage.setItem(DoubleHistoryWorkaround.comingFromLabel, ""); 
    } 
} 

Nazywamy DoubleHistoryWorkaround.saveLocation() kiedy kliknij przycisk Wstecz naszej aplikacji, wyznaczając pozycje sesyjne, które są sprawdzane przez checkLocation().

Powiązane problemy