javascript AngularJS ui-router:如何为所有路由全局解析典型数据?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28237952/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 08:38:51  来源:igfitidea点击:

AngularJS ui-router: how to resolve typical data globally for all routes?

javascriptangularjsangular-ui-routerangularjs-service

提问by Sray

I have an AngularJS service which communicates with the server and returns translations of different sections of the application:

我有一个 AngularJS 服务,它与服务器通信并返回应用程序不同部分的翻译:

angular
     .module('utils')
     .service('Translations', ['$q','$http',function($q, $http) {
        translationsService = {
            get: function(section) {
                if (!promise) {
                    var q = $q.defer();
                    promise = $http
                            .get(
                                '/api/translations',
                                {
                                    section: section
                                })
                            .success(function(data,status,headers,config) {
                                q.resolve(result.data);
                            })
                            .error(function(data,status,headers,config){ 
                                q.reject(status);
                            });
                    return q.promise;
                }
            }
        };

        return translationsService;
    }]);

The name of the section is passed as the sectionparameter of the getfunction.

该部分的名称作为函数的section参数传递get

I'm using AngularJS ui-router module and following design pattern described here

我正在使用 AngularJS ui-router 模块并遵循此处描述的设计模式

So I have the following states config:

所以我有以下状态配置:

angular.module('app')
    .config(['$stateProvider', function($stateProvider) {
    $stateProvider
    .state('users', {
        url: '/users',
        resolve: {
            translations: ['Translations',
                function(Translations) {
                    return Translations.get('users');
                }
            ]            
        },
        templateUrl: '/app/users/list.html',
        controller: 'usersController',
        controllerAs: 'vm'
    })
    .state('shifts', {
        url: '/shifts',
        resolve: {
            translations: ['Translations',
                function(Translations) {
                    return Translations.get('shifts');
                }
            ]            
        },
        templateUrl: '/app/shifts/list.html',
        controller: 'shiftsController',
        controllerAs: 'vm'
    })

This works fine but as you may notice I have to explicitly specify translationsin the resolve parameter. I think that's not good enough as this duplicates the logic.

这工作正常,但您可能会注意到我必须translations在解析参数中明确指定。我认为这还不够好,因为这重复了逻辑。

Is there any way to resolve translations globally and avoid the code duplicates. I mean some kind of middleware.

有什么方法可以全局解析翻译并避免代码重复。我的意思是某种中间件。

I was thinking about listening for the $stateChangeStart, then get translations specific to the new state and bind them to controllers, but I have not found the way to do it.

我正在考虑监听$stateChangeStart,然后获取特定于新状态的翻译并将它们绑定到控制器,但我还没有找到这样做的方法。

Any advice will be appreciated greatly.

任何建议将不胜感激。

Important note: In my case the resolved translations objectmust contain the translations data, not service/factory/whatever.

重要说明:在我的情况下,已解决的translations object必须包含翻译数据,而不是服务/工厂/任何东西。

Kind regards.

亲切的问候。

采纳答案by Sray

Though this is a very old question, I'd like to post solution which I'm using now. Hope it will help somebody in the future. After using some different approaches I came up with a beautiful angularjs pattern by John Papa

虽然这是一个非常古老的问题,但我想发布我现在正在使用的解决方案。希望它会在将来对某人有所帮助。在使用了一些不同的方法后,我想出了一个由约翰·帕帕 (John Papa) 编写漂亮的 angularjs 模式

He suggest using a special service routerHelperProviderand configure states as a regular JS object. I'm not going to copy-paste the entire provider here. See the link above for details. But I'm going to show how I solved my problem by the means of that service.

他建议使用特殊服务routerHelperProvider并将状态配置为常规 JS 对象。我不会在这里复制粘贴整个提供程序。有关详细信息,请参阅上面的链接。但我将展示我如何通过该服务解决我的问题。

Here is the part of code of that provider which takes the JS object and transforms it to the states configuration:

这是该提供程序的部分代码,它接受 JS 对象并将其转换为状态配置:

function configureStates(states, otherwisePath) {
    states.forEach(function(state) {
        $stateProvider.state(state.state, state.config);
});

I transformed it as follows:

我将其转换如下:

function configureStates(states, otherwisePath) {

    states.forEach(function(state) {

        var resolveAlways = {

            translations: ['Translations', function(Translations) {

                if (state.translationCategory) {

                    return Translations.get(state.translationCategory);

                } else {

                    return {};

                }

            }],

        };  



        state.config.resolve =

            angular.extend(state.config.resolve || {}, resolveAlways || {});



        $stateProvider.state(state.state, state.config);

    }); 

}); 

And my route configuration object now looks as follows:

我的路由配置对象现在如下所示:

        {
            state: ‘users',
            translationsCategory: ‘users',
            config: {
                controller: ‘usersController'
                controllerAs: ‘vm',
                url: ‘/users'.
                templateUrl: ‘users.html'
            }

So what I did:

所以我做了什么:

I implemented the resolveAlwaysobject which takes the custom translationsCategoryproperty, injects the Translationsservice and resolves the necessary data. Now no need to do it everytime.

我实现了resolveAlways采用自定义translationsCategory属性的对象,注入Translations服务并解析必要的数据。现在不需要每次都这样做。

回答by Radim K?hler

Let me show you my approach. There is a working plunker

让我告诉你我的方法。有一个工作plunker

Let's have a translation.jsonlike this:

让我们有一个translation.json这样的:

{
  "home" : "trans for home",
  "parent" : "trans for parent",
  "parent.child" : "trans for child"
}

Now, let's introduce the super parent stateroot

现在,我们来介绍一下超级父状态root

$stateProvider
  .state('root', {
    abstract: true,
    template: '<div ui-view=""></div>',
    resolve: ['Translations'
      , function(Translations){return Translations.loadAll();}]
  });

This super root state is not having any url(not effecting any child url). Now, we will silently inject that into every state:

这个超级根状态没有任何url(不影响任何子网址)。现在,我们将悄悄地将其注入每个状态:

$stateProvider
  .state('home', {
      parent: 'root',
      url: "/home",
      templateUrl: 'tpl.html',
  })
  .state('parent', {
      parent: 'root',
      url: "/parent",
      templateUrl: 'tpl.html',
  })

As we can see, we use setting parent- and do not effect/extend the original state name.

正如我们所见,我们使用设置parent- 并且不影响/扩展原始状态名称

The root state is loading the translations at one shot via new method loadAll():

根状态通过新方法一次性加载翻译loadAll()

.service('Translations', ['$http'
    ,function($http) {
    translationsService = {
      data : {},
      loadAll : function(){
        return $http
          .get("translations.json")  
          .then(function(response){
            this.data = response.data;    
            return this.data;
          })
      },
      get: function(section) {
        return data[section];
      }
    };

    return translationsService;
}])

We do not need $qat all. Our super root state just resolves that once... via $httpand loadAll()method. All these are now loaded, and we can even place that service into $rootScope:

我们根本不需要$q。我们的超级根状态只是解决了一次……通过$httploadAll()方法。所有这些现在都已加载,我们甚至可以将该服务放入$rootScope

.run(['$rootScope', '$state', '$stateParams', 'Translations',
  function ($rootScope, $state, $stateParams, Translations) {
    $rootScope.$state = $state;
    $rootScope.$stateParams = $stateParams;
    $rootScope.Translations = Translations;
}])

And we can access it anyhwere like this:

我们可以像这样访问它:

<h5>Translation</h5>
<pre>{{Translations.get($state.current.name) | json}}</pre>

Wow... that is solution profiting almost from each feature coming with UI-Router... I'd say. All loaded once. All inherited because of $rootScope and view inheritance... all available in any child state...

哇...这是几乎从 UI-Router 附带的每个功能中获利的解决方案...我想说。全部加载一次。由于 $rootScope 和视图继承而继承的所有...在任何子状态都可用...

Check that all here.

检查所有这里