Решить проблему, что браузер не обновляется при возврате на страницу

внешний интерфейс

Феномен

Из-за механизма кэширования страниц системы IOS часто встречается, что предыдущая страница не обновляется при возврате на мобильный терминал.

Например, при разработке страниц WeChat H5 сегодня при возврате на предыдущую страницу во встроенном браузере IOS WeChat предыдущая страница не обновится. Обычно в механизме кеширования браузера, при операции возврата на предыдущую страницу динамические и статические ресурсы типа html/css/js/interface не будут повторно запрашиваться, а будет повторно загружаться js. Однако на странице IOS WeChat js также сохранит последнее выполненное состояние предыдущей страницы и не будет повторно выполнять js. Использование этого режима кэширования может ускорить рендеринг, но некоторые данные необходимо часто отображать и редактировать, что приводит к рассинхронизации. Например, «страница сведений» переходит на «страницу редактирования», а затем после редактирования возвращается на «страницу сведений». Если отображение данных «страницы сведений» не изменяется синхронно, это определенно неприемлемо. В режиме смешанного приложения веб-просмотра и 5+ также будет возникать эта проблема возврата на предыдущую страницу без обновления.

причина

Кэш браузера вперед/назад

Здесь упоминается понятие, браузерный прямой/обратный кеш (Backward/Forward Cache, BF Cache), конечно, некоторые называют его дисковым кешем. BF Cache — это оптимизация браузера.Стандарт HTML не указывает, как кэшировать, поэтому поведение кэша реализуется каждым браузером, поэтому оно отличается. Поскольку это не HTTP-кэш, настройка no-cache через кеш заголовков не имеет никакого эффекта. Конечно, BF Cache нельзя понимать с точки зрения механизма кэширования HTTP.

Решения

Установить текущую историю просмотров

//监听后退返回事件 --解决微信返回不刷新问题
pushHistory: function(){
    window.addEventListener("popstate", function(e) {
        self.location.reload();
    }, false);
    var state = {
        title : "",
        url : "#"
    };
    window.history.replaceState(state, "", "#");
},

/**
* 页面初始化调用pushHistory,监听popstate事件和执行replaceState()
* 当执行replaceState()时,不会触发popstate事件,所以不会重复刷新
* 当在ios微信内置浏览器中执行浏览器前进后退操作时,触发popstate事件,执行location.reload()
* 但是在谷歌浏览器中执行浏览器前进后退操作时,不会触发popstate事件!因为不在一个document中了
* 但是如果手动改变URL的哈希值,比如www.baidu.com# 改成 www.baidu.com#1 会触发popstate事件,执行location.reload()
* 以上如果有一项不理解或不清晰,请往下看原理深究,你会找到答案
**/

Углубленное изучение принципа

Принцип реализации внешней маршрутизации (история)

В прошлом браузер управлял историей браузера в основном на основе объекта истории. В его протонаследовании есть функции назад, вперед, вперед и другие. После HTML5 был добавлен popState для управления API истории посещенных страниц. Есть pushState, который может хранить текущую точку истории, replaceState, который заменяет текущую точку истории, и onPopState, который прослушивает точку истории.

window.history.pushState(state, title, url)

  • состояние (объект состояния): объект js, который можно использовать для хранения некоторых простых данных. Стоит отметить, что если активированная запись истории была сгенерирована с помощью вызова pushState или replaceState, свойство состояния события popState содержит копию объекта состояния записи истории. Сохраненное состояние можно прочитать из history.state.
  • title (название): в настоящее время игнорируется браузерами, поэтому обычно передается пустая строка
  • URL (адрес): адрес новой записи истории. Стоит отметить, что браузер не загружает этот URL-адрес сразу после вызова pushState(), но может загружать URL-адрес в некоторых случаях, когда пользователь повторно открывает браузер и так далее. И новый URL-адрес должен иметь то же происхождение, что и текущий URL-адрес, иначе будет выдано исключение. новый URL-адреса могут быть абсолютными или относительными.

window.history.replaceState(state, title, url)

  • Разница в том, что оба API работают с историей браузера, не вызывая обновления страницы и не проверяя существование веб-страницы, соответствующей новой записи.
  • Разница в том, что pushState добавляет новую историю, а replaceState заменяет текущую историю.
  • Ни один из API никогда не запустит событие hashchange, даже если новый URL-адрес отличается от старого URL-адреса только хешем.
  • Если передается stateObj, объект состояния, связанный с текущей записью, будет обновлен; если передан url, адрес страницы текущей записи будет заменен и адрес адресной строки браузера будет изменен.

событие window.onpopstate

  • Запускается только при переходе браузера вперед и назад, вызове history.go/back/forward, hashChange
  • Ни history.pushState, ни history.replaceState не вызовут это событие.
  • firefox, chrome не будет запускать событие popstate при первом открытии страницы, но сафари будет
  • Область действия события popstate находится только в документе, так как ни pushState, ни hashchange не изменят содержимое веб-страницы, то есть документа, popstate можно эффективно использовать в такой веб-странице. Предположим, мы заходим на веб-страницу и добавляем к ней обратный вызов popstate, затем переходим на другую веб-страницу через переход по ссылке, затем нажимаем кнопку «Назад», чтобы вернуться на первую веб-страницу. В этом случае обратный вызов popstate на первой веб-странице, за исключением того, что он может быть запущен из-за инициализации страницы, браузера назад и впередне сработаетЭто так, потому что таким образом изменяется документ окна.но! ! ! Во встроенном браузере iOS WeChat повторение вышеуказанной операции вызовет событие onpopstate! , так что мы можем решить проблему, что страница не обновляется в браузере WeChat

Первый параметр stateObj для pushState и replaceState будет привязан к записи истории, соответствующей третьему параметру. Когда событие popstate запускается, это означает, что активируется новая запись истории. В объекте события popstate есть свойство состояния, которое возвращает копию объекта stateObj, связанного с этой активной записью. Запись истории может иметь связанный объект stateObj только в том случае, если она была создана с помощью pushState или изменена с помощью replaceState, поэтому при активации некоторых записей истории, отличных от этих двух условий, stateObj может быть получен.

Схема предотвращения возврата на предыдущую страницу

/**
* 向历史记录中手动添加一条记录
* 用户选择返回的时候,每次都会消耗一个 history 实体,此时触发 popstate 监听事件,再手动添加一条history实体记录
* 所以用户无论点击多少次都会永远留在这个页面了,当然页面也不会刷新
**/
function pushHistory() {
    window.history.pushState(null, null, "#");
    window.addEventListener("popstate", function (e) {
        console.log(e);
        window.history.pushState(null, null, "#");
    }, false);
}

# в URL

# в URL-адресе представляет собой хэш-значение URL-адреса.

  • # представляет позицию на веб-странице, а символ справа — идентификатор позиции.
设置方法:
step1:设置一个锚点<a href="#print">定位到print位置</a>
step2:在页面需要定位的内容加上id="print"。例如:<div id="print"></div> 或者 <a name="print"></a>
测试:step1设置的锚点,step2中id为print的内容会滚动到页面顶端(可观察滚动条的距离)。同时,页面的url末端中会出现 # print的哈希值。
  • HTTP-запрос не содержит #
    Знак # используется для управления действиями браузера и совершенно бесполезен на стороне сервера.
    Любой символ, который появляется после первого #, будет интерпретирован браузером как идентификатор местоположения. Это означает, что ни один из этих символов не отправляется на сервер.
    Посетите следующий URL-адрес:www.w3cschool.cn/#helloФактический запрос, сделанный браузером, выглядит следующим образом:

  • Изменение # не вызывает перезагрузку страницы
    Если вы просто измените содержимое после #, браузер прокрутит только до соответствующей позиции и не перезагрузит веб-страницу.
    Браузер также не будет повторно запрашивать страницу с сервера

  • Изменение # изменит историю доступа браузера
    Каждый раз, когда вы меняете часть после #, в историю доступа браузера будет добавляться запись, и вы сможете вернуться на предыдущую позицию с помощью кнопки «назад».

  • window.location.hash чтение #значение
    Свойство window.location.hash доступно для чтения и записи. При чтении с его помощью можно определить, изменился ли статус веб-страницы, при записи создаст запись истории доступа без перезагрузки веб-страницы.

  • событие onhashchange
    Это новое событие HTML 5, которое запускается при изменении значения #. IE8+, Firefox 3.6+, Chrome 5+, Safari 4.0+ поддерживают это событие.

    // 它的使用方法有三种:
    window.onhashchange = func;
    <body onhashchange="func();">
    window.addEventListener("hashchange", func, false);
    
  • Как Google сканирует #
    По умолчанию поисковые роботы Google игнорируют # часть URL-адресов.
    Однако Google также оговаривает, что если вы хотите, чтобы контент, сгенерированный Ajax, читался браузерным движком, вы можете использовать «#!» в URL-адресе, и Google автоматически преобразует контент, стоящий за ним, в значение строки запроса _escaped_fragment_. .
    Например, Google нашел новую версию URL-адреса Twitter:twitter.com/#!/username
    автоматически захватит другой URL:twitter.com/?escaped_fragment=/username
    Благодаря этому механизму Google может индексировать динамический контент Ajax.

Другое решение: событие pageShow

window.addEventListener('pageshow', () => {
  if (e.persisted || (window.performance && 
    window.performance.navigation.type == 2)) {
    location.reload()
  }
}, false)
  • Чтобы узнать, была ли страница загружена непосредственно с сервера или прочитана из кэша, используйте свойство persisted объекта PageTransitionEvent. Возвращает значение true, если страница считывает это свойство из кэша браузера, в противном случае — значение false.
  • объект window.performance, performance.navigation.type — короткое целое число без знака.

TYPE_NAVIGATE (0):

Текущая страница представлена ​​нажатием ссылок, закладок и форм или сценарий, или непосредственно ввод в адрес в URL, а значение типа 0

TYPE_RELOAD (1)

Нажмите кнопку обновления страницы или страницу, отображаемую методом Location.reload(), значение типа равно 1.

TYPE_BACK_FORWARD (2)

Доступ к страницам осуществляется через историю и вперед и назад. значение типа 2

TYPE_RESERVED (255)

В любом другом случае значение типа равно 255. Это действительно та часть, которая нам нужна