AngularJS深入(1)——加载启动
本系列文章的分析基于AngularJS v1.4.2.
参考资料有:
- AngularJS API Docs
- AngularJS Developer Guide
- AngularJS实战
- Service vs provider vs factory
1. 整体结构
AngularJS的源码在整体上,与其它很多库和框架一样,是一个自执行函数,其整体结构简化如下:
(function(window, document, undefined) {// define variables and functions// and do some operationsif (window.angular.bootstrap) {console.log('WARNING: Tried to load angular more than once.');return;}bindJQuery();publishExternalAPI(angular);jqLite(document).ready(function() {angularInit(document, bootstrap);}); })(window, document);
整体思路为:
- 首先是一些全局变量和方法的定义,以及一些其它操作;
- 通过
window.angular.bootstrap
判断是否已经加载angular,如果已经加载,则直接退出; - 执行
bindJQuery()
,如果已经加载了jQuery,则AngularJS会使用已经加载的jQuery,否则使用内部实现的JQLite,其相当于是一个简化版的jQuery; - 执行
publishExternalAPI(angular)
来为全局变量angular
增加属性和方法,并建立起模块机制,注册核心模块; - 在文档加载完成后执行
angularInit()
。
2. bindJQuery
该方法主要是绑定jQuery,简化后的代码如下:
var bindJQueryFired = false;function bindJQuery() {if (bindJQueryFired) {return;}var jqName = jq();jQuery = window.jQuery;if (isDefined(jqName)) {jQuery = jqName === null ? undefined : window[jqName];}if (jQuery && jQuery.fn.on) {jqLite = jQuery;// ... ...} else {jqLite = JQLite;}angular.element = jqLite;bindJQueryFired = true; }
bindJQueryFired
相当于是一个标志符,初始值为false
。在执行bindJQuery
的时候,先判断bindJQueryFired
的值,如果其为true
,则说明已经执行过jQuery绑定,直接返回;否则执行绑定过程,并将bindJQueryFired
的值设置为true
;jqName
是调用jq()
的返回值,jq()
的主要作用是遍历文档,找出第一个包含属性ng-jq
的节点,然后取其属性值;- 变量
jQuery
取值为window.jQuery
,如果加载了jQuery函数库,则其值非空; - 在应用了
ng-jq
指令的情况下,如果jQName
的值不为null
,则设置变量jQuery
的值为window[jqName]
,否则设置为undefined
- 如果
jQuery
变量有效,则使用jQuery
变量指定的库;否则使用内置实现的JQLite
。
总结起来,绑定的jQuery可以的来源有三个:ng-jq
指定、引入的jQuery库、内置实现的JQLite,其使用流程为:
- 如果有
ng-jq
- 如果
ng-jq
的值不为空,则使用它指定的库 - 如果
ng-jq
指定的值为空,则变量jQuery
的值为undefined
,此时强制使用JQLite,无论是否引入了jQuery库
- 如果
- 如果没有
ng-jq
- 如果引入了jQuery库,则使用它
- 如果没有引入jQuery库,则使用JQLite
3. publishExternalAPI
该方法的代码简化如下:
function publishExternalAPI(angular) {extend(angular, {// ... ... });angularModule = setupModuleLoader(window);try {angularModule('ngLocale');} catch (e) {angularModule('ngLocale', []).provider('$locale', $LocaleProvider);}angularModule('ng', ['ngLocale'], ['$provide',function ngModule($provide) {// ... ... }]); }
主要功能为:
- 对
angular
对象进行扩展; - 执行
setupModuleLoader(window)
,该方法主要是定义了angular.module
方法,用于注册及获取模块;angular.module
只有一个参数的时候为获取模块,否则为注册模块; - 如果没有注册
ngLocal
模块,则对其进行注册; - 注册
ng
模块,也就是AngularJS的核心模块。
4. angularInit
该方法的主要作用是启动Angular应用。相关代码为:
var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];function getNgAttribute(element, ngAttr) {var attr, i, ii = ngAttrPrefixes.length;for (i = 0; i < ii; ++i) {attr = ngAttrPrefixes[i] + ngAttr;if (isString(attr = element.getAttribute(attr))) {return attr;}}return null; }function angularInit(element, bootstrap) {var appElement,module,config = {};// The element `element` has priority over any other elementforEach(ngAttrPrefixes, function(prefix) {var name = prefix + 'app';if (!appElement && element.hasAttribute && element.hasAttribute(name)) {appElement = element;module = element.getAttribute(name);}});forEach(ngAttrPrefixes, function(prefix) {var name = prefix + 'app';var candidate;if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) {appElement = candidate;module = candidate.getAttribute(name);}});if (appElement) {config.strictDi = getNgAttribute(appElement, "strict-di") !== null;bootstrap(appElement, module ? [module] : [], config);} }
需要说明的是,AngularJS支持的属性前缀有多种,包括ng-
、data-ng
、ng:
和x-ng-
。
- 首先对
element
进行检测,看它是否有ng-app
等属性,如果有则设定appElement
和module
; - 如果
element
元素没有ng-app
等属性,则对其后继元素进行查找,找到第一个有ng-app
等属性的元素,从而设定appElement
和module
; - 如果
appElement
不为空,即找到了应用的入口元素,则执行bootstrap
。
需要注意的是,如果有多个元素都有ng-app
属性,则只会找到第一个并启动它,而后面的应用则不会自动启动。
5. 应用启动
应用的启动方式主要包括自动启动和手动启动。
(1)自动启动
例如:
<div ng-app="MyModule"><div ng-controller="ctrl">{{ name }}</div> </div> <script>var myModule = angular.module('MyModule', []);myModule.controller('ctrl', ['$scope', function($scope) {$scope.name = 'alex';}]); </script>
在这个例子中,对于最外层的div
设置了ng-app
属性,因此会自动启动应用。
(2)手动启动
例如:
<div><div ng-controller="ctrl"></div> </div> <script>var myModule = angular.module('MyModule', []);myModule.controller('ctrl', ['$scope', function($scope) {$scope.name = 'alex';}]);angular.element(document).ready(function() {angular.bootstrap(document, ['MyModule']);}); </script>
由于没有设置ng-app
,因此需要通过angular.bootstrap
来手动启动应用。
(3)多个应用的启动
一般情况下,一个页面中只有一个应用,但是一个页面上多个应用也是可以共存的。通过上面对源码的分析,可以知道,只有第一个应用会自动启动,因此其余的应用需要手动来启动,例如:
<div id="app1" ng-app="MyModule1"><div ng-controller="ctrl1"></div> </div> <div id="app2" ng-app="MyModule2"><div ng-controller="ctrl2"></div> </div> <script>var myModule1 = angular.module('MyModule1', []);myModule1.controller('ctrl1', ['$scope', function($scope) {$scope.name = 'alex';}]);var myModule2 = angular.module('MyModule2', []);myModule2.controller('ctrl2', ['$scope', function($scope) {$scope.greeting = 'hello';}]);angular.element(document).ready(function() {angular.bootstrap(document.getElementById('app2'), ['MyModule2']);}); </script>
转载于:https://www.cnblogs.com/folyred/p/4723773.html
AngularJS深入(1)——加载启动相关推荐
- AngularJS之手动加载模块app和controller
AngularJS之手动加载模块app和controller 转载于:https://www.cnblogs.com/baobaodong/p/5157256.html
- ant design pro(一)安装、目录结构、项目加载启动【原始、以及idea开发】
一.概述 1.1.脚手架概念 编程领域中的"脚手架(Scaffolding)"指的是能够快速搭建项目"骨架"的一类工具.例如大多数的React项目都有src,p ...
- Linux用户程序的编译链接与加载启动过程
Linux用户程序的编译链接与加载启动过程 rtoax 2021年3月 1. 程序的编译链接 1.1. 介绍 如果我们打开维基百科的 链接器 页,我们将会看到如下定义: 在计算机科学中,链接器(英文: ...
- uboot加载linux内核加载那些内容,几个地址参数及uboot加载启动内核过程的理解
关于uBoot和Linux内核中几个地址参数及uboot加载启动内核过程的理解 uboot一般使用mkimage工具先制作一个启动映象文件来引导识别内核的,uboot源代码的tools/目录下有mki ...
- ZYNQ7000 FSBL加载启动代码详解
参考资料: https://blog.csdn.net/zhaoxinfan/article/details/54958641 https://blog.csdn.net/asmartkiller/a ...
- 详细教你如何部署ICE服务(二)---IceBox加载启动Ice服务
在上一篇文章中,我使用了自己实现的一个简单容器简单粗暴的启动一个ICE服务,正如上篇文章所总结的那样,这种部署服务的方式存在诸多缺点. 这里我们给出使用IceBox这个框架来开发和部署我们的Ice服务 ...
- 在 linux 中加载启动 zynq PL 程序
目录 环境 使用 BIN 文件生成 附 在 zynq 使用系统时,可在 uboot 与 linux 中加载启动 PL 程序,一直以来用的都是在 uboot 中加载启动,本次试了试在 linux 中启动 ...
- AngularJS 无限滚动加载数据控件 ngInfiniteScroll
为什么80%的码农都做不了架构师?>>> 1.什么是 InfiniteScroll? 无限滚动(Infinite Scroll)也称为自动分页.滚动分页和无限分页.常用在图片 ...
- angularjs 路由 异步加载js
angularjs 异步加载js 有两种方法 第一种 使用$q 和 requireJS 加载 这个问题 首要出现 在 当我 把require 引入 项目中是,希望做到 点击路由时加载相应的页面htm ...
最新文章
- 第十七篇:信息抽取Information Extraction
- Linux学习(3)-常用命令
- oracle11g数据文件路径,oracle11g修改数据文件路径
- ​最新综述!基于图神经网络的关系抽取技术进展
- ta-lib 里的蜡烛图形态函数源码
- Windows下安装jenkins,关闭jenkins,修改jenkins端口号
- 组队开发第二周第五次会议
- JavaWeb开发Session管理
- IntelliJ IDEA后台程序启动
- Excel单元格区域快速导出为PDF
- VBA每日一练(2),将txt 的部分/全部内容 导入到EXCEL
- 【读书笔记】《我的奋斗》罗永浩
- Broken Pipe
- win7怎么把计算机图标下的箭头掉,告诉你win7如何去除快捷方式小箭头
- jsp汽车销售管理系统
- 滚动 下拉简单实现分页
- linux pclint配置_PC-lint
- “链上政务”三管齐下,效率、监管、企业服务成关键词
- AlignedReID 源码解析
- 00后确实卷,公司新来的卷王,我们这帮老油条真干不过...