【问题标题】:Verifying route preconditions prior to loading controller在加载控制器之前验证路由前提条件
【发布时间】:2013-12-24 03:56:33
【问题描述】:

我正在用 Angular 编写一个单页应用程序,特别是 angular.dart,但我假设这个问题仍然适用于 AngularJS。

以以下路线为例:

/登录 - 预计没有人登录。如果有人通过身份验证但未注册,则重定向到“注册”路由,如果他们已注册,则重定向到“家”路由。

/注册 - 需要一个尚未完成注册过程的经过身份验证的用户。如果未通过身份验证,则重定向到登录。如果通过了身份验证,则重定向到主页。

/home - 需要经过身份验证和注册的用户。如果没有认证,重定向到“login”路由,如果没有注册,重定向到“register”路由。

我已经进行了大量搜索,但找不到内置或惯用的方法来检查以确保在加载与特定路由关联的控制器之前满足某些先决条件,并在这些先决条件满足时进行适当的重定向没有遇到。

任何帮助将不胜感激!

【问题讨论】:

    标签: dart angular-dart


    【解决方案1】:

    Angular.Dart 和 Angular.JS 路由框架非常/根本不同。 Angular.Dart 使用第三方路由框架 (https://github.com/dart-lang/route/tree/experimental_hierarchical),仅实现了 Angular 特定功能,例如 ng-view 以及通过 ViewFactory 将路由绑定到模板的方法。

    所以您的问题确实属于route_hierarchical 包域。目前,您可以否决用户尝试离开路线,但我猜您希望根据用户是否登录来否决用户输入路线的能力。不幸的是,这尚不支持,但已在计划中。

    与此同时,您可以尝试创建自定义 viewFactory 包装器。

    class RecipesRouteInitializer implements RouteInitializer {
       void init(Router router, ViewFactory view) {
         router
           ..addRoute(
              name: 'login',
              path: '/login',
              enter: authView(router, view('login.html'), NOT_AUTH))
           ..addRoute(
              name: 'register',
              path: '/register',
              enter: authView(router, view('register.html'), AUTH_NO_REG))
           ..addRoute(
              name: 'home',
              path: '/home',
              enter: authView(router, view('home.html'), AUTH_AND_REG));
       }
    
       authView(Router router, ngView, mode) {
         return (RouteEvent e) {
           if (mode == AUTH_AND_REG) {
             if (!authService.isAuth) {
               router.go('login', {});
               return;
             }
             if (!authService.isReg) {
               router.go('register', {});
               return;
             }
           } else if (mode == AUTH_NO_REG) {
             if (!authService.isAuth) {
               router.go('login', {});
               return;
             }
             if (authService.isReg) {
               router.go('home', {});
               return;
             }
           } else if (mode == NOT_AUTH) {
             if (authService.isAuth) {
               router.go('register', {});
               return;
             }
           }
           ngView(e);
         };
       }
    

    }

    免责声明:这只是一个想法……可能完全行不通。

    【讨论】:

    • 感谢您的回复!就您提出的解决方案而言,例如,如果我必须向服务器发出请求以验证缓存的访问令牌是否有效 - 取决于异步行为会否决此解决方案?
    • 我相信应该可以异步调用ngView(e)
    • 所以您提出的解决方案确实有效,但如果异步调用 ngView() 则它不起作用。没有错误被抛出,日志也没有表明任何问题,视图永远不会显示。
    【解决方案2】:

    嗯,我在 Dart 中做了一个东西,它与以前的一个解决方案很接近,但它并没有真正起作用。重点是在RouteEventHandler中,需要调用视图的RouteEventHandler

          ..addRoute(
              name: 'userAdd',
              path: '/userAdd',
              enter: checkAuthentication(router,view,'view/addUser.html'))
          ..addRoute(
            name: 'login',
            path: '/login',
            enter: view('view/login.html'));
      }
    
      RouteEventHandler checkAuthentication(Router router,ViewFactory view, String location){
         return (RouteEvent e) {
          if(_authenticationService.isAuthenticated()){
            view(location)(e);
          }else{
            router.go("login",{});
          }
        };
      }
    

    【讨论】:

      【解决方案3】:

      注意:这仅适用于 AngularJS,以防万一使用 JS 的人需要它。

      查看$routeProvider 中的resolve 属性。您可以返回一个承诺,该承诺将确定是否应接受路由更改。

      来自文档:

      如果这些依赖项中的任何一个是承诺,路由器将等待它们全部解决或在控制器实例化之前被拒绝。如果所有的 Promise 都成功解决,则注入已解决的 Promise 的值并触发 $routeChangeSuccess 事件。如果任何一个 Promise 被拒绝,$routeChangeError 事件就会被触发。

      egghead.io here上还有一个关于它和路线生命周期的视频

      【讨论】:

      • 不幸的是,这不适用于 Angular.Dart
      【解决方案4】:

      我知道以下解决方案不适用于 Angular.Dart,但仍然值得一提的是 ui-router 的解决方案:

      https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-create-rules-to-prevent-access-to-a-state

      app.config(function($stateProvider) {
        $stateProvider.state('privatePage', {
        data: {
          rule: function(user) {
          // ...
        }
      });
      });
      app.run(function($rootScope, $state, $currentUser) {
      $rootScope.$on('$stateChangeStart', function(e, to) {
      if (!angular.isFunction(to.data.rule)) return;
      var result = to.data.rule($currentUser);
      
      if (result && result.to) {
        e.preventDefault();
        // Optionally set option.notify to false if you don't want 
        // to retrigger another $stateChangeStart event
        $state.go(result.to, result.params, {notify: false});
      }
      });
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-12-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-17
        • 1970-01-01
        相关资源
        最近更新 更多