【问题标题】:Reload a controller not managed by ngRoute on route change在路由更改时重新加载不受 ngRoute 管理的控制器
【发布时间】:2015-10-30 18:37:23
【问题描述】:

我的web应用登录流程如下,

一个。用户点击登录按钮,链接将他们带到http://localhost:3030/login/facebook

b. NodeJS 后端接收请求,并使用 passport-facebook 将浏览器定向到 Facebook 登录页面。

c。然后,Facebook 使用一些用户数据将用户引导回回调。 (回调:http://localhost:3030/login/facebook/callback

d。使用用户数据,帐户要么存在,要么将被创建,并且将创建属于该帐户的令牌(使用 JWT)

e。该令牌将通过重定向到http://localhost:3030/#/got_token/the_actual_jwt_string

发送给用户

f。 AngularJS 应用程序将使用 ngRoute 进行路由,并将令牌保存在 localStorage 中。

NodeJS 中的令牌发行代码,

server.get('/auth/facebook', passport.authenticate('facebook', {session: false}));
server.get('/auth/facebook/callback', passport.authenticate('facebook', {session: false}), function(req, res) {
  var token = jwt.sign(/* issue a token */);
  // put the token into database
  res.header('Location', 'http://localhost:3030/#/got_token/' + token);
  res.send(302);
});

AngularJS中的路由代码,

.when('/got_token/:token*', {
   redirectTo: function(parameters, path, search) {
     localStorage.setItem('ngStorage-token', JSON.stringify({
       token: parameters.token
      }));
     return '/';
    }
 })

这很好用,直到我的视图层次结构看起来像这样,

<body ng-controller="NavigationViewController">
  <div ng-view>
  </div>
</body>

还有控制器代码,

controllers.controller('NavigationViewController', ['$scope', '$route', 'token', function($scope, $route, token) {
    var _token = token.retrieve();
    $scope.token = _token;
    $scope.authenticated = (_token != '');
    if ($scope.authenticated) {
      var payload_string = b64utos(_token.split('.')[1]);
      var payload = KJUR.jws.JWS.readSafeJSONString(payload_string);
      $scope.displayName = payload.facebookDisplayName;
    } else {
      $scope.displayName = 'no';
    }
    $scope.logout = function() {
      token.clear();
    };
}]);

ngRoute 完成的路由不会重新创建我的NavigationViewController,而是将_token 变量设置为之前的状态。

我需要一种方法让NavigationViewController 知道令牌已更改,因为它不参与路由。

【问题讨论】:

  • 它不是很清楚你想要什么。您的意思是NavigationViewController 需要知道或获取一些事件,以便在令牌更改后立即通知它?什么时候改变?登录后为什么token会变!
  • @Салман 是的,NavigationViewController 需要知道。令牌只在登录/注销时改变,我把登录逻辑放在路由中,注销逻辑放在NavigationViewController
  • 为什么我认为它不正确,或者我应该说这样做的标准方式?您可以使用 ui-router 并且登录和注销应该是单独的路由,因为所有需要身份验证的页面都应该是一个或多个 abstract 视图的子级。你是故意走这条路还是不知道另一条路?
  • @Салман 我刚开始学习 AngularJS,对所有流行的模块都不熟悉。您建议切换到ui-router 是我打算学习的一件事,但我在这里看到的问题与路由无关。我只使用路由将令牌送回。我的另一个应用程序不依赖 Facebook,因此它的身份验证过程是一个 POST 请求,可以在控制器中完成。然而,Facebook 需要做很多工作,并且不能单独嵌入(据我所知)控制器中。

标签: javascript angularjs node.js passport.js passport-facebook


【解决方案1】:

最后,使用了一个简单的解决方案——事件。

正如我的问题的标题所示,我想在路由更改时重新加载嵌套的父视图控制器。由于嵌套层次结构的父级不受ngRoute 管理,因此它不会自动执行此操作。但是,ngRoute 有一个服务 ($route) 会发出事件,这是最简单的答案。

基本上,我将所有的初始化代码放到一个函数中,并在事件中调用该函数。

controllers.controller('NavigationViewController', ['$scope', '$route', '$location', 'token', function($scope, $route, $location, token) {
    var updateNavigationBar = function() {
      var _token = token.retrieve();
      $scope.token = _token;
      $scope.authenticated = (_token != '');
      if ($scope.authenticated) {
        var payload_string = b64utos(_token.split('.')[1]);
        var payload = KJUR.jws.JWS.readSafeJSONString(payload_string);
        $scope.displayName = payload.facebookDisplayName;
      } else {
        $scope.displayName = 'no';
      }
    };

    $scope.$on('$routeChangeSuccess', function(event, current, previous) {
      if ($location.path() == '/events') {
        updateNavigationBar();
      }
    });

    updateNavigationBar();
}]);

【讨论】:

    【解决方案2】:

    看起来您需要在控制器之间传递数据。这是您可以做到的一种方法。在您的NavigationViewController 中监听changedemit 中的事件,当它发生变化时。绑定到rootScope

    angular.module('app', [])
    
    .controller('LoginCtrl', function ($scope, $rootScope) {
        $scope.changeToken = function () {
            $rootScope.$emit('changed', +new Date());
        }
    })
    
    .controller('NavigationViewController', function ($scope, $rootScope) {
        $scope.token = null;
    
        $rootScope.$on('changed', function(event, token) {
            $scope.token = token;
        });
    })
    

    【讨论】:

      【解决方案3】:

      想建议你两个想法。这里是这两个。 (1.) 您可以将 $watch 添加到令牌中,以便无论何时更改它都会自动反映。 (2.) 将令牌分配到 rootscope 并在令牌更改时更新它。

      如果你需要的话,我也想给你例子。

      问候, 马亨德拉

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-03-29
        • 2020-04-29
        • 2014-02-03
        • 2021-12-16
        • 2012-08-20
        • 2017-05-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多