Событие Popstate не запускается после двойного нажатия на историю с помощью history.pushState()

Я работаю над интернет-магазином, в котором элементы открываются поверх страницы в фреймах. Я использую

history.pushState(stateObj, "page 2", http://localhost:8888/product-category/tyger/vara-tyger/?view=product&item=test-4);

чтобы позволить клиентам скопировать текущий URL-адрес и использовать его для перехода на текущую страницу с элементом, открытым в iframe. Кроме того, я использую

window.addEventListener('popstate', manageHistory);

function manageHistory(event) {
    if (!has_gone_back) {
        var iframeOpen = false;
        has_gone_back = true;
    }
    else {
        var iframeOpen = true;
        has_gone_back = false;
    }
}

чтобы клиенты могли использовать кнопки «назад» и «вперед» своего браузера для навигации (закрытие и открытие iframe).

Однако при открытии одного продукта (вызов history.pushState один раз), использовании кнопки «Назад» в браузере и открытии другого продукта (вызов history.pushState снова) и повторном возврате manageHistory() не вызывается. Покупатель переходит к первому открытому продукту, но при повторном нажатии вызывается manageHistory().

Я хочу, чтобы manageHistory() вызывался при нажатии назад на странице продукта, открытой второй, чтобы добавить код для перенаправления клиентов на стартовую страницу категории при нажатии назад.

Я пробовал добавлять прослушиватели событий как для обоих открытых продуктов, так и только для первого. Есть идеи, в чем может быть проблема?


person Alexander Lind    schedule 05.08.2016    source источник


Ответы (1)


Из https://developer.mozilla.org/en-US/docs/Web/Events/popstate

Обратите внимание, что простой вызов history.pushState() или history.replaceState() не вызовет событие popstate. Событие popstate запускается только при выполнении действия браузера, такого как нажатие кнопки «Назад» (или вызов history.back() в JavaScript).

Вы можете перезаписать popState и replaceState, но, как правило, лучше создать оболочку, которая устанавливает URL-адрес, а затем запускает функцию обработчика.

Что-то вроде этого...

function urlChangeHandler() {
  var url = window.location.href;

  // Whatever you want to do...
}

// Handle initial url:
urlChangeHandler();

window.addEventListener('popstate', urlChangeHandler);

var urlState = {
  push: function(url) {
    window.history.pushState(null, null, url);
    urlChangeHandler();
  },
  replace: function(url) {
    window.history.replaceState(null, null, url);
    urlChangeHandler();
  }
}

У меня есть аналогичный файл в одном из моих проектов, который обновляет хранилище данных на основе #hash...

import tree from './state'


// No need for react-router for such a simple application.

function hashChangeHandler(commit) {
  return () => {
    const hash = window.location.hash.substr(1);

    const cursor = tree.select('activeContactIndex');
    const createCursor = tree.select('createNewContact');

    cursor.set(null);
    createCursor.set(false);

    (() => {
      if(!hash.length) {
        // Clean up the url (remove the hash if there is nothing after it):
        window.history.replaceState(null, null, window.location.pathname);
        return;
      }

      if(hash === 'new') {
        createCursor.set(true);
        return;
      }

      const index = parseInt(hash, 10);
      if(!isNaN(index)) {
        cursor.set(index);
      }
    })();
    commit && tree.commit();
  }
}

// Handle initial url:
hashChangeHandler(true)();

// Handle manual changes of the hash in the url:
window.addEventListener('hashchange', hashChangeHandler(true));

function createHash(location) {
  return (location !== null) ? `#${location}` : window.location.pathname;
}

module.exports = {
  push: (location, commit=true) => {
    window.history.pushState(null, null, createHash(location));
    hashChangeHandler(commit)();
  },
  replace: (location, commit=true) => {
    window.history.replaceState(null, null, createHash(location));
    hashChangeHandler(commit)();
  }
}
person demux    schedule 05.08.2016
comment
Когда я пытаюсь использовать ваш код, я получаю Unexpected token '>'. Я использую Wordpress, мне нужно добавить библиотеку или что-то в этом роде? - person Alexander Lind; 05.08.2016
comment
Это просто пример кода, который я сделал на скорую руку. Это отредактированная версия второго фрагмента кода, который я скопировал из одного из своих проектов. На самом деле это модуль, и предполагается, что вы будете использовать что-то вроде webpack или browserify. Кроме того, есть синтаксис ES2015, поэтому вам понадобится транспилятор, такой как babel. Прочтите его, поймите, что он делает, и повторно реализуйте его в своем приложении. Я перепишу его на ванильный javascript. - person demux; 05.08.2016