1. 程式人生 > >angularJS+ui-router+requireJS非同步載入controller、directive、filter

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'
                },
                '[email protected]': {
                    templateUrl: 'views/home/topbar.html'
                },
                '[email protected]': {
                    templateUrl: 'views/home/home.html'
                },
                '[email protected]': {
                    templateUrl: 'views/home/footer.html'
                }
            }
    })
    // 模組1
    .state("index.news",{
        url:"/news",       
        views: {
                '[email protected]': {
                    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: {
                '[email protected]': {
                    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;
            }
        );        
    });
});

自定義指令以及過濾器的寫法也類似噢~