Turbolinks 5 и историческое событие popstate - PullRequest
0 голосов
/ 26 мая 2020

Я использую Turbolinks в веб-приложении Rails 6.1.

Я понимаю, что Turbolinks использует AJAX для замены body и history.pushState() для обновления URL-адреса, чтобы он соответствовал.

Я реализовал диалоговую / модальную систему, которая добавляет элемент к body, а затем показывает этот элемент, используя CSS с некоторыми обработчиками событий, чтобы закрыть диалоговое окно и удалить его, когда пользователь нажимает кнопку закрытия на диалоговое окно.

Проблема заключается в браузерах мобильных устройств, пользователи предпочитают использовать кнопку «Назад» (стрелка в левом нижнем углу Android) вместо того, чтобы дотягиваться до верхней части диалогового окна и нажимать кнопку закрытия.

Итак, мне нужен способ перехватить обычное событие Turbolinks restoration и выполнить некоторые из моих собственных Javascript в событии popstate вместо того, чтобы Turbolinks взял верх.

Я Знаю, что в документах Turbolinks указано, что события restoration нельзя отменить, но я искал способ использовать собственный JS, чтобы перехватить popstate, прежде чем Turbolinks когда-либо его получит.

Я подумал его Это может быть довольно просто: когда я показываю диалог в моем Javascript, я выполняю

window
      .history
      .pushState({ dialog: { id: "id-of-dialog" } }, null, window.location)

, а затем имею обработчик событий для popstate, который закрывает диалог.

document.addEventListener("popstate", (event) => {
  console.log(event.state)
  if (event.state.dialog) {
    const dialogId = event.state.dialog.id
    const dialogElement = document.getElementyById(dialogId)

    // Note: I do have some animations for closing, so the closing logic is slightly more
    // complex than this, but this shows the gist of what's going on.
    dialogElement.classList.remove("dialog-container-open")
    dialogElement.remove()

    // Does this stop Turbolinks from taking over?
    event.preventDefault()
    event.stopPropagation()
  } else {
    // Do nothing, let Turbolinks handle it
  }
})

Однако в событии popstate Turbolinks всегда имеет состояние на вершине стека истории, и я не могу понять, как и где это происходит, поэтому я не могу его остановить.

По существу , Я просто хочу вручную управлять историей popstate logi c, когда нажимается кнопка «Назад» для обработки моих диалогов. Но несмотря ни на что, Turbolinks всегда, кажется, запускает и обновляет sh страницу, когда я просто хочу закрыть диалоговое окно.

Есть ли способ реализовать это? Я тоже пробовал hashchange, но history API казался намного более перспективным, поскольку Turbolinks построен на его основе.

1 Ответ

0 голосов
/ 02 июня 2020

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

Turbolinks обрабатывает все события popstate и имеет свои собственные механизмы для этого. Вы можете отправить sh в стек истории способом, понятным Turbolinks, позвонив:

Turbolinks
  .controller
  .pushHistoryWithLocationAndRestorationIdentifier(<YOUR_LOCATION>, Turbolinks.uuid())

Таким образом, вместо того, чтобы думать, что вы хотите обработать событие popstate, Turbolinks теперь должен обработать это за вас. , восстанавливая страницу в том виде, в котором она была до инициализации диалогового окна. Стоит отметить, что хотя это метод publi c, он не задокументирован и поэтому может быть удален в будущих версиях.

...