From f01e1043c085a51192612f747b64089b128a807b Mon Sep 17 00:00:00 2001 From: TZ Date: Sun, 20 Oct 2013 21:52:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=86=8D=E6=AC=A1=E9=87=8D=E6=9E=84,=20?= =?UTF-8?q?=E5=B9=B6=E4=BF=AE=E6=94=B9=E9=A1=B9=E7=9B=AE=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=E4=B8=BA=20`angular-lazyload`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TZ --- Gruntfile.js | 6 +- README.md | 46 +++++---- bower.json | 8 +- dist/angular-lazyload.js | 113 +++++++++++++++++++++ dist/angular-lazyload.min.js | 2 + dist/angular-seajs.js | 121 ----------------------- dist/angular-seajs.min.js | 2 - example/src/app.js | 14 +-- example/src/index.html | 17 ++-- example/src/modules/module1/testACtrl.js | 2 +- package.json | 8 +- src/angular-lazyload.js | 112 +++++++++++++++++++++ src/angular-seajs.js | 120 ---------------------- 13 files changed, 284 insertions(+), 287 deletions(-) create mode 100644 dist/angular-lazyload.js create mode 100644 dist/angular-lazyload.min.js delete mode 100644 dist/angular-seajs.js delete mode 100644 dist/angular-seajs.min.js create mode 100644 src/angular-lazyload.js delete mode 100644 src/angular-seajs.js diff --git a/Gruntfile.js b/Gruntfile.js index 8c7d5c8..797c07e 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -11,7 +11,7 @@ module.exports = function (grunt) { //define tasks //启动Web服务器,监控变更,自动加载 - grunt.registerTask('server', ['connect', 'open', 'watch']); + grunt.registerTask('server', ['connect', 'open', 'watch:server']); grunt.registerTask('dev', ['connect', 'open', 'watch:dev']); grunt.registerTask('build', ['clean', 'concat', 'uglify']); @@ -91,7 +91,7 @@ module.exports = function (grunt) { }, build: { files: [ - {expand: true, cwd:'src/', src: ['angular-seajs.js'], dest: 'dist/'} + {expand: true, cwd:'src/', src: ['angular-lazyload.js'], dest: 'dist/'} ] } }, @@ -106,7 +106,7 @@ module.exports = function (grunt) { }, build: { files: { - 'dist/angular-seajs.min.js' : ['dist/angular-seajs.js'] + 'dist/angular-lazyload.min.js' : ['dist/angular-lazyload.js'] } } } diff --git a/README.md b/README.md index 506ff78..5f45135 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,10 @@ -# angular-seajs +# angular-lazy-load -#### 通过[Sea.js](http://seajs.org/)动态按需加载[AngularJS](http://angularjs.org) 模块。 +#### A lazyload service for angular projects, only load-on-demand, support seajs/requirejs/custom. +### 按需加载[AngularJS](http://angularjs.org)模块, 支持[Sea.js](http://seajs.org/)和[RequireJS](http://requirejs.org/‎)。 --- -**[下载](dist/angular-seajs.js)** (or **[压缩版](dist/angular-seajs.min.js)**) **|** +**[下载](dist/angular-lazyload.js)** (or **[压缩版](dist/angular-lazyload.min.js)**) **|** **[使用指南](#使用指南) |** **[基本原理](#基本原理) |** **[TODO/贡献代码](#TODO) |** @@ -15,38 +16,46 @@ ### 使用指南 **(1)** 安装 -- 通过[Bower](http://bower.io/)安装: `bower install angular-seajs` -- 直接下载: [Download](dist/angular-seajs.js) (or [Minified](dist/angular-seajs.min.js)) +- 通过[Bower](http://bower.io/)安装: `bower install angular-lazyload` +- 直接下载: [Download](dist/angular-lazyload.js) (or [Minified](dist/angular-lazyload.min.js)) -**(2)** 在你的`index.html`中先引入`angular.js`和`sea.js`。 +**(2)** 在你的`index.html`中引入`angular-lazyload`。 +``` + + + + + + + +``` -**(3)** 通过`seajs`加载`angular-seajs`, 并手动启动bootstrap。 +**(3)** 在你的启动文件里面, 手动启动bootstrap。 ``` - //修改`../../dist/angular-seajs`为`angular-seajs`的实际存放路径, app为你的主模块文件`app.js` - seajs.use(['../../dist/angular-seajs', 'app'], function(ngSea, app){ + //Step2: bootstrap youself + seajs.use(['app'], function(app){ angular.bootstrap(document, ['app']); }); ``` **(3)** 添加`angular-seajs`为你的主模块的依赖中。 ``` - //app.js - var app = angular.module('app', ['angular-seajs', 'ngRoute']); + //Step3: add 'angular-lazyload' to your main module's list of dependencies + var app = angular.module('app', ['angular-lazyload', 'ngRoute']); ``` **(4)** 在`app.run`里进行初始化。 ``` - //app.js - app.run(['$sea', function($sea){ - $sea.init(app); - //两个参数均为可选, 支持ui-route, 修改事件名为`$stateChangeStart`即可 - //$sea.init(app, '$routeChangeStart'); + app.run(['$lazyload', function($lazyload){ + //Step5: init lazyload & hold refs + $lazyload.init(app); + app.register = $lazyload.register; }]); ``` **(5)** 路由映射, 添加`controllerUrl` ``` - //app.js + //Step4: add `controllerUrl` to your route item config $routeProvider .when('/test/a', { controller: 'testACtrl', @@ -58,8 +67,7 @@ **(6)** 在你的模块里进行注册controller。 ``` - //testACtrl.js - //通过`app.register`来注册 + //Step6: use `app.register` to register controller/service/directive/filter app.register.controller('testACtrl', ['$scope', function($scope){ ... }]); diff --git a/bower.json b/bower.json index 86db304..dd91a76 100644 --- a/bower.json +++ b/bower.json @@ -1,10 +1,10 @@ { - "name": "angular-seajs", - "version": "0.3.0", + "name": "angular-lazyload", + "version": "0.4.0", "author": "TZ ", - "description": "using seajs to dynamic/lazy load angular module.", + "description": "A lazyload service for angular projects, only load-on-demand, support seajs/requirejs/custom.", "repository": { "type": "git", - "url": "https://github.com/atian25/angular-seajs" + "url": "https://github.com/atian25/angular-lazyload" } } diff --git a/dist/angular-lazyload.js b/dist/angular-lazyload.js new file mode 100644 index 0000000..344e054 --- /dev/null +++ b/dist/angular-lazyload.js @@ -0,0 +1,113 @@ +/*! angular-lazyload - v0.4.0 - https://github.com/atian25/angular-lazyload - 2013-10-21 */ +/** + * A lazyload service for angular projects, only load-on-demand, support seajs/requirejs/custom. + * support [Sea.js](http://seajs.org/) & [RequireJS](http://requirejs.org/‎) + * + * @author TZ + * @home https://github.com/atian25/angular-lazyload + */ +(function(global, undefined) { + 'use strict'; + + /** + * register `angular-lazyload` module & `$lazyload` service + */ + angular.module('angular-lazyload', [], ['$controllerProvider', '$compileProvider', '$filterProvider', '$provide', + function ($controllerProvider, $compileProvider, $filterProvider, $provide) { + //register `$lazyload` service + $provide.factory('$lazyload', ['$rootScope', '$q', function($rootScope, $q){ + //hold provide's refs, because after ng bootstrap, you can't use `app.controller` to dynamic register controller. + var register = { + controller: $controllerProvider.register, + directive: $compileProvider.directive, + filter: $filterProvider.register, + factory: $provide.factory, + service: $provide.service, + decorator: $provide.decorator + }; + return new LazyLoadProvider($rootScope, $q, register); + }]); + } + ]); + + /** + * $lazyload Service + */ + function LazyLoadProvider($rootScope, $q, register){ + //patch the $rootScope, add `safeApply` function. + patchScope($rootScope); + + /** + * hold provide's refs, because after ng bootstrap, you can't use `app.controller` to dynamic register controller. + */ + this.register = register; + + /** + * @param {Object} params This will pass to the lazy load module + * @param {String} eventName Default to `$routeChangeStart`, //TODO: support `ui-route` + * @param {Function/String} loaderType The loader function: //FIXME: only support `seajs` current. + * - 'seajs' : default value, use [Sea.js](http://seajs.org/) to async load modules + * - 'requirejs': use [RequireJS](http://requirejs.org/‎) to async load modules + * - {Function} : custom loader function: + * - route : current route item + * - callback : callback function when async load success + */ + this.init = function(params, eventName, loaderType){ + //get loaderFn: if loaderType is function, then just use it, else use build in loader by loaderType, default to seajs + var loaderFn = angular.isFunction(loaderType) ? loaderType : this.loaders[loaderType] || this.loaders['seajs']; + + //listen to route change event to hook + $rootScope.$on(eventName || '$routeChangeStart', function(e, target){ + //console.debug(e, '|', target); + var route = target && target.$$route; + if(route){ + route.resolve = route.resolve || {}; + //keypoint: use `route.resolve` + route.resolve.loadedModule = function(){ + var defer = $q.defer(); + loaderFn(route, function(m){ + $rootScope.safeApply(function(){ + defer.resolve(angular.isFunction(m) ? m(params) : m); + }); + }); + return defer.promise; + } + } + }); + } + } + + /** + * build-in loaders + */ + LazyLoadProvider.prototype.loaders = {}; + LazyLoadProvider.prototype.loaders['seajs'] = function(route, callback){ + //if exsit `controllerUrl` then trigger seajs async load. + if(typeof route.controllerUrl == 'string'){ + seajs.use(route.controllerUrl, callback); + } + } + + LazyLoadProvider.prototype.loaders['requirejs'] = function(route, callback){ + //if exsit `controllerUrl` then trigger requirejs async load. + if(typeof route.controllerUrl == 'string'){ + require(route.controllerUrl, callback); + } + } + + /** + * 为$rootScope增加safeApply方法, 安全的apply + */ + function patchScope($rootScope){ + $rootScope.safeApply = function(fn){ + var phase = this.$root.$$phase; + if(phase == '$apply' || phase == '$digest') { + if(fn && (typeof(fn) === 'function')) { + fn(); + } + } else { + this.$apply(fn); + } + }; + } +})(this); \ No newline at end of file diff --git a/dist/angular-lazyload.min.js b/dist/angular-lazyload.min.js new file mode 100644 index 0000000..b11f373 --- /dev/null +++ b/dist/angular-lazyload.min.js @@ -0,0 +1,2 @@ +/*! angular-lazyload - v0.4.0 - https://github.com/atian25/angular-lazyload - 2013-10-21 */ +!function(){"use strict";function a(a,c,d){b(a),this.register=d,this.init=function(b,d,e){var f=angular.isFunction(e)?e:this.loaders[e]||this.loaders.seajs;a.$on(d||"$routeChangeStart",function(d,e){var g=e&&e.$$route;g&&(g.resolve=g.resolve||{},g.resolve.loadedModule=function(){var d=c.defer();return f(g,function(c){a.safeApply(function(){d.resolve(angular.isFunction(c)?c(b):c)})}),d.promise})})}}function b(a){a.safeApply=function(a){var b=this.$root.$$phase;"$apply"==b||"$digest"==b?a&&"function"==typeof a&&a():this.$apply(a)}}angular.module("angular-lazyload",[],["$controllerProvider","$compileProvider","$filterProvider","$provide",function(b,c,d,e){e.factory("$lazyload",["$rootScope","$q",function(f,g){var h={controller:b.register,directive:c.directive,filter:d.register,factory:e.factory,service:e.service,decorator:e.decorator};return new a(f,g,h)}])}]),a.prototype.loaders={},a.prototype.loaders.seajs=function(a,b){"string"==typeof a.controllerUrl&&seajs.use(a.controllerUrl,b)},a.prototype.loaders.requirejs=function(a,b){"string"==typeof a.controllerUrl&&require(a.controllerUrl,b)}}(this); \ No newline at end of file diff --git a/dist/angular-seajs.js b/dist/angular-seajs.js deleted file mode 100644 index 9615d34..0000000 --- a/dist/angular-seajs.js +++ /dev/null @@ -1,121 +0,0 @@ -/*! angular-seajs - v0.3.0 - https://github.com/atian25/angular-seajs - 2013-10-20 */ -/** - * 通过[Sea.js](http://seajs.org/)动态按需加载[AngularJS](http://angularjs.org) 模块。 - * - * @author TZ - * @home https://github.com/atian25/angular-seajs - */ -define(function (require, exports, module) { - 'use strict'; - var ngSea = module.exports = angular.module('angular-seajs', []); - - /** - * 由于ng的问题, bootstrap完成后就无法通过app.controller动态注册, - * 故需保存provider的引用, 动态注册均通过 `app.register.controller`的方式。 - * service等同理。 - */ - ngSea.config(['$controllerProvider', '$compileProvider', '$filterProvider', '$provide', - function ($controllerProvider, $compileProvider, $filterProvider, $provide) { - //hold provide's refs - ngSea.register = { - controller: $controllerProvider.register, - directive: $compileProvider.directive, - filter: $filterProvider.register, - factory: $provide.factory, - service: $provide.service, - decorator: $provide.decorator - }; - } - ]).run(['$rootScope', function($rootScope){ - //console.log('init ngSea'); - patchScope($rootScope); - }]); - - /** - * register `$sea` service. - * usage: - * app.run(['$sea', function($sea){ - * $sea.init(app); - * }]); - */ - ngSea.factory('$sea', ['$rootScope', function($rootScope){ - return { - /** - * 初始化 - * @param {Module} app 主模块, 若你的module不需要传入,则可以不赋值,参见两个示例的不同点 - * @param {String} eventName 事件名,默认为$routeChangeStart。支持ui-route, 修改事件名为`$stateChangeStart`即可 - */ - init: initProvider($rootScope), - /** - * 由于ng的问题, bootstrap完成后就无法通过app.controller动态注册, - * 故需保存provider的引用, 动态注册均通过 `app.register.controller`的方式。 - */ - register: ngSea.register, - loadBySeajs: loadBySeajs - } - }]); - - - /** - * 为$route打补丁: 存在参数controllerUrl,则通过seajs动态加载Controller - */ - function initProvider($rootScope){ - return function(app, eventName){ - //hold refs to lazy register - if(app && !app.register){ - app.register = ngSea.register; - }; - - //listen event to patch route item - $rootScope.$on(eventName || '$routeChangeStart', function(e, target){ - //console.debug(e, '|', target); - var route = target && target.$$route; - if(route){ - route.resolve = route.resolve || {}; - - //if exsit `controllerUrl` then trigger seajs async load. - if(typeof route.controllerUrl == 'string'){ - //keypoint: use `route.resolve` - route.resolve.loadBySeajs = loadBySeajs(route.controllerUrl, function(m){ - if(angular.isFunction(m)){ - m(app); - } - }); - } - } - }); - } - } - - /** - * 通过SeaJS加载外部文件,返回promise - */ - function loadBySeajs(url, success, error){ - return ['$q', '$rootScope' , function($q, $rootScope){ - var defer = $q.defer(); - require.async(url, function(m){ - //console.debug('loaded module `'+url+'` from '+ seajs.resolve(url)); - $rootScope.safeApply(function (){ - defer.resolve(m); - }); - }); - return defer.promise.then(success, error); - }]; - } - - /** - * 为$rootScope增加safeApply方法, 安全的apply - */ - function patchScope($rootScope){ - $rootScope.safeApply = function(fn){ - var phase = this.$root.$$phase; - if(phase == '$apply' || phase == '$digest') { - if(fn && (typeof(fn) === 'function')) { - fn(); - } - } else { - this.$apply(fn); - } - }; - } -}); \ No newline at end of file diff --git a/dist/angular-seajs.min.js b/dist/angular-seajs.min.js deleted file mode 100644 index 235281f..0000000 --- a/dist/angular-seajs.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! angular-seajs - v0.3.0 - https://github.com/atian25/angular-seajs - 2013-10-20 */ -define(function(require,exports,module){"use strict";function a(a){return function(c,e){c&&!c.register&&(c.register=d.register),a.$on(e||"$routeChangeStart",function(a,d){var e=d&&d.$$route;e&&(e.resolve=e.resolve||{},"string"==typeof e.controllerUrl&&(e.resolve.loadBySeajs=b(e.controllerUrl,function(a){angular.isFunction(a)&&a(c)})))})}}function b(a,b,c){return["$q","$rootScope",function(d,e){var f=d.defer();return require.async(a,function(a){e.safeApply(function(){f.resolve(a)})}),f.promise.then(b,c)}]}function c(a){a.safeApply=function(a){var b=this.$root.$$phase;"$apply"==b||"$digest"==b?a&&"function"==typeof a&&a():this.$apply(a)}}var d=module.exports=angular.module("angular-seajs",[]);d.config(["$controllerProvider","$compileProvider","$filterProvider","$provide",function(a,b,c,e){d.register={controller:a.register,directive:b.directive,filter:c.register,factory:e.factory,service:e.service,decorator:e.decorator}}]).run(["$rootScope",function(a){c(a)}]),d.factory("$sea",["$rootScope",function(c){return{init:a(c),register:d.register,loadBySeajs:b}}])}); \ No newline at end of file diff --git a/example/src/app.js b/example/src/app.js index 4131fc8..509e2ed 100644 --- a/example/src/app.js +++ b/example/src/app.js @@ -2,13 +2,12 @@ define(function (require, exports, module) { "use strict"; console.log('init app...' + (new Date().getTime())); - //步骤二: 把`angular-sea`注册为主项目的依赖 - var app = angular.module('app', ['angular-seajs', 'ngRoute']); + //Step3: add 'angular-lazyload' to your main module's list of dependencies + var app = angular.module('app', ['angular-lazyload', 'ngRoute']); //配置期 app.config(['$routeProvider', function($routeProvider) { - //路由映射 - //步骤四: 提供controllerUrl, 参见对应的controller文件示例 + //Step4: add `controllerUrl` to your route item config $routeProvider .when('/test/a', { controller: 'testACtrl', @@ -34,9 +33,10 @@ define(function (require, exports, module) { ]); //运行期 - app.run(['$sea', function($sea){ - //步骤三: 初始化 - $sea.init(app); + app.run(['$lazyload', function($lazyload){ + //Step5: init lazyload & hold refs + $lazyload.init(app); + app.register = $lazyload.register; }]); module.exports = app; diff --git a/example/src/index.html b/example/src/index.html index 6ff5928..aa5b3de 100644 --- a/example/src/index.html +++ b/example/src/index.html @@ -2,11 +2,11 @@ - angular-seajs-showcase + angular-lazyload-showcase - +

A lazyload service for angular projects, only load-on-demand, support seajs/requirejs/custom.

@@ -16,15 +16,20 @@ + - - --> + + + + diff --git a/example/src/modules/module1/testACtrl.js b/example/src/modules/module1/testACtrl.js index ca9ae29..4398ead 100644 --- a/example/src/modules/module1/testACtrl.js +++ b/example/src/modules/module1/testACtrl.js @@ -5,7 +5,7 @@ define(function (require, exports, module) { 'use strict'; module.exports = function(app){ - //步骤五: 通过app.register注册controller + //Step6: use `app.register` to register controller/service/directive/filter app.register.controller('testACtrl', ['$scope', '$routeParams', '$location', '$http', function($scope, $routeParams, $location, $http){ //获取页面的入参 diff --git a/package.json b/package.json index 8defe19..3796726 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { - "name": "angular-seajs", - "version": "0.3.0", + "name": "angular-lazyload", + "version": "0.4.0", "author": "TZ ", - "description": "using seajs to dynamic/lazy load angular module.", + "description": "A lazyload service for angular projects, only load-on-demand, support seajs/requirejs/custom.", "repository": { "type": "git", - "url": "https://github.com/atian25/angular-seajs" + "url": "https://github.com/atian25/angular-lazyload" }, "devDependencies": { "grunt": "latest", diff --git a/src/angular-lazyload.js b/src/angular-lazyload.js new file mode 100644 index 0000000..92ada89 --- /dev/null +++ b/src/angular-lazyload.js @@ -0,0 +1,112 @@ +/** + * A lazyload service for angular projects, only load-on-demand, support seajs/requirejs/custom. + * support [Sea.js](http://seajs.org/) & [RequireJS](http://requirejs.org/‎) + * + * @author TZ + * @home https://github.com/atian25/angular-lazyload + */ +(function(global, undefined) { + 'use strict'; + + /** + * register `angular-lazyload` module & `$lazyload` service + */ + angular.module('angular-lazyload', [], ['$controllerProvider', '$compileProvider', '$filterProvider', '$provide', + function ($controllerProvider, $compileProvider, $filterProvider, $provide) { + //register `$lazyload` service + $provide.factory('$lazyload', ['$rootScope', '$q', function($rootScope, $q){ + //hold provide's refs, because after ng bootstrap, you can't use `app.controller` to dynamic register controller. + var register = { + controller: $controllerProvider.register, + directive: $compileProvider.directive, + filter: $filterProvider.register, + factory: $provide.factory, + service: $provide.service, + decorator: $provide.decorator + }; + return new LazyLoadProvider($rootScope, $q, register); + }]); + } + ]); + + /** + * $lazyload Service + */ + function LazyLoadProvider($rootScope, $q, register){ + //patch the $rootScope, add `safeApply` function. + patchScope($rootScope); + + /** + * hold provide's refs, because after ng bootstrap, you can't use `app.controller` to dynamic register controller. + */ + this.register = register; + + /** + * @param {Object} params This will pass to the lazy load module + * @param {String} eventName Default to `$routeChangeStart`, //TODO: support `ui-route` + * @param {Function/String} loaderType The loader function: //FIXME: only support `seajs` current. + * - 'seajs' : default value, use [Sea.js](http://seajs.org/) to async load modules + * - 'requirejs': use [RequireJS](http://requirejs.org/‎) to async load modules + * - {Function} : custom loader function: + * - route : current route item + * - callback : callback function when async load success + */ + this.init = function(params, eventName, loaderType){ + //get loaderFn: if loaderType is function, then just use it, else use build in loader by loaderType, default to seajs + var loaderFn = angular.isFunction(loaderType) ? loaderType : this.loaders[loaderType] || this.loaders['seajs']; + + //listen to route change event to hook + $rootScope.$on(eventName || '$routeChangeStart', function(e, target){ + //console.debug(e, '|', target); + var route = target && target.$$route; + if(route){ + route.resolve = route.resolve || {}; + //keypoint: use `route.resolve` + route.resolve.loadedModule = function(){ + var defer = $q.defer(); + loaderFn(route, function(m){ + $rootScope.safeApply(function(){ + defer.resolve(angular.isFunction(m) ? m(params) : m); + }); + }); + return defer.promise; + } + } + }); + } + } + + /** + * build-in loaders + */ + LazyLoadProvider.prototype.loaders = {}; + LazyLoadProvider.prototype.loaders['seajs'] = function(route, callback){ + //if exsit `controllerUrl` then trigger seajs async load. + if(typeof route.controllerUrl == 'string'){ + seajs.use(route.controllerUrl, callback); + } + } + + LazyLoadProvider.prototype.loaders['requirejs'] = function(route, callback){ + //if exsit `controllerUrl` then trigger requirejs async load. + if(typeof route.controllerUrl == 'string'){ + require(route.controllerUrl, callback); + } + } + + /** + * 为$rootScope增加safeApply方法, 安全的apply + */ + function patchScope($rootScope){ + $rootScope.safeApply = function(fn){ + var phase = this.$root.$$phase; + if(phase == '$apply' || phase == '$digest') { + if(fn && (typeof(fn) === 'function')) { + fn(); + } + } else { + this.$apply(fn); + } + }; + } +})(this); \ No newline at end of file diff --git a/src/angular-seajs.js b/src/angular-seajs.js deleted file mode 100644 index 568bfc4..0000000 --- a/src/angular-seajs.js +++ /dev/null @@ -1,120 +0,0 @@ -/** - * 通过[Sea.js](http://seajs.org/)动态按需加载[AngularJS](http://angularjs.org) 模块。 - * - * @author TZ - * @home https://github.com/atian25/angular-seajs - */ -define(function (require, exports, module) { - 'use strict'; - var ngSea = module.exports = angular.module('angular-seajs', []); - - /** - * 由于ng的问题, bootstrap完成后就无法通过app.controller动态注册, - * 故需保存provider的引用, 动态注册均通过 `app.register.controller`的方式。 - * service等同理。 - */ - ngSea.config(['$controllerProvider', '$compileProvider', '$filterProvider', '$provide', - function ($controllerProvider, $compileProvider, $filterProvider, $provide) { - //hold provide's refs - ngSea.register = { - controller: $controllerProvider.register, - directive: $compileProvider.directive, - filter: $filterProvider.register, - factory: $provide.factory, - service: $provide.service, - decorator: $provide.decorator - }; - } - ]).run(['$rootScope', function($rootScope){ - //console.log('init ngSea'); - patchScope($rootScope); - }]); - - /** - * register `$sea` service. - * usage: - * app.run(['$sea', function($sea){ - * $sea.init(app); - * }]); - */ - ngSea.factory('$sea', ['$rootScope', function($rootScope){ - return { - /** - * 初始化 - * @param {Module} app 主模块, 若你的module不需要传入,则可以不赋值,参见两个示例的不同点 - * @param {String} eventName 事件名,默认为$routeChangeStart。支持ui-route, 修改事件名为`$stateChangeStart`即可 - */ - init: initProvider($rootScope), - /** - * 由于ng的问题, bootstrap完成后就无法通过app.controller动态注册, - * 故需保存provider的引用, 动态注册均通过 `app.register.controller`的方式。 - */ - register: ngSea.register, - loadBySeajs: loadBySeajs - } - }]); - - - /** - * 为$route打补丁: 存在参数controllerUrl,则通过seajs动态加载Controller - */ - function initProvider($rootScope){ - return function(app, eventName){ - //hold refs to lazy register - if(app && !app.register){ - app.register = ngSea.register; - }; - - //listen event to patch route item - $rootScope.$on(eventName || '$routeChangeStart', function(e, target){ - //console.debug(e, '|', target); - var route = target && target.$$route; - if(route){ - route.resolve = route.resolve || {}; - - //if exsit `controllerUrl` then trigger seajs async load. - if(typeof route.controllerUrl == 'string'){ - //keypoint: use `route.resolve` - route.resolve.loadBySeajs = loadBySeajs(route.controllerUrl, function(m){ - if(angular.isFunction(m)){ - m(app); - } - }); - } - } - }); - } - } - - /** - * 通过SeaJS加载外部文件,返回promise - */ - function loadBySeajs(url, success, error){ - return ['$q', '$rootScope' , function($q, $rootScope){ - var defer = $q.defer(); - require.async(url, function(m){ - //console.debug('loaded module `'+url+'` from '+ seajs.resolve(url)); - $rootScope.safeApply(function (){ - defer.resolve(m); - }); - }); - return defer.promise.then(success, error); - }]; - } - - /** - * 为$rootScope增加safeApply方法, 安全的apply - */ - function patchScope($rootScope){ - $rootScope.safeApply = function(fn){ - var phase = this.$root.$$phase; - if(phase == '$apply' || phase == '$digest') { - if(fn && (typeof(fn) === 'function')) { - fn(); - } - } else { - this.$apply(fn); - } - }; - } -}); \ No newline at end of file