Примітка
Відповіді, що пропонують використовувати варіанти $window.history.back()
, усі пропустили важливу частину питання: Як відновити стан програми до правильного розташування стану, коли історія переходить (назад / вперед / оновлення). Маючи це на увазі; будь ласка, читайте далі.
Так, можна отримати браузер назад / вперед (історія) та оновити під час запуску чистого ui-router
автомата, але для цього потрібно трохи зробити.
Вам потрібно кілька компонентів:
Унікальні URL-адреси . Браузер дозволяє кнопки перемотування назад / вперед лише при зміні URL-адрес, тому вам потрібно створити унікальну URL-адресу для кожного відвіданого стану. Ці URL-адреси не повинні містити жодної інформації про стан.
Сесійна служба . Кожна згенерована URL-адреса співвідноситься з певним станом, тому вам потрібен спосіб зберігати пари url-state, щоб ви могли отримувати інформацію про стан після перезапуску вашого кутового додатка клацанням назад / вперед або оновлення.
Державна історія . Простий словник станів інтерфейсу маршрутизатора, введений унікальною URL-адресою. Якщо ви можете покластися на HTML5, ви можете використовувати API історії HTML5 , але якщо, як і я, ви не можете, ви можете реалізувати його самостійно в декількох рядках коду (див. Нижче).
Служба локації . Нарешті, вам потрібно вміти керувати як змінами стану користувальницького інтерфейсу, що ініціюються внутрішнім вашим кодом, так і звичайними змінами URL-адрес браузера, як правило, викликаними користувачем, натисканням кнопок браузера або введенням речей на панелі браузера. Це все може стати дещо складним, тому що легко заплутатися у тому, що що спричинило.
Ось моя реалізація кожної з цих вимог. Я об’єднав усе в три служби:
Сесійна служба
class SessionService
setStorage:(key, value) ->
json = if value is undefined then null else JSON.stringify value
sessionStorage.setItem key, json
getStorage:(key)->
JSON.parse sessionStorage.getItem key
clear: ->
@setStorage(key, null) for key of sessionStorage
stateHistory:(value=null) ->
@accessor 'stateHistory', value
accessor:(name, value)->
return @getStorage name unless value?
@setStorage name, value
angular
.module 'app.Services'
.service 'sessionService', SessionService
Це обгортка для sessionStorage
об’єкта javascript . Я тут для чіткості це скоротив. Повне пояснення цього див. У розділі: Як обробити оновлення сторінки за допомогою програми AngularJS Single Page?
Державна служба історії
class StateHistoryService
@$inject:['sessionService']
constructor:(@sessionService) ->
set:(key, state)->
history = @sessionService.stateHistory() ? {}
history[key] = state
@sessionService.stateHistory history
get:(key)->
@sessionService.stateHistory()?[key]
angular
.module 'app.Services'
.service 'stateHistoryService', StateHistoryService
На StateHistoryService
зовнішньому вигляді після зберігання і вилучення історичних станів введених користувача з допомогою згенерованих унікальних адрес. Це справді просто зручна обгортка для об’єкта стилю словника.
Державна служба локації
class StateLocationService
preventCall:[]
@$inject:['$location','$state', 'stateHistoryService']
constructor:(@location, @state, @stateHistoryService) ->
locationChange: ->
return if @preventCall.pop('locationChange')?
entry = @stateHistoryService.get @location.url()
return unless entry?
@preventCall.push 'stateChange'
@state.go entry.name, entry.params, {location:false}
stateChange: ->
return if @preventCall.pop('stateChange')?
entry = {name: @state.current.name, params: @state.params}
url = "/#{@state.params.subscriptionUrl}/#{Math.guid().substr(0,8)}"
@stateHistoryService.set url, entry
@preventCall.push 'locationChange'
@location.url url
angular
.module 'app.Services'
.service 'stateLocationService', StateLocationService
StateLocationService
Обробляє дві події:
locationChange . Це викликається, коли місцезнаходження браузера змінюється, як правило, коли натискається кнопка назад / вперед / оновлення або коли програма запускається вперше або коли користувач вводить URL-адресу. Якщо стан поточного location.url існує, StateHistoryService
тоді він використовується для відновлення стану за допомогою ui-маршрутизатора $state.go
.
stateChange . Це називається при внутрішньому переміщенні стану. Ім'я та параметри поточного стану зберігаються в StateHistoryService
ключі за допомогою згенерованої URL-адреси. Ця згенерована URL-адреса може бути будь-якою, що вам заманеться, вона може або не може ідентифікувати стан зрозумілим для людини способом. У моєму випадку я використовую параметр стану плюс випадково згенеровану послідовність цифр, отриманих з GUID (див. Підставу для фрагмента генератора GUID). Створена URL-адреса відображається на панелі браузера і, що найважливіше, додається до внутрішнього стеку історії браузера за допомогою @location.url url
. Його додавання URL-адреси в стек історії браузера, що дозволяє кнопки вперед / назад.
Велика проблема з цією технікою, що виклик @location.url url
в stateChange
методі викличе $locationChangeSuccess
подія і так викличте locationChange
метод. Рівним чином виклик @state.go
from locationChange
буде ініціювати $stateChangeSuccess
подію і, отже, stateChange
метод. Це стає дуже заплутаним і плутає історію веб-переглядача.
Рішення дуже просте. Ви можете бачити, як preventCall
масив використовується як стек ( pop
і push
). Кожного разу, коли один із методів викликається, це заважає іншому методу називатися одноразовим. Цей прийом не заважає правильному запуску $-подій і тримає все прямо.
Тепер все, що нам потрібно зробити, - це викликати HistoryService
методи у відповідний час життєвого циклу переходу держави. Це робиться за допомогою .run
методу AngularJS Apps , наприклад:
Кутовий додаток.run
angular
.module 'app', ['ui.router']
.run ($rootScope, stateLocationService) ->
$rootScope.$on '$stateChangeSuccess', (event, toState, toParams) ->
stateLocationService.stateChange()
$rootScope.$on '$locationChangeSuccess', ->
stateLocationService.locationChange()
Створіть керівництво
Math.guid = ->
s4 = -> Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1)
"#{s4()}#{s4()}-#{s4()}-#{s4()}-#{s4()}-#{s4()}#{s4()}#{s4()}"
З усім цим на місці кнопки вперед / назад і кнопка оновлення працюють належним чином.