Angularjs的啟動(dòng)過(guò)程分析
本文介紹了Angularjs的啟動(dòng)過(guò)程分析,分享給大家
啟動(dòng)過(guò)程(v1.3.9)
步驟一
用自執(zhí)行函數(shù)的形式讓整個(gè)代碼在加載完成之后立即執(zhí)行
in angular.js Line6
(function(window, document, undefined)
在window上暴露一個(gè)唯一的全局對(duì)象angular,Line250
angular = window.angular || (window.angular = {})
獲得其它工具模塊 Line 2129
function publishExternalAPI(angular) {
extend(angular, {
'bootstrap': bootstrap,
'copy': copy,
'extend': extend,
'equals': equals,
'element': jqLite,
'forEach': forEach,
'injector': createInjector,
'noop': noop,
'bind': bind,
.....
我們來(lái)看看angular全局對(duì)象都有什么東西

接著,我們使用全局對(duì)象中的isFunction 來(lái)遍歷一下angular全局對(duì)象上的屬性,函數(shù)
var counter = 0;
for (var p in angular) {
counter++;
if (angular.isFunction(angular[p])) {
console.log("function->" + p);
} else {
console.log("property-->" + p + "-->" + angular[p]);
}
}
console.log(counter);
有兩個(gè)property,其它都是function

我們?cè)賮?lái)看看injector里都有什么
/** * angular.injector(); */ var injector = angular.injector(); console.log(injector);
一共有5個(gè)方法
annotate:分析函數(shù)簽名(不要new的原因)

步驟二
檢查是不是多次導(dǎo)入Angular:window.angular.bootstrap(通過(guò)檢查指定的元素上是否已經(jīng)存在injector進(jìn)行判斷)
in angular.js line 26041
if (window.angular.bootstrap) {
//AngularJS is already loaded, so we can return here...
console.log('WARNING: Tried to load angular more than once.');
return;
}
angular的三種啟動(dòng)方式
自動(dòng)啟動(dòng)
Angular會(huì)自動(dòng)的找到ng-app,將它作為啟動(dòng)點(diǎn),自動(dòng)啟動(dòng)
<!DOCTYPE html>
<html ng-app="myModule">
<head>
<title>New Page</title>
<meta charset="utf-8" />
<script type="text/javascript" src="../../vendor/bower_components/angular/angular.min.js"></script>
<script type="text/javascript" src="./02.boot1.js"></script>
</head>
<body>
<div ng-controller="MyCtrl">
<span>{{Name}}</span>
</div>
</body>
</html>
js
var myModule = angular.module("myModule", []);
myModule.controller('MyCtrl', ['$scope',
function($scope) {
$scope.Name = "Puppet";
}
]);
手動(dòng)啟動(dòng)
在沒(méi)有ng-app的情況下,只需要在js中添加一段注冊(cè)代碼即可
<body>
<div ng-controller="MyCtrl">
<span>{{Name}}</span>
</div>
</body>
js
var myModule = angular.module("myModule", []);
myModule.controller('MyCtrl', ['$scope',
function($scope) {
$scope.Name = "Puppet";
}
]);
/**
* 這里要用ready函數(shù)等待文檔初始化完成
*/
angular.element(document).ready(function() {
angular.bootstrap(document, ['myModule']);
});
多個(gè)ng-app
ng中,angular的ng-app是無(wú)法嵌套使用的,在不嵌套的情況下有多個(gè)ng-app,他默認(rèn)只會(huì)啟動(dòng)第一個(gè)ng-app,第二個(gè)第三個(gè)需要手動(dòng)啟動(dòng)(注意,不要手動(dòng)啟動(dòng)第一個(gè),雖然可以運(yùn)行,但會(huì)拋異常)
<body>
<div id="app1" ng-app="myModule1">
<div ng-controller="MyCtrl">
<span>{{Name}}</span>
</div>
</div>
<div id="app2" ng-app="myModule2">
<div ng-controller="MyCtrl">
<span>{{Name}}</span>
</div>
</div>
</body>
js
/**
* 第一個(gè)APP
* @type {[type]}
*/
var myModule1 = angular.module("myModule1", []);
myModule1.controller('MyCtrl', ['$scope',
function($scope) {
$scope.Name = "Puppet";
}
]);
// angular.element(document).ready(function() {
// angular.bootstrap(app1, ['MyModule1']);
// });
/**
* 第二個(gè)APP
* @type {[type]}
*/
var myModule2 = angular.module("myModule2", []);
myModule2.controller('MyCtrl', ['$scope',
function($scope) {
$scope.Name = "Vincent";
}
]);
angular.element(document).ready(function() {
angular.bootstrap(app2, ['myModule2']);
});
步驟三
嘗試綁定jQuery,如果發(fā)現(xiàn)導(dǎo)入了jQuery ,則使用導(dǎo)入的jQuery,否則,使用Angular自己封裝的JQLite
in angular.js line 1521:
bindJQuery();
in angular.js line 1534:
jQuery = window.jQuery;
if (jQuery && jQuery.fn.on) {
jqLite = jQuery;
extend(jQuery.fn, {
scope: JQLitePrototype.scope,
isolateScope: JQLitePrototype.isolateScope,
controller: JQLitePrototype.controller,
injector: JQLitePrototype.injector,
inheritedData: JQLitePrototype.inheritedData
});
測(cè)試
<html ng-app="myModule">
<body>
<div>
<div ng-controller="MyCtrl">
<span>{{Name}}</span>
</div>
</div>
</body>
</html>
js
var myModule = angular.module("myModule", []);
myModule.controller('MyCtrl', ['$scope',
function($scope) {
$scope.Name = "Puppet";
}
]);
查看執(zhí)行流程

步驟四
發(fā)布ng提供的API
in angular.js line 2162 : publishExternalAPI(angular);
//構(gòu)建模塊加載器
angularModule = setupModuleLoader(window);
try {
angularModule('ngLocale');
} catch (e) {
angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
}
模塊加載器的實(shí)現(xiàn)原理
in angular.js function setupModuleLoader(window)
function setupModuleLoader(window) {
var $injectorMinErr = minErr('$injector');
var ngMinErr = minErr('ng');
function ensure(obj, name, factory){
return obj[name] || (obj[name] = factory());
}
var angular = ensure(window, 'angular', Object);
// We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
angular.$$minErr= angular.$ $minErr || minErr;
//把module方法放到angular的全局對(duì)象上,ensure就是一個(gè)屬性拷貝的過(guò)程
return ensure(angular, 'module', function(){
//模塊緩存
var modules = {};
}
把工具函數(shù)給載到模塊里
return function module(name, requires, configFn) {
......
}
查看模塊里所包含的內(nèi)容
<!DOCTYPE html> <html ng-app="myModule"> </html>
JS
/**
* 定義模塊
*/
var myModule = angular.module("myModule", []);
/**
* 從debug的過(guò)程可以看到,angular中的“模塊”只是一個(gè)閉包空間(或者叫命名空間)
* 所有模塊都被注冊(cè)在modules這個(gè)對(duì)象上
*/
console.log(myModule);
查看控制臺(tái)

構(gòu)建內(nèi)置模塊ng
in angular.js line 2169 publishExternalAPI(angular)
angularModule('ng', ['ngLocale'], ['$provide',
function ngModule($provide) {
// $ $sanitizeUriProvider needs to be before $compileProvider as it is used by it.
$provide.provider({
$ $sanitizeUri: $$SanitizeUriProvider
});
$provide.provider('$compile', $CompileProvider).
directive({
a: htmlAnchorDirective,
input: inputDirective,
......
加載了所有內(nèi)置的directive,provider.注冊(cè)ng內(nèi)核Provider:兩個(gè)最重要的$parser 和 $rootScope
總結(jié)
- 工具函數(shù)拷貝到angular全局對(duì)象上;
- 調(diào)用setupModuleLoader方法創(chuàng)建模塊定義和加載工具(掛在全局對(duì)象window.angular上);
- 構(gòu)建內(nèi)置模塊ng;
- 創(chuàng)建ng內(nèi)置的directive和provider;
- 兩個(gè)重要的provider:$parse 和 $rootScope;
步驟五
初始化Angular - 查找Ng-app
jqLite(document).ready(function() {
angularInit(document, bootstrap);
});
bootstrap
創(chuàng)建injector,拉起內(nèi)核和啟動(dòng)模塊,調(diào)用compile服務(wù)(一個(gè)ng-app只有一個(gè)injector)
in angular.js line 1415
function bootstrap(element, modules, config){
....
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Angular 1.x個(gè)人使用的經(jīng)驗(yàn)小結(jié)
這篇文章主要給大家介紹了關(guān)于Angular 1.x個(gè)人使用的一些經(jīng)驗(yàn),屬于一些基礎(chǔ)入門(mén)教程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-07-07
Angular實(shí)現(xiàn)防抖和節(jié)流的示例代碼
這篇博客主要是詳細(xì)介紹兩種常用Angular實(shí)現(xiàn)防抖和節(jié)流的方法:使用RxJS操作符和使用Angular自帶的工具,文中通過(guò)代碼示例給大家講解的非常詳細(xì),需要的朋友可以參考下2024-02-02
對(duì)angular2中的ngfor和ngif指令嵌套實(shí)例講解
今天小編就為大家分享一篇對(duì)angular2中的ngfor和ngif指令嵌套實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09
AngularJS基礎(chǔ) ng-include 指令示例講解
本文主要介紹AngularJS ng-include 指令,這里對(duì)ng-include 指令的知識(shí)做了詳細(xì)整理介紹,有需要的朋友可以參考下2016-08-08
AngularJS學(xué)習(xí)筆記之依賴(lài)注入詳解
下面小編就為大家?guī)?lái)一篇AngularJS學(xué)習(xí)筆記之依賴(lài)注入詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-05-05
angularJs中跳轉(zhuǎn)到指定的錨點(diǎn)實(shí)例($anchorScroll)
今天小編就為大家分享一篇angularJs中跳轉(zhuǎn)到指定的錨點(diǎn)實(shí)例($anchorScroll),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
詳解angularjs popup-table 彈出框表格指令
本篇文章主要介紹了angularjs popup-table 彈出框表格指令,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09
JavaScript框架Angular和React深度對(duì)比
這篇文章主要介紹了JS框架中Angular和React不同和差異,以及兩個(gè)框架的深度對(duì)比介紹。2017-11-11
Angular企業(yè)級(jí)開(kāi)發(fā)——MVC之控制器詳解
本篇文章主要介紹了Angular企業(yè)級(jí)開(kāi)發(fā)——MVC之控制器詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02
Angular+Ionic使用queryParams實(shí)現(xiàn)跳轉(zhuǎn)頁(yè)傳值的方法
這篇文章主要介紹了Angular+Ionic使用queryParams實(shí)現(xiàn)跳轉(zhuǎn)頁(yè)傳值的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09

