混淆 $locationChangeSuccess 和 $stateChangeStart [英] Confusing $locationChangeSuccess and $stateChangeStart

查看:18
本文介绍了混淆 $locationChangeSuccess 和 $stateChangeStart的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 AngularUI 路由器进行一些身份验证.$urlRouter.sync() 看起来正是我需要的.但是,这仅在我拦截 $locationChangeSuccess 时可用.但是当我这样做时, $state.current.name 是空的,而我希望它是当前状态.

I am trying to do some authentication with AngularUI Router. $urlRouter.sync() looks like exactly what I need. However, that's only available when I intercept $locationChangeSuccess. But when I do that, $state.current.name is empty, whereas I want it to be the current state.

这是我目前的代码:

$rootScope.$on('$locationChangeSuccess', function(event, next, nextParams) {
  event.preventDefault();
  if ($state.current.name === 'login') {
    return userService.isAuthenticated().then(function(response) {
      var authenticated;
      authenticated = response.authenticated;
      return alert(authenticated);
    });
  }
});

任何关于我做错了什么的提示?

Any pointers as to what I'm doing wrong?

推荐答案

我建议多走UI-Router 方式".我们应该使用 $rootScope.$on('$stateChangeStart' 事件,其中 $state.current 将被正确提供.这里是 一个工作示例

I would suggest to go more "UI-Router way". We should use $rootScope.$on('$stateChangeStart' event where $state.current would be properly provided. Here is a working example

让我们观察简单的(但不是幼稚的) 解决方案,它可以在以后扩展到任何程度.此外,如果您喜欢这种方法,这里有更全面的实现:angular ui-router login authentication

Let's observe simple (but not naive) solution, which could be extended to any degree later. Also if you will like this approach, here is much more comprehensive implementation: angular ui-router login authentication

首先,让我们像这样定义我们的用户服务:

Firstly, let's have our user service defined like this:

.factory('userService', function ($timeout, $q) {

    var user = undefined;

    return {
        // async way how to load user from Server API
        getAuthObject: function () {
            var deferred = $q.defer();

            // later we can use this quick way -
            // - once user is already loaded
            if (user) {
                return $q.when(user);
            }

            // server fake call, in action would be $http
            $timeout(function () {
                // server returned UN authenticated user
                user = {isAuthenticated: false };
                // here resolved after 500ms
                deferred.resolve(user)
            }, 500)

            return deferred.promise;
        },

        // sync, quick way how to check IS authenticated...
        isAuthenticated: function () {
            return user !== undefined
                && user.isAuthenticated;
        }
    };    
})

因此,我们使用 async (here $timeout) 从服务器加载 user 对象.在我们的示例中,它将有一个属性 {isAuthenticated: false },用于检查是否已通过身份验证.

So, we use async (here $timeout) to load user object form a server. In our example it will have a property {isAuthenticated: false }, which will be used to check if is authenticated.

还有同步方法 isAuthenticated(),在加载并允许用户之前,它总是返回 false.

There is also sync method isAuthenticated() which, until user is loaded and allowed - always returns false.

这就是我们对 '$stateChangeStart' 事件的监听器:

And that would be our listener of the '$stateChangeStart' event:

.run(['$rootScope', '$state', 'userService',
 function ($rootScope, $state, userService) {

     $rootScope.$on('$stateChangeStart', function (event, toState,   toParams
                                                        , fromState, fromParams) {    
        // if already authenticated...
        var isAuthenticated = userService.isAuthenticated();
        // any public action is allowed
        var isPublicAction = angular.isObject(toState.data)
                           && toState.data.isPublic === true;    

        if (isPublicAction || isAuthenticated) {
          return;
        }

        // stop state change
        event.preventDefault();

        // async load user 
        userService
           .getAuthObject()
           .then(function (user) {

              var isAuthenticated = user.isAuthenticated === true;

              if (isAuthenticated) {
                // let's continue, use is allowed
                $state.go(toState, toParams)
                return;
              }    
              // log on / sign in...
              $state.go("login");
           })
       ...

我们首先要检查的是用户是否已经加载并通过身份验证(var isAuthenticated = ...).接下来,我们将为任何公共方法赋予绿色.这是通过状态对象定义的 data {} 属性完成的(请参阅 将自定义数据附加到状态对象)

What we are checking first, is if user is already loaded and authenticated (var isAuthenticated = ...). Next we will give green to any public method. This is done with the data {} property of the state object definition (see Attach Custom Data to State Objects)

就是这样.如果像下面的代码片段那样定义状态,我们可以体验:

And that's it. In case of states defined like in a below snippet we can experience:

  • 'public', 'home' 任何人都可以使用
  • 'private', 'private' 将重定向到登录如果 isAuthenticated === false
  • 本示例中的 'login' 提供了如何打开/关闭 isAuthenticated 的快速方法

  • the 'public', 'home' are allowed to anybody
  • the 'private', 'private' will redirect to login if isAuthenticated === false
  • the 'login' in this example provides quick way how to switch isAuthenticated on/off

// States
$stateProvider

  // public
  .state('home', {
      url: "/home",
      templateUrl: 'tpl.html',
      data: { isPublic: true },
  })
  .state('public', {
      url: "/public",
      templateUrl: 'tpl.html',
      data: { isPublic: true },
  })
  // private
  .state('private', {
      url: "/private",
      templateUrl: 'tpl.html',
  })
  .state('private2', {
      url: "/private2",
      templateUrl: 'tpl.html',
  })

  // login
  .state('login', {
      url: "/login",
      templateUrl: 'tpl.html',
      data: { isPublic: true },
      controller: 'loginCtrl',
  })

检查所有这里

其他一些资源:

这篇关于混淆 $locationChangeSuccess 和 $stateChangeStart的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆