一尘不染

如何在UI-Router中装饰当前状态解析功能?当前函数未调用

angularjs

我正在尝试干燥,$stateProvider并防止auth在每个解析中添加相同的功能。我已经创建了装饰器,该装饰器在每个状态更改时都会将此函数添加到当前状态,但auth不会调用该函数,如何修复它或如何解决所讨论的问题?

app.config(function ($stateProvider, $urlRouterProvider, $provide) {
  $provide.decorator('$state', function($delegate, $rootScope) {
    $rootScope.$on('$stateChangeStart', function(event, state, params) {
      if ($delegate.current === "login" || $delegate.current === "register") {
        return;
      }
      console.log("decorator", $delegate);
      $delegate.current.resolve = {
        auth: ['AuthService', '$stateParams', function(AuthService, $stateParams) {
          //how to invoke this function?
          if (AuthService.isAuthenticated()) {
            return AuthService.me(); //promise
          } else {
            return false;
          }
        }]
      };
    });
    return $delegate;
  });

状态定义:

  $stateProvider.state('root', {
    abstract: true,
    url: '/',
    views: {
      "": {
        controller: 'RootCtrl',
        templateUrl: 'views/root.html'
      },
      "header@root": {
        templateUrl: 'views/header.html'
      }
    }
  })
  .state('root.home', {
    url: urlPrefix,
    views: {
      "content@artworks": {
        templateUrl: 'views/home.html',
        //resolve: {
        //  auth: ['AuthService', '$stateParams', function(AuthService, $stateParams) {
        //  }]
        //}
      }
    }
  })
  ...

阅读 188

收藏
2020-07-04

共1个答案

一尘不染

如果我正确理解您的要求,我们可以使用本机UI-Router内置的 decorator

[decorator(name, func)](http://angular-ui.github.io/ui-

router/site/#/api/ui.router.state.$stateProvider#methods_decorator)

允许您扩展(谨慎)或重写(自担风险)由$ stateProvider内部使用的stateBuilder对象。这可用于向ui-
router添加自定义功能,例如,基于状态名称推断templateUrl … (请参阅 doc中的更多内容

一个工作的家伙

所以,我们可以有这个 var auth

var auth = ['AuthService', '$stateParams',
  function(AuthService, $stateParams) {
    //how to invoke this function on needed states?
    if (AuthService.isAuthenticated()) {
      return AuthService.me();
    } else {
      return false;
    }
  }
];

在这里,我们仅使用带有“ IF”逻辑的装饰器

.config(['$stateProvider', 
  function($stateProvider) {

    $stateProvider.decorator('views', function(state, parent) {
      var result = {},
        views = parent(state);

      // some naive example when to not inject resolve
      if (state.name === "home") { 
        return views;
      }
      // child already has that in parent
      if (state.name.indexOf(".") > 0) { 
        return views;
      }

      angular.forEach(views, function(config, name) {

        // here inject the resolve (if not existing)
        config.resolve = config.resolve || {};
        // and extend it with the auth stuff above
        config.resolve.auth = auth;

        result[name] = config;
      });

      return result;
    });

  }
])

后来我们的几个州,将由上述内容扩展

$stateProvider
    .state('home', {
      url: "/home",
      templateUrl: 'tpl.html',
    })
    .state('parent', {
      url: "/parent",
      templateUrl: 'tpl.html',
      controller: 'SharedCtrl',
    })
    .state('parent.child', {
      url: "/child",
      templateUrl: 'tpl.html',
      controller: 'SharedCtrl',
    });

这里检查它的作用

2020-07-04