7

Допустим, я нахожусь на/странице? ID = 1после редиректа-получить (PRG) вновь вставляет одну страницу в историю в Webkit браузеров

Затем я перейти к/странице? ID = 2

И я вношу изменения на эту страницу, которая реализует сообщение, а затем перенаправляет обратно на/page? Id = 2

В Firefox я могу нажать кнопку «назад» один раз и вернуться к/page? Id = 1, но в Chrome и Safari на iPhone мне нужно дважды нажать кнопку «Назад», потому что/page? id = 2 в истории браузера дважды. (И если я сделал несколько сообщений с id = 2, мне пришлось бы нажимать кнопку «Назад», чтобы многократно вернуться к id = 1.)

В некотором роде это похоже на обычное поведение браузера, так как каждый GET просто вставляется в историю, но поскольку URL-адрес идентичен предыдущей записи, это приводит к плохому пользовательскому опыту, чего обычно избегают другие веб-приложения ... и, естественно, его можно избежать в Firefox. Является ли это неизбежной ошибкой в ​​браузерах Webkit, или я могу реализовать PRG по-другому, чтобы этого избежать?

btw- поведение по-видимому, тот же перенаправление с 302 или 303.

UPDATE: Я издевался некоторый пример кода ... не знает, если есть платформа, как jsfiddle где Я мог бы загрузить это для вас, чтобы увидеть в действии:

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']); 
?> 

Если я начинаю с form.php? Id = 4 (просто чтобы поместить его в историю браузера), а затем перейдите к form.php? Id = 5, а затем нажмите submit (как будто для выполнения изменения базы данных) в Firefox я получаю одну запись в истории для каждого; в Chrome я получаю одну запись для id = 4, а затем две записи для id = 5. Почему разница в поведении? Я думаю, что поведение Firefox лучше, так как двойное нажатие, чтобы уйти от id = 5, является интуитивно понятным для пользователя.

ответ

1

Хотя это не объяснение того, что происходит, у меня есть путь вокруг него, который я использую во всех своих приложениях. Первый некоторый код:

form.php будет выглядеть следующим образом:

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 так:

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

Это ваши документы с некоторыми дополнительными вещами в <form> тегах и новенькие <script> тегов.

Я хотел бы также иметь iframe где-то в документе, как это:

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

Так, чтобы объяснить. Вместо перехода на новый сайт и обратно каждый раз, когда вам нужно внести изменения, вы просто загружаете submit.php в iframe в существующий документ. Следовательно, часть target="iframe".

Затем, когда загрузился iframe, что означает, что изменения были сделаны, вы перезагрузите исходную страницу, чтобы отразить эти изменения, отсюда часть window.parent.location.reload();. Поскольку страница просто перезагружается, она не добавит второй записи в вашу историю.

Я надеюсь, что это помогло вам :)

+0

спасибо. Я вижу, как это работает, но ничего себе, довольно окольный подход, требующий iframes, javascript и т. Д. Для простой подачи формы (и надеясь, что браузер не загрязнит ее историю из-за iframe). Я все еще надеюсь, что кто-то может обратиться к основной механике поведения истории браузера во время стандартного PRG в Webkit и посмотреть, есть ли более прямое исправление для его решения. – dlo

+0

Спасибо за хороший комментарий. И да, было бы неплохо получить реальное объяснение того, как работает механика. –

+0

Да, я однажды испорчен, когда задал вопрос об Firefox, и кто-то, кто на самом деле находится в команде разработчиков Firefox, ответил. :) – dlo

1

Мы также испытали те же проблемы, и даже после того, как исследования в течение нескольких дней я не нашел «легкое» решение. Самое близкое, что я нашел, это Webkit Bugzilla ticket, который по внешнему виду кажется не очень высоким. Как вы уже упоминали, IE и Firefox ведут себя отлично.

Поскольку у нас есть собственная кнопка возврата в приложении, мы смогли решить проблему, используя хранилище сеансов и проверив ее при загрузке страницы. Код Машинопись является следующее:

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

Мы называем DoubleHistoryWorkaround.saveLocation(), когда мы нажимаем кнопку назад нашего приложения, настройки записи сеансов, которые проверяются checkLocation().