Переадресация AngularJS без нажатия состояния истории
Я работаю над приложением AngularJS, у которого есть весь маршрут (например, .when('/:slug', {...)
), который необходим для поддержки устаревших форматов url из предыдущей (не angular) версии приложения. Контроллер, который реагирует на catch, пытается потянуть связанный объект и, если не найден, перенаправляет на страницу 404 с помощью метода $location.path
. Это работает при получении пользователя на странице 404, но когда пользователь возвращается в свой браузер, он возвращает их на страницу, которая вынуждала их на страницу 404 в первую очередь, и они в конечном итоге не могут выйти из цикла.
Мой вопрос в том, есть ли 1) лучший шаблон для обработки этой ситуации или 2) если есть способ перенаправить пользователя, который не заставляет состояние истории в браузере?
Ответы
Ответ 1
Вы можете изменить URL-адрес без добавления в состояние истории, найти здесь в разделе "Метод замены". Это фактически то же самое, что вызывать HTML5 history.replaceState().
$location.path('/someNewPath').replace();
Я не нашел, что можно изменить представление без изменения URL-адреса. Единственный способ изменить вид, который я нашел, - это изменить путь к местоположению.
Ответ 2
Нормальная работа системы маршрутов предназначена для службы $route
наблюдать за событием $locationChangeSuccess
, а затем начать загрузку маршрута. После загрузки шаблона, выполнения шагов решения и создания экземпляра контроллера он, в свою очередь, транслирует событие $routeChangeSuccess
. Этот $routeChangeSuccess
контролируется директивой ng-view
и как он знает, чтобы менять шаблоны и области действия после того, как новый маршрут готов.
При всем сказанном выше может работать код приложения, который эмулирует поведение службы $route
, обновляя текущий маршрут и выдавая событие изменения маршрута, чтобы обновить представление:
var errorRoute = $route.routes[null]; // assuming the "otherwise" route is the 404
// a route instance is an object that inherits from the route and adds
// new properties representing the routeParams and locals.
var errorRouteInstance = angular.inherit(
errorRoute,
{
params: {},
pathParams: {},
}
);
// The $route service depends on this being set so it can recover the route
// for a given route instance.
errorRouteInstance.$$route = errorRoute;
var last = $route.current;
$route.current = errorRouteInstance;
// the ng-view code doesn't actually care about the parameters here,
// since it goes straight to $route.current, but we should include
// them anyway since other code might be listening for this event
// and depending on these params to behave as documented.
$rootScope.broadcast('$routeChangeSuccess', errorRoute, last);
Вышеизложенное предполагает, что ваш маршрут "по-другому" не имеет шагов "разрешения". Он также предполагает, что он не ожидает никаких $routeParams
, что, конечно, верно для маршрута "иначе", но может быть неверным, если вы используете другой маршрут.
Непонятно, что из вышеперечисленного зависит от деталей реализации и интерфейса. Событие $routeChangeSuccess
, безусловно, задокументировано, но свойство $$route
экземпляра маршрута, по-видимому, представляет собой деталь реализации системы маршрута, учитывая его двузначный знак. Деталь, что маршрут "в противном случае" хранится в таблице маршрутов с ключом null
, возможно, также является деталью реализации. Таким образом, при всем этом сказано, что это поведение не может оставаться функциональным в будущих версиях AngularJS.
Для получения дополнительной информации вы можете обратиться к коду ng-view
, который обрабатывает это событие, что в конечном итоге означает, что приведенный выше код пытается удовлетворить, а также код, испускающий события, который я использовал в качестве основы для приведенного выше примера. Как вы могли бы сделать вывод из этих ссылок, информация в этом сообщении получена из последней ведущей ветки AngularJS, которая на момент написания помечена как 1.2.0-моментальный снимок.