Как реализовать history.back () в angular.js


191

У меня есть директива, которая является заголовком сайта с кнопкой «Назад», и я хочу щелкнуть, чтобы вернуться на предыдущую страницу. Как мне сделать это угловым способом?

Я пытался:

<header class="title">
<a class="back" ng-class="icons"><img src="../media/icons/right_circular.png" ng-click="history.back()" /></a>
<h1>{{title}}</h1>
<a href="/home" class="home" ng-class="icons"><img src="../media/icons/53-house.png" /></a>   
</header>

и это директива JS:

myApp.directive('siteHeader', function () {
    return {
        restrict: 'E',
        templateUrl: 'partials/siteHeader.html',
        scope: {
            title: '@title',
            icons: '@icons'
        }
    };
});

но ничего не происходит Я посмотрел в API angular.js о $ location, но не нашел ничего о кнопке back или history.back().


1
Вы упомянули, что это работает для вас. Это перенесет вас на разные страницы вашего приложения или просто вернет браузер? Похоже, это делает браузер обратно ко мне.
— Chookoos

Если вы установили AngularJS для использования режима HTML5, при переходе на любую страницу, уже имеющуюся в истории браузера, будет использоваться кэшированная версия, а не ее перезагрузка. Проект, над которым я работаю, использует смесь старого и нового кода, и предыдущая страница изменяется после сохранения данных в AngularJS. Невозможно обновить первую страницу для использования AngularJS, поэтому мне пришлось загрузить третью страницу, отличную от AngularJS, чтобы перенаправить обратно на первую страницу. Не очень хорошее решение, но оно работает.
— CJ Деннис

Ответы:


262

Вам нужно использовать функцию ссылки в вашей директиве:

link: function(scope, element, attrs) {
     element.on('click', function() {
         $window.history.back();
     });
 }

Смотрите jsFiddle .


Но у меня есть 2 кнопки в заголовке, одна для дома и одна для спины, если я понимаю ваш код, элемент в функции ссылки - это элемент, по которому щелкнули в этом случае history.back будет применяться также для кнопки домой? (Что не хорошо )
— Baba-Dev

Я немного изменил пример. Теперь есть две кнопки (назад и вперед). Теперь он использует jQuery, а это означает, что нужно нажать. $ Apply () при нажатии.
— asgoth

8
Этот код не тестируется, вы должны действительно использовать объект $ window вместо окна.
— Арбитр

Это работает с IE8? Я не верю, что у него есть история
— Нил

5
@Neil, Angular гордо не поддерживает IE8. Так что нет.
— Рэп

133

Угловые маршруты следят за местоположением браузера, поэтому будет достаточно просто window.history.back()нажать на что-нибудь.

HTML:

<div class="nav-header" ng-click="doTheBack()">Reverse!</div>

JS:

$scope.doTheBack = function() {
  window.history.back();
};

Я обычно создаю глобальную функцию с именем $ back на контроллере приложения, которую я обычно помещаю в тег body.

angular.module('myApp').controller('AppCtrl', ['$scope', function($scope) {
  $scope.$back = function() { 
    window.history.back();
  };
}]);

Тогда в любом месте моего приложения я могу просто сделать <a ng-click="$back()">Back</a>

(Если вы хотите, чтобы он был более тестируемым, вставьте службу $ window в ваш контроллер и используйте $window.history.back()).


9
Я бы рекомендовал не помещать что-либо в «глобальную функцию». Есть очень много вещей, которые могут произойти с глобальным состоянием . В этом случае это в основном изменчивость. Код от третьего лица (или другого разработчика, если вы в большой команде), например, директива или служба, может легко изменить $ scope. $ Back для своих детей. Что может быть трудно отладить. Определенно, лучше внедрять сервис в каждый компонент и раскрывать функциональность там, где это необходимо. Пример только «глобален для приложения», но есть риск
— Бен Леш,

Источник: у меня были вещи, которые я застрял в «глобальном» приложении. Область $ укусила меня слишком много раз, чтобы сосчитать, и я перестал использовать эту технику в пользу сервисов. Который все еще может быть взорван, но это намного легче разузнать.
— Бен Леш

65

В идеале используйте простую директиву, чтобы сохранить контроллеры свободными от избыточного окна $

app.directive('back', ['$window', function($window) {
        return {
            restrict: 'A',
            link: function (scope, elem, attrs) {
                elem.bind('click', function () {
                    $window.history.back();
                });
            }
        };
    }]);

Используйте как это:

<button back>Back</button>

Рад, что вы показали зависимость от $ window - это важно.
— Крис Смит

20

Другое хорошее и многократно используемое решение - создать директиву, подобную этой :

app.directive( 'backButton', function() {
    return {
        restrict: 'A',
        link: function( scope, element, attrs ) {
            element.on( 'click', function () {
                history.back();
                scope.$apply();
            } );
        }
    };
} );

тогда просто используйте это так:

<a href back-button>back</a>

1
Кажется, работает, как только вы переупорядочиваете закрывающие фигурки и переименовываете директиву и элемент attr, чтобы они соответствовали друг другу.
— Restrsh

18

В случае, если это полезно ... Я нажимал "10 $ digest () достигли итераций. Отмена!" ошибка при использовании $ window.history.back (); с IE9 (работает нормально в других браузерах, конечно).

Я получил его на работу с помощью:

setTimeout(function() {
  $window.history.back();
},100);

Другие ответы используют простые window. Вы, кажется, используете $windowсервис Angular. Может быть, это коренная причина?
— Superjos

7
Я получил ту же ошибку под IE9, и это решило проблему. См. Github.com/angular/angular.js/issues/1417 Он прав насчет использования $ window, все остальные ответы «неправильны» в этом вопросе, см. Docs.angularjs.org/api/ng.$window
— tanguy_k

Есть идеи, почему 100 мс? Это довольно задержка, это работает с меньшими затратами?
— Кевин

@Kevin 100 мс были просто продолжительностью, которую я считал разумной, а imo не заметной. Действительно, меньшая задержка может работать.
— Роб Бигрейв

У меня возникают похожие проблемы в последней версии Chrome при использовании в моем приложении угловой навигации по умолчанию, и задержка тоже не поможет. Помогло только отключение управления навигацией Angular .
— Доми


1

Произошла синтаксическая ошибка. Попробуйте это, и это должно работать:

directives.directive('backButton', function(){
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            element.bind('click', function () {
                history.back();
                scope.$apply();
            });
        }
    }
});

1

Угловой 4:

/* typescript */
import { Location } from '@angular/common';
// ...

@Component({
  // ...
})
export class MyComponent {

  constructor(private location: Location) { } 

  goBack() {
    this.location.back(); // go back to previous location
  }
}

0

Для меня моей проблемой было то, что мне нужно было вернуться назад и затем перейти в другое состояние. Поэтому использование $window.history.back()не сработало, потому что по какой-то причине переход произошел до того, как произошло history.back (), поэтому мне пришлось обернуть свой переход в функцию тайм-аута следующим образом.

$window.history.back();
setTimeout(function() {
  $state.transitionTo("tab.jobs"); }, 100);

Это исправило мою проблему.


0

В AngularJS2 я нашел новый способ, может быть, это то же самое, но в этой новой версии:

import {Router, RouteConfig, ROUTER_DIRECTIVES, Location} from 'angular2/router'; 

(...)

constructor(private _router: Router, private _location: Location) {}

onSubmit() {
    (...)
    self._location.back();
}

После выполнения моей функции я вижу, что мое приложение отправляется на предыдущую страницу, используя местоположение angular2 / router.

https://angular.io/docs/ts/latest/api/common/index/Location-class.html


Это работает, вы должны импортировать его из @ angular / common, а не @ angular / router.
— сплетение
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.