Angular UI路由器嵌套状态在子状态中解析

时间:2013-12-13 00:38:04

标签: angularjs angular-ui-router

在我正在处理的角度应用程序中,我希望有一个抽象的父状态,它必须解决其所有子状态的某些依赖关系。具体来说,我希望所有州都要求经过身份验证的用户从某个authroot状态继承该依赖关系。

我遇到的问题是父依赖关系并不总是被重新解决。理想情况下,我希望让父状态检查用户是否仍然自动登录任何子状态。在docs中,它说

  

子状态将从父状态继承已解析的依赖关系,它们可以覆盖它们。

我发现如果我从父级之外的状态进入任何子状态,则只重新解析父依赖关系,但如果在兄弟状态之间移动则不会。

在此示例中,如果在状态authroot.testA和authroot.testB之间移动,则只调用一次GetUser方法。当您移至other状态并返回时,它将再次运行。

我能够将User依赖于每个子状态,以确保每次进入任何这些状态时都调用该方法,但这似乎会破坏继承依赖项的目的。

我对文档的理解不正确吗?有没有办法强制父状态重新解析其依赖关系,即使状态在兄弟姐妹之间发生变化?

jsfiddle

<!doctype html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.0/angular-ui-router.min.js"></script>
<script>
(function(ng) {
    var app = ng.module("Test", ["ui.router"]);
    app.config(["$stateProvider", "$urlRouterProvider", function(sp, urp) {
        urp.otherwise("/testA");
        sp.state("authroot", {
            abstract: true, 
            url: "",
            template: "<div ui-view></div>", 
            resolve: {User: ["UserService", function(UserService) {
                        console.log("Resolving dependency...");
                        return UserService.GetUser();
                    }]}
        });
        sp.state("authroot.testA", {
            url: "/testA", 
            template: "<h1>Test A {{User|json}}</h1>", 
            controller: "TestCtrl"
        });
        sp.state("authroot.testB", {
            url: "/testB", 
            template: "<h1>Test B {{User|json}}</h1>", 
            controller: "TestCtrl"
        });
        sp.state("other", {
            url: "/other", 
            template: "<h1>Other</h1>", 
        });
    }]);
    app.controller("TestCtrl", ["$scope", "User", function($scope, User) {$scope.User = User;}]);
    app.factory("UserService", ["$q", "$timeout", function($q, $timeout) {
        function GetUser() {
            console.log("Getting User information from server...");
            var d = $q.defer();
            $timeout(function(){
                console.log("Got User info.");
                d.resolve({UserName:"JohnDoe1", OtherData: "asdf"});
            }, 500);
            return d.promise;
        };
        return {
            GetUser: GetUser
        };
    }]);
})(window.angular);
</script>
</head>
<body ng-app="Test">
    <a ui-sref="authroot.testA">Goto A</a>
    <a ui-sref="authroot.testB">Goto B</a>
    <a ui-sref="other">Goto Other</a>
    <div ui-view>Loading...</div>
</body>
</html>

2 个答案:

答案 0 :(得分:20)

我找到 ui-router 例外的方式就是你刚刚描述过的行为。

让我们考虑一些实体,例如联系。因此,有一个右侧向我们显示联系人列表,左侧部分是详细信息,这将是很好的。请查看The basics of using ui-router with AngularJS以了解有关布局的快速概述。引用:

  ui-router完全包含了路由系统的状态机特性。   它允许您定义状态,并将您的应用程序转换为   那些州。真正的胜利是它允许你解耦嵌套   陈述,并以优雅的方式做一些非常复杂的布局。

     

你需要考虑一下你的路由有点不同,但一旦你   让我们了解一下以州为基础的方法,我想你会喜欢   它

好的,为什么这一切?

因为我们可以有一个表示List的状态Contact。从详细信息的角度说出固定的列表(现在跳过列表分页过滤)我们可以点击列表并移动到状态Contact.Detail(ID),以查看所选项目。然后选择其他联系人/项目。

这里嵌套状态的优点是:

  

列表(状态Contact重新加载。子状态Contact.Detail是。{/ p>

这应该解释为什么应该将“怪异”行为视为正确。

要回答您的问题,如何处理用户状态。我会使用路由状态的一些顶级兄弟,其分离的视图和控制器以及一些生命周期...在某些周期中触发

答案 1 :(得分:8)

真正的简短回答是:

$rootScope.$on("$stateChangeStart")

侦听任何范围更改并执行适当的操作。

更长的答案是,看看小提琴: http://jsfiddle.net/jasallen/SZGjN/1/

请注意,我使用了app.run,这意味着我正在为每个状态更改解析用户。如果要在authRoot位于parentage中时将其限制为状态更改,请在authRoot控制器中检查$stateChangeStart