angularJS+ui-router+requireJS异步加载controller、directive、filter

开发比较复杂的单页面应用时,往往包括比较多的控制器、服务等,如果这些js文件都在页面打开时就全部加载,往往加载量大,耗时长;因此,当打开对应的页面才加载响应的控制器等资源时,能一定程度地优化页面加载速度。

· 项目目录结构:
这里写图片描述

· index.html:

<html>
    <head>
        <title></title>
    </head>
    <body>
        <div ui-view></div>
        <script type="text/javascript" src="js/libs/require.js" data-main="js/main"></script>
    </body>
</html>

· main.js

require.config({
    baseUrl: 'js',
    paths: {
        'app': 'app',
        'angular': 'libs/angular.min',
        'router': 'libs/angular-ui-router'
    },
    shim: {
        'angular': {
            exports: 'angular'
        },
        'router': {
            deps: ['angular']
        },
        'app': {
            deps: ['router']
        }
    }
})
// 手动初始化myModule模块
require(['app'],function(){
    angular.bootstrap(document, ['myModule'])       
})

在main.js中配置文件路径,初始化模块。此处使用angular.bootstrap完成模块的手动加载

· 各模块视图
先来看一下views中包含的文件:
这里写图片描述
home文件夹里的是每一个视图都包含的相同的视图部分,比如PC网站每一个页面都有相同的导航栏,底部版权信息,这类视图分块就可以单独抽出来,再在app.js中嵌套到路由中。

../home/index.html:

<!--主模块结构-->
<div class="container">
    <div ui-view="topbar"></div>
    <div ui-view="main"></div>
    <div ui-view="footer"></div>
</div>

../home/topbar.html:

<a ui-sref="index">首页</a>
<a ui-sref="index.news">资讯动态</a>
<a ui-sref="index.community">社区科普</a>
<a ui-sref="index.resource">科普资源</a>
<a ui-sref="index.signin">活动报名</a>
<a ui-sref="index.learn">在线学习</a>
<a ui-sref="index.notice">通知公告</a>
<a ui-sref="index.service">志愿者服务</a>
<a ui-sref="index.about">关于我们</a>

· app.js

define(['angular','router'],function(){
    var app = angular.module("myModule", ['ui.router'])
    app.config(function($controllerProvider,$compileProvider,$filterProvider,$provide){     
        app.register = {
            //得到$controllerProvider的引用
            controller : $controllerProvider.register,
            //同样的,这里也可以保存directive/filter/service的引用
            directive: $compileProvider.directive,
            filter: $filterProvider.register,
            service: $provide.service
        };
    })
.config(['$stateProvider','$urlRouterProvider',function($stateProvider, $urlRouterProvider){
    $urlRouterProvider.otherwise('/index');
    $stateProvider
    .state("index",{
        url:"/index",
        views: {
                '': {
                    templateUrl: 'views/home/index.html'
                },
                'topbar@index': {
                    templateUrl: 'views/home/topbar.html'
                },
                'main@index': {
                    templateUrl: 'views/home/home.html'
                },
                'footer@index': {
                    templateUrl: 'views/home/footer.html'
                }
            }
    })
    // 模块1
    .state("index.news",{
        url:"/news",       
        views: {
                'main@index': {
                    templateUrl: 'views/modules/news/news.html',
                    controller: 'newsCtrl',
                    resolve: {
                        loadCtrl: ["$q", function($q) { 
                            var deferred = $q.defer();
                            //异步加载controller/directive/filter/service
                            require([
                                'directives/myDirective',
                                'filters/sexFilter',
                                'controller/newsCtrl'
                                ], function() { deferred.resolve(); });
                             return deferred.promise;
                        }]
                    },
                }
            }
    })    
    // 模块2
    .state("index.about",{
        url:"/about",
        views: {
                'main@index': {
                    templateUrl: 'views/modules/about/about.html',
                    controller: 'aboutCtrl',
                    resolve: {
                        loadCtrl: ["$q", function($q) { 
                            var deferred = $q.defer();
                            //异步加载controller/directive/filter/service
                            require([
                                'controller/aboutCtrl'
                            ], function() { deferred.resolve(); });
                            return deferred.promise;
                        }]
                    }                     
                }
            },
    })       
}])
    return app;
})

此处使用了路由嵌套,由于views可能包含多个视图,所以对应视图的controller记得写在响应的视图定义区域内噢。

· newsService.js:

define(['app'],function(app){
    //Service比较特殊,加载后还需要手动注入控制器
    app.register.service('newsService', function($http, $q){
        return {
            getData:function(){
                var deferred = $q.defer();
                var promise = $http.get("/json/news.json");
                promise.then(
                    // 通讯成功的处理
                    function(answer){
                        //在这里可以对返回的数据集做一定的处理,再交由controller进行处理
                        answer.status = true;
                        deferred.resolve(answer);
                    },
                    // 通讯失败的处理
                    function(error){
                        // 可以先对失败的数据集做处理,再交由controller进行处理
                        error.status = false;
                        deferred.reject(error);
                        console.log("获取资讯动态数据失败");
                    });
                //返回promise对象,交由controller继续处理成功、失败的业务回调
                return deferred.promise;
            }
        }
    })
})

· newsCtrl.js:

define(['app','service/newsService'],function(app){
    // 控制器 将服务器手动注入控制器中
    app.register.controller('newsCtrl', function($scope,newsService){
        newsService.getData().then(
            function(answer){
                $scope.newsList = answer.data;
            },
            function(error){
                $scope.error = error;
            }
        );        
    });
});

自定义指令以及过滤器的写法也类似噢~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章