angular源码学习笔记----(加载)
angular资源:
angular文档:http://docs.angularjs.org/api
angular官网:http://angularjs.org/
angular源码:https://github.com/angular/angular.js
angular下载:http://code.angularjs.org/
学习版本:
1.2.0-rc.2
流程简述:
angular初始化大致上有2部分:
1.初始化angular框架,模块等
2.解析document
1.读取angular.js脚本,执行angular框架上下文脚本
(function(window, document, undefined) { ... })(window, document);
2.初始化angular框架,配置模块,挂载angular对象
publishExternalAPI(angular);
3.使用angular框架,初始化(扫描)document中,相应的节点
angularInit(document, bootstrap);
angular源码,加载启动部分:
(function(window, document, undefined) { //设置严格模式 'use strict'; /********* 省略代码 *********/ //尝试绑定使用jquery对象 bindJQuery(); //公布angular扩展api函数(初始化angular环境) publishExternalAPI(angular); //document加载完成后,加载angular jqLite(document).ready(function() { //加载angular入口 angularInit(document, bootstrap); }); })(window, document);
angular源码,初始化angular框架部分
function publishExternalAPI(angular){ /******************************** 设置angular公共属性,成员 ********************************/ extend(angular, { 'bootstrap': bootstrap, 'copy': copy, 'extend': extend, 'equals': equals, 'element': jqLite, 'forEach': forEach, 'injector': createInjector, 'noop':noop, 'bind':bind, 'toJson': toJson, 'fromJson': fromJson, 'identity':identity, 'isUndefined': isUndefined, 'isDefined': isDefined, 'isString': isString, 'isFunction': isFunction, 'isObject': isObject, 'isNumber': isNumber, 'isElement': isElement, 'isArray': isArray, '$$minErr': minErr, 'version': version, 'isDate': isDate, 'lowercase': lowercase, 'uppercase': uppercase, 'callbacks': {counter: 0} }); /******************************** 创建angular默认模块 ********************************/ angularModule = setupModuleLoader(window); /******************************** 尝试挂载ngLocale模块 ********************************/ try { angularModule('ngLocale'); } catch (e) { angularModule('ngLocale', []).provider('$locale', $LocaleProvider); } /******************************** 配置ng模块 ********************************/ angularModule('ng', ['ngLocale'], ['$provide', function ngModule($provide) { $provide.provider('$compile', $CompileProvider). directive({ a: htmlAnchorDirective, input: inputDirective, textarea: inputDirective, form: formDirective, script: scriptDirective, select: selectDirective, style: styleDirective, option: optionDirective, ngBind: ngBindDirective, ngBindHtml: ngBindHtmlDirective, ngBindTemplate: ngBindTemplateDirective, ngClass: ngClassDirective, ngClassEven: ngClassEvenDirective, ngClassOdd: ngClassOddDirective, ngCsp: ngCspDirective, ngCloak: ngCloakDirective, ngController: ngControllerDirective, ngForm: ngFormDirective, ngHide: ngHideDirective, ngIf: ngIfDirective, ngInclude: ngIncludeDirective, ngInit: ngInitDirective, ngNonBindable: ngNonBindableDirective, ngPluralize: ngPluralizeDirective, ngRepeat: ngRepeatDirective, ngShow: ngShowDirective, ngStyle: ngStyleDirective, ngSwitch: ngSwitchDirective, ngSwitchWhen: ngSwitchWhenDirective, ngSwitchDefault: ngSwitchDefaultDirective, ngOptions: ngOptionsDirective, ngTransclude: ngTranscludeDirective, ngModel: ngModelDirective, ngList: ngListDirective, ngChange: ngChangeDirective, required: requiredDirective, ngRequired: requiredDirective, ngValue: ngValueDirective }). directive(ngAttributeAliasDirectives). directive(ngEventDirectives); $provide.provider({ $anchorScroll: $AnchorScrollProvider, $animate: $AnimateProvider, $browser: $BrowserProvider, $cacheFactory: $CacheFactoryProvider, $controller: $ControllerProvider, $document: $DocumentProvider, $exceptionHandler: $ExceptionHandlerProvider, $filter: $FilterProvider, $interpolate: $InterpolateProvider, $http: $HttpProvider, $httpBackend: $HttpBackendProvider, $location: $LocationProvider, $log: $LogProvider, $parse: $ParseProvider, $rootScope: $RootScopeProvider, $q: $QProvider, $sce: $SceProvider, $sceDelegate: $SceDelegateProvider, $sniffer: $SnifferProvider, $templateCache: $TemplateCacheProvider, $timeout: $TimeoutProvider, $window: $WindowProvider, $$urlUtils: $$UrlUtilsProvider }); } ]); }
angular源码,装载angular及module部分
function setupModuleLoader(window) { function ensure(obj, name, factory) { return obj[name] || (obj[name] = factory()); } /********************************** 声明window的angular属性 声明angular的module属性 注:angular.module设置为return的module函数 *********************************/ return ensure(ensure(window, 'angular', Object), 'module', function() { var modules = {}; /********************************** module函数 *********************************/ return function module(name, requires, configFn) { /*******. 省略代码 *******/ }); }); }
angular源码,入口(angularInit)部分:
function angularInit(element, bootstrap) { //检索加载angular的dom元素列表 var elements = [element], //加载angular的dom元素 appElement, //加载的模块 module, //检索angular加载的关键字 names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'], //提取angular加载模块的正则表达式 NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/; //追加加载angular的dom元素 function append(element) { element && elements.push(element); } /********************************************************************** 遍历angular加载的关键字 检索分为两种方式: 1.使用document.getElementById,检索id中关键字 2.使用element.querySelectorAll,参考:http://www.w3.org/TR/selectors-api/] **********************************************************************/ forEach(names, function(name) { names[name] = true; append(document.getElementById(name)); name = name.replace(':', '\\:'); if (element.querySelectorAll) { forEach(element.querySelectorAll('.' + name), append); forEach(element.querySelectorAll('.' + name + '\\:'), append); forEach(element.querySelectorAll('[' + name + ']'), append); } }); /********************************************************************** 解析加载angular的dom元素及module 解析分为两种方式: 1.获取element.className,提取元素class属性内容,作为module名 2.获取names中存在于dom元素上的属性,提取属性内容,作为module **********************************************************************/ forEach(elements, function(element) { if (!appElement) { var className = ' ' + element.className + ' '; var match = NG_APP_CLASS_REGEXP.exec(className); if (match) { appElement = element; module = (match[2] || '').replace(/\s+/g, ','); } else { forEach(element.attributes, function(attr) { if (!appElement && names[attr.name]) { appElement = element; module = attr.value; } }); } } }); //如果存在需要加载angular的dom元素,调用bootstrap引导加载appElement,module if (appElement) { bootstrap(appElement, module ? [module] : []); } }
学习膜拜:
1.把javascript写出了oop的范,设计模式,设计原则很好的体现了出来。
2.angular的结构,已经不是为了实现的页面功能,而是成为了一个应用框架。
学习吐槽:
setupModuleLoader的时候,死绑定的属性为'angular',我要copy装b改名字,让我咋弄?
angularInit的时候,为毛最初是elements,最后却用一个element去引导,module也只能是最后一个element上的,并且module只能为单模块名。