Answers:
ui-router转换后不会跟踪以前的状态,但是会在状态更改时$stateChangeSuccess
广播该事件$rootScope
。
您应该能够从该事件中捕获先前状态(from
即将离开的状态):
$rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from, fromParams) {
//assign the "from" parameter to something
});
我使用resolve在移动到新状态之前保存当前状态数据:
angular.module('MyModule')
.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('mystate', {
templateUrl: 'mytemplate.html',
controller: ["PreviousState", function (PreviousState) {
if (PreviousState.Name == "mystate") {
// ...
}
}],
resolve: {
PreviousState: ["$state", function ($state) {
var currentStateData = {
Name: $state.current.name,
Params: $state.params,
URL: $state.href($state.current.name, $state.params)
};
return currentStateData;
}]
}
});
}]);
$stateChangeSuccess
$stateChangeSuccess
奏效,但它是在全球范围内进行的,大多数时候并不需要。
$state.current
is对象:{name: "", url: "^", views: null, abstract: true}
。
为了便于阅读,我将在这里放置我的解决方案(基于stu.salsbury的anwser)。
将此代码添加到应用程序的抽象模板中,以便在每个页面上运行。
$rootScope.previousState;
$rootScope.currentState;
$rootScope.$on('$stateChangeSuccess', function(ev, to, toParams, from, fromParams) {
$rootScope.previousState = from.name;
$rootScope.currentState = to.name;
console.log('Previous state:'+$rootScope.previousState)
console.log('Current state:'+$rootScope.currentState)
});
跟踪rootScope的更改。它非常方便。
在下面的示例中,我创建了一个decorator
(在配置阶段每个应用仅运行一次),并向$state
服务添加了一个额外的属性,因此该方法不会向,而不向其他服务添加全局变量,$rootscope
也不需要向其添加任何额外的依赖项$state
。
在我的示例中,我需要在用户已经登录时以及在登录后不将其重定向到先前的“受保护”页面时将用户重定向到索引页面。
我使用的唯一未知服务(为您服务)是authenticationFactory
和appSettings
:
authenticationFactory
只需管理用户登录。在这种情况下,我仅使用一种方法来识别用户是否已登录。appSettings
是常量,只是为了不在任何地方使用字符串。appSettings.states.login
并appSettings.states.register
包含登录和注册网址的状态名称。然后,在任何controller
/ service
etc中,您需要注入$state
服务,并且可以像这样访问当前和以前的URL:
$state.current.name
$state.previous.route.name
在Chrome控制台中:
var injector = angular.element(document.body).injector();
var $state = injector.get("$state");
$state.current.name;
$state.previous.route.name;
实现方式:
(我正在使用angular-ui-router v0.2.17
和angularjs v1.4.9
)
(function(angular) {
"use strict";
function $stateDecorator($delegate, $injector, $rootScope, appSettings) {
function decorated$State() {
var $state = $delegate;
$state.previous = undefined;
$rootScope.$on("$stateChangeSuccess", function (ev, to, toParams, from, fromParams) {
$state.previous = { route: from, routeParams: fromParams }
});
$rootScope.$on("$stateChangeStart", function (event, toState/*, toParams, fromState, fromParams*/) {
var authenticationFactory = $injector.get("authenticationFactory");
if ((toState.name === appSettings.states.login || toState.name === appSettings.states.register) && authenticationFactory.isUserLoggedIn()) {
event.preventDefault();
$state.go(appSettings.states.index);
}
});
return $state;
}
return decorated$State();
}
$stateDecorator.$inject = ["$delegate", "$injector", "$rootScope", "appSettings"];
angular
.module("app.core")
.decorator("$state", $stateDecorator);
})(angular);
在$ stateChangeStart的$ state中添加一个名为{previous}的新属性
$rootScope.$on( '$stateChangeStart', ( event, to, toParams, from, fromParams ) => {
// Add {fromParams} to {from}
from.params = fromParams;
// Assign {from} to {previous} in $state
$state.previous = from;
...
}
现在您需要的任何地方都可以使用$ state,您将可以使用之前的状态
previous:Object
name:"route name"
params:Object
someParam:"someValue"
resolve:Object
template:"route template"
url:"/route path/:someParam"
并像这样使用它:
$state.go( $state.previous.name, $state.previous.params );
我陷入同样的问题,并找到最简单的方法来做...
//Html
<button type="button" onclick="history.back()">Back</button>
要么
//Html
<button type="button" ng-click="goBack()">Back</button>
//JS
$scope.goBack = function() {
window.history.back();
};
(如果您希望它具有更高的可测试性,请将$ window服务注入您的控制器并使用$ window.history.back())。
对于Endy Tjahjono,我使用类似的方法。
我要做的是在进行转换之前保存当前状态的值。让我们看一个例子;想象一下,在攀登到任何触发转换的函数中执行以下操作:
$state.go( 'state-whatever', { previousState : { name : $state.current.name } }, {} );
这里的关键是params对象(将发送到状态的参数的映射)-> { previousState : { name : $state.current.name } }
注意:请注意,我只“保存” $ state对象的name属性,因为这是我唯一需要保存的状态。但是我们可以拥有整个状态对象。
然后,状态“无论如何”的定义如下:
.state( 'user-edit', {
url : 'whatever'
templateUrl : 'whatever',
controller: 'whateverController as whateverController',
params : {
previousState: null,
}
});
在这里,关键点是params对象。
params : {
previousState: null,
}
然后,在该状态内,我们可以像这样获得先前的状态:
$state.params.previousState.name
这是来自Chris Thielen ui-router-extras的一个非常优雅的解决方案:$ previousState
var previous = $previousState.get(); //Gets a reference to the previous state.
previous
是一个看起来像这样的对象:{ state: fromState, params: fromParams }
其中fromState是先前的状态,fromParams是先前的状态参数。
好的,我知道我在这里参加聚会迟到了,但是我是新手。我正在尝试使其适合John Papa风格指南。我想使它可重用,所以我在一个代码块中创建了它。这是我想出的:
previousStateProvider
(function () {
'use strict';
angular.module('blocks.previousState')
.provider('previousState', previousStateProvider);
previousStateProvider.$inject = ['$rootScopeProvider'];
function previousStateProvider($rootScopeProvider) {
this.$get = PreviousState;
PreviousState.$inject = ['$rootScope'];
/* @ngInject */
function PreviousState($rootScope) {
$rootScope.previousParms;
$rootScope.previousState;
$rootScope.currentState;
$rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from, fromParams) {
$rootScope.previousParms = fromParams;
$rootScope.previousState = from.name;
$rootScope.currentState = to.name;
});
}
}
})();
核心模块
(function () {
'use strict';
angular.module('myApp.Core', [
// Angular modules
'ngMessages',
'ngResource',
// Custom modules
'blocks.previousState',
'blocks.router'
// 3rd Party Modules
]);
})();
core.config
(function () {
'use strict';
var core = angular.module('myApp.Core');
core.run(appRun);
function appRun(previousState) {
// do nothing. just instantiating the state handler
}
})();
对此代码的任何批评只会对我有所帮助,所以请让我知道我可以在哪里改进此代码。
如果您只需要此功能,并想在多个控制器中使用它,这是跟踪路线历史记录的一项简单服务:
(function () {
'use strict';
angular
.module('core')
.factory('RouterTracker', RouterTracker);
function RouterTracker($rootScope) {
var routeHistory = [];
var service = {
getRouteHistory: getRouteHistory
};
$rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from, fromParams) {
routeHistory.push({route: from, routeParams: fromParams});
});
function getRouteHistory() {
return routeHistory;
}
return service;
}
})();
.module('core')中的'core'将是您的应用程序/模块的名称。将服务作为对控制器的依赖项,然后可以在控制器中执行以下操作:$scope.routeHistory = RouterTracker.getRouteHistory()
我在$ rootScope中跟踪以前的状态,因此只要有需要,我都将调用下面的代码行。
$state.go($rootScope.previousState);
在App.js中:
$rootScope.$on('$stateChangeSuccess', function(event, to, toParams, from, fromParams) {
$rootScope.previousState = from.name;
});
对于UI-Router(> = 1.0),不建议使用StateChange事件。有关完整的迁移指南,请单击此处
要在UI-Router 1.0+中获取当前状态的先前状态:
app.run(function ($transitions) {
$transitions.onSuccess({}, function (trans) {
// previous state and paramaters
var previousState = trans.from().name;
var previousStateParameters = trans.params('from');
});
});
您可以通过以下方式返回状态:
$state.go($state.$current.parent.self.name, $state.params);
一个例子:
(function() {
'use strict'
angular.module('app')
.run(Run);
/* @ngInject */
function Run($rootScope, $state) {
$rootScope.back = function() {
$state.go($state.$current.parent.self.name, $state.params);
};
};
})();