正在加载视图配置

Loading view configuration

本文关键字:配置 视图 加载      更新时间:2023-09-26

我想做这样的事情:

app.config(function($routeProvider){
$routeProvider.when('products/list', {
    controller: 'ProductListCtrl',
    templateUrl : 'products/list/view.html',
    resolve : { data : function(){
        ...
    },
    loadingTemplateUrl : 'general/loader.html'
}
});

我想将加载页面放在不同的视图中。

这将使每个页面的视图和控制器中的代码更清晰,(没有<...ng-include ng-show="load"...>).这也意味着我不必$scope.$watch数据进行更改。是否有一个干净的解决方案来做类似的事情(不一定在 .config 方法中)或替代库来做到这一点?

假设您想在解析数据时显示所有状态转换的一些通用模板,我的建议是侦听路由库触发的事件。这允许使用一个中心点来处理所有状态转换,而不是污染路由配置(我认为这并不容易做到)。

请参阅$routeChangeStart的文档,$routeChangeSuccess,当然还有角度路由器文档中的$routeChangeError文档

也许有人可能对我所做的事情感兴趣:我创建了一个新服务和一个新的视图指令。这似乎有很多工作,但这样做比我预期的要容易得多。新服务使我能够将主视图与加载视图分开,我可以在应用程序的所有页面中重用。我还提供了配置错误模板 url 和错误控制器的可能性,以便在加载失败时使用。

Angular $injector、$templateRequest 和 $controller 服务完成了大部分工作。我只需要将依赖于这些服务的指令连接到正确的事件 ($locationChangeSuccess) 以及从解析对象的函数中检索(使用 $q.all)的承诺。此连接是在路由服务中完成的。该服务选择正确的模板 url 和主计员,并将其传递给指令进行处理。

缩短版本(省略了getCurrentConfig方法):

路由服务:

(function () {
    'use strict';
// provider: 
    angular.module('pikcachu')
        .provider('pikaRouteService', [function () {
        var routeConfigArray;
        var otherwiseRouteConfig;
        //configuration methods
        this.when = function (url, routeConfig){
            routeConfigArray.push({url: url, routeConfig: routeConfig});
            return this; 
        }
        this.otherwise = function(routeConfig){
            otherwiseRouteConfig = routeConfig;
            return this;
        }
        // service factory:
        this.$get = ['$rootScope', '$location', '$q', '$injector', '$templateRequest', 
            function ($rootScope, $location, $q, $injector, $templateRequest) {
                function RouteService() {
                    this.setViewDirectiveUpdateFn = function(){ /*...*/ }
                    function init(){
                        $rootScope.$on('$locationChangeSuccess', onLocationChangeSuccess);
                    }
                    function onLocationChangeSuccess(){
                        // get the configuration based on the current url
                        // getCurrentConfig is a long function, because it involves parsing the templateUrl string parameters, so it's left out for brevity
                        var currentConfig = getCurrentConfig($location.url());
                        if(currentConfig.resolve !== undefined){
                            // update view directive to display loading view
                        viewDirectiveUpdateFn(currentConfig.loadingTemplateUrl, currentConfig.loadingController);
                            // resolve
                            var promises = [];
                            var resolveKeys = [];
                            for(var resolveKey in currentConfig.resolve){
                               resolveKeys.push(resolveKey);
                               promises.push($injector.invoke(resolve[resolveKey]));
                            }
                            $q.all(promises).then(resolveSuccess, resolveError);
                            function resolveSucces(resolutionArray){
                               // put resolve results in an object
                               var resolutionObject = {};
                               for(var i = 0; i< promises.length;++i){
                                  resolved[resolveKeys[i]] = resolutionArray[i];
                               }
                                 viewDirectiveUpdateFn(currentConfig.errorTemplateUrl, currentConfig.errorController);
                            }
                            function resolveError(){
                                viewDirectiveUpdateFn(currentConfig.errorTemplateUrl, currentConfig.errorController);
                            }
                        }
                    }
                    init();
                }
                return new RouteService();
            }]
    })();

查看指令

(function () {
    'use strict';
    angular.module('pikachu')
        .directive('pikaView', ['$templateRequest', '$compile', '$controller', 'pikaRouteService', function ($templateRequest, $compile, $controller, pikaRouteService) {
            return function (scope, jQdirective, attrs) {
                var viewScope;
                function init() {
                    pikaRouteService.listen(updateView);
                }
                function updateView(templateUrl, controllerName, resolved) {
                    if(viewScope!== undefined){
                        viewScope.$destroy();
                    }
                    viewScope = scope.$new();
                    viewScope.resolved = resolved;
                    var controller = $controller(controllerName, { $scope: viewScope });
                    $templateRequest(templateUrl).then(onTemplateLoaded);
                    function onTemplateLoaded(template, newScope) {
                        jQdirective.empty();
                        var compiledTemplate = $compile(template)(newScope);
                        jQdirective.append(compiledTemplate);
                    }
                }
                init();
            };
        }
    ]);
})();