5

angular执行图:
图片描述
jquery启动:
js dom元素绑定相应的事件,当dom监听到相应的事件,这时就开始执行注册的这个事件.
angularjs执行:
首先,绑定jquery,判断是否引入jquery,如果没有引入jquery,自己会实现一个jqlit。
其次,publishExternalApi
2,publishExternalApi 在启动angular之前首要准备好service,directives...,首先在angular上注册forEach,bind方法
比如:
2.1需要备案,能够是angular能方便找到你,yourName就是检索
[]就是依赖

var APP = angular.module('yourName',[],configFn)
angular.module()创建、获取、注册angular中的模块
   传递参数不止一个,代表新建模块;空数组代表该模块不依赖其他模块  
  var createModule = angular.module("myModule", []);  
    只有一个参数(模块名),代表获取模块,如果模块不存在,angular框架会抛异常  
   var getModule = angular.module("myModule");  
   getModule ==createModule
configFn就是你出生的时候可以做些初始化之类的动作,比如娃娃大叫...

2.2,出生之后可以有很多的技能,比如会angular编程,会java...,然后这些技能都需要取个名字...

var APP = angular.module('yourName',[],configFn)
app.controller(xx)
factory()...
service()...
...
angular.module(name, [requires], [configFn]);
name:字符串类型,代表模块的名称;
requires:字符串的数组,代表该模块依赖的其他模块列表,如果不依赖其他模块,用空数组即可;
configFn:用来对该模块进行一些配置。

2.3,有了技能之后要让人知道,所以要暴露你的技能让别人来用.

如在services.js里面setupModuleLoader在angular上注册module,controller等api最后返回的是:
return(moduleInstance=(_invokeQueue:[],_runBlocks:[],controller factory service...))

2.4,有了技能,别人也已经知道了,然后也准备好了让别人调用了,首先别人需要遍历你的技能,把所有的技能都列在一个list invokeQueue上

 moduleInstance={_invokeQueue _runBlock}

2.5,技能都掌握在一个人的手里,他的名字叫ng,下面就是ng的备案:
angularModule('ng',['ngLocal'],['$provide',function ngModule($provide){//ngLocal是ng自己不会的技能,所以要依赖于别人
$provide.provider('$compile',$compileProvider).directive({//compile服务是ng自己的技能

 A:htmlDirective,
 input:inputDirective,
 ...

}).directive(ngAttributeAliasDirectives).directive(ngEventDirectives);

 $provide.provider({
   $anchorScroll:$AnchorScrollProvider,
   $animate:$AnimateProvider,
   $browser:$BrowserProvider
 })

}])
3,angularInit
所有的东西都准备好了,现在开始启动:2种方法启动
1),ng-app
2),跳过第一步直接 doBootstrap(element,[module])
3.1在解析html的时候,很多directives的技能都是有ng这个人掌握,所以首先要召唤出ng,另外还需要注册$rootElement,这个由无名氏掌握(放在匿名的空间里)

modules=[
'ng',['$provide',function($provide){$provide.value('$rootElement',element);

}],'myApp'
]
3.2 所有的技能都调集起来了现在开始决斗了,首先调用createInjecter,这里我们定义2个技能的集合:

createInjecter(modules)
//providerCache存放所有人的技能,不管名字,只管技能
 providerCache:{$provider,$injector}
//如果调用过了就放在这里,方便下次寻找,如果需要新的技能就去大库里寻找
instanceCache:{$injector}

3.3 遍历每个人的invokeQueue

 .loadModules
 if:string 遍历,检索出module,遍历invokeQueue,将其技能放在定义好的库里面
 var invokeArgs = invokeQueue[i],
 provider = providerInjecter.get(invokeArgs[0])
 provider[invokeArgs[1]].apply(provider,invokeArgs[2]);
 if:function或Array, 直接providerInjector.invoke
 return runBlocks

3.4 遍历所有人的技能 遍历runBlocks
forEach(runBlocks){

  instanceInjector.invoke

}
3.5 编译所有的dom compile dom
injector.invoke(['$rootScope'...])

demo 执行顺序 4,2,3,1
   var app = angular.module('demo',[])
   app.controller('test',[function(){//放在providerCach里,等compile服务执行之后才执行
     console.log('step1')
   }])
  
   app.config('test',[function($provide){//其次是config
     console.log('step2')
   }])
  
   app.run(function(){
     console.log('step3')
   })
  
   angular.element(document).ready(function(){//首先是dom ready
    console.log('step4')
    angular.bootstrap(angular.element(document),['demo'])
   })
   

4,angularjs源码解析
angular源码是一个自执行函数,当js被加载完之后,立即执行。除了最后一行.

在angular的源码中,这段代码不是自执行函数。
!window.angular.$$csp() && window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>');

代码开始执行:

if (window.angular.bootstrap) {//判断angularjs是不是已经启动,如果已经启动了就报错WARNING: Tried to load angular more than once.
    //AngularJS is already loaded, so we can return here...
    console.log('WARNING: Tried to load angular more than once.');
    return;
  }

  //try to bind to jquery now so that one can write jqLite(document).ready()
  //but we will rebind on bootstrap again.
  bindJQuery();//对jquery库进行绑定

  publishExternalAPI(angular);//将angular的api扩展到angular全局函数

  jqLite(document).ready(function() {
    angularInit(document, bootstrap);//启动angular,默认从document开始启动
  });

我们在写angularjs的时候,总是要定义全局的angular函数,比如:
var app = angular.module('app',[])
那么这个angular的全局函数从哪里来的呢?

/** @name angular */
    angular           = window.angular || (window.angular = {}),
    //如果window.angular有值就返回--> angular = window.angular
    //如果没有值 window.angular = {} --> angular = {} 是一个空对象。

angular 是如何调用module函数呢?
angular.module
function publishExternalAPI

 extend(angular, {//extend是一个工具函数,复制的作用
    'bootstrap': bootstrap,
    'copy': copy,
    'extend': extend,
    'merge': merge,
    '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,
    'version': version,
    'isDate': isDate,
    'lowercase': lowercase,
    'uppercase': uppercase,
    'callbacks': {counter: 0},
    'getTestability': getTestability,
    '$$minErr': minErr,
    '$$csp': csp,
    'reloadWithDebugInfo': reloadWithDebugInfo
  });

MichaelDuan
1.8k 声望39 粉丝

引用和评论

0 条评论