原文:http://www.angularjs.cn/A137?utm_source=ourjs.com

目录:

  1. 引导之前
  2. 自动引导启动框架
  3. 手工引导启动框架
  4. 引导第1步:创建注入器
  5. 引导第2步:创建根作用域
  6. 引导第3步:编译DOM子树
  7. 编译器/$compile
  8. 指令/directive
  9. 指令的规范化

1.引导之前:库阶段

在示例中,我们定义了一个指令ez-duang, 它应该会展开成一个动画 显示出来。 AngularJS代码:

   angular.module("ezstuff",[])
.directive("ezDuang",function(){
return {
restrict : "E",
template : "<img src='http://ww4.sinaimg.cn/bmiddle/757eb2ffjw1eptcr4qobjg209205dthh.gif'>"
};
});

html代码:

  • 应该在下面看到一幅动画才对!

但是,看起来没有什么动画显示出来。AngularJS似乎没有工作,为什么?

有点像操作系统,AngularJs也有一个启动引导的概念。

当你在HTML文件中引入angular.min.js时,AngularJS只是建立了一个全局的 angular对象,这个对象有一些方法可供开发者调用,但应用的框架还没有建立。

在这个阶段,AngularJS还只是一个库,和jQuery类似,你可以使用angular.element() 操作DOM,也可以使用angular.injector()创建注入器... 但是,你定义的指令,你 创建的控制器,你封装的服务,你开发的模板...所有这些组件,还静静地躺在那里, 没有被整合在一起。

我们说,框架还没有运转起来,现在还是库阶段。

只有通过启动引导,AngularJS框架才开始将那些组件拼接在一起,应用才真正 开始运转。

像下面这样,试着给html元素增加一个ng-app指令,再重新运行!

 <html ng-app="ezstuff">
....
</html>

2.自动引导启动框架

就像你看到的那样,如果HTML模板中有某个标签有ng-app属性,那么当DOM树建立成功后, AngularJS就会自动进入引导过程,启动整个框架:

试着把ng-app指令挪到body元素上,看看有什么不同?

3.手工引导启动框架

在大多数情况下,我们都使用ng-app指令来进行自动引导启动,但是如果一个HTML文件中 有多个ng-app,AngularJS只会自动引导启动它找到的第一个ng-app应用,这是需要手工引导 的一个应用场景。

我们可以利用 angular.bootstrap() 方法进行手动引导:

angular.bootstrap(element, [modules], [config]);

bootstrap方法有三个参数:

element : 一个DOM元素,以这个元素为Angular应用的根,等同自动引导时ng-app所在 的元素。这个参数是必须的。比如:document、document.body等。 modules : 引导时需要载入的模块数组。比如:[]、["ezstuff"]等。由于我们的HTML中引用 了ezstuff模块中定义的ez-duang指令,所以,我们需要指定载入ezstuff模块。 config :引导配置项,可选。我们先忽略。 最终,我们使用如下的形式进行手动引导:

angular.bootstrap(document,["ezstuff"]); 请点击【手动引导】按钮启动引导过程!

4.引导第1步:创建注入器

引导过程使AngularJS从库转变成了一个框架。

回忆我们之前提到,AngularJS深入骨髓地使用着依赖注入,那么,在引导过程 之初,首先需要创建一个注入器就毫不奇怪了。

注入器是通向AngularJS所有功能的入口,而AngularJS的功能实现,是通过模块的方式组织的。所以, 在创建注入器的时候,需要告诉AngularJS载入哪些模块(ng模块是内置载入的,不需要显式指定)。

在自动启动引导的场景下,可以给ng-app赋值以指定一个需要载入的模块,比如: ng-app = "ezstuff"

在手动启动引导的场景下,通过bootstrap方法的第二个参数指定需要载入的模块,比如: angular.bootstrap(document,["ezstuff"]);

INSIDE:无论自动启动还是手工启动,最终都是调用angular对象上的injector()方法创建了一个 注入器,然后把这个注入器存入了根对象的data里: var injector = angular.injector(["ng","ezstuff"]); angular.element(document).data("$injector",injector);

我们在开始模拟引导启动过程的第一步:创建注入器。

5.引导第2步:创建根作用域

scope对象是AngularJS实现数据绑定的重要服务,所以,在引导启动建立了注入器之后, AngularJS马上在应用的根节点上创建一个根作用域:$rootScope对象。

如果是自动引导启动,那么ng-app所在的DOM节点对应着根作用域。如果是手工引导启动, 那么在bootstrap方法中指定的第一个参数就对应着根作用域。

无论哪一种情况,一旦$rootScope对象创建成功,AngularJS就将这个对象存储到根节点 的data中,我们可以使用如下的方法查看这个对象: angular.element(approot).data("$rootScope");

你可以摆弄一下代码,看看$rootScope到底是什么东西。

6.引导第3步:编译DOM子树

引导过程的最后一步,是以ng-app所在DOM节点为根节点,对这棵DOM子树进行编译。

编译过程通常借助于指令,完成这几种操作:

  1. 对DOM对象进行变换。
  2. 在DOM对象上挂接事件监听。
  3. 在DOM对象对应的scope对象上挂接数据监听。 编译过程是AngularJS相当有特点的一个存在,我们将在下一节继续深入。

现在你应该看到结果了吧?

7.编译器/$compile

编译器$compile是一个AngularJS的内置服务,它负责遍历DOM树来查找匹配指令, 并调用指令的实现代码进行处理。

HTML编译包括3个步骤:

匹配指令 $compile遍历DOM树,如果发现有元素匹配了某个指令,那么这个指令将被加入 该DOM元素的指令列表中。一个DOM元素可能匹配多个指令。

执行指令的编译函数 当一个DOM元素的所有指令都找齐后,编译器根据指令的优先级/priority指令进行排序。 每个指令的compile函数被依次执行。每个compile执行的结果产生一个link函数,这些 link函数合并成一个复合link函数。

执行生成的链接函数 $compile通过执行指令的link函数,将模板和scope链接起来。结果就是一个DOM视图和scope对象模型 之间的动态数据绑定。

为何将编译和连接两个步骤分开?

简单说,当数据模型的变化会导致DOM结构变化时,指令就需要分别定义compile()函数和link函数。 例如,ng-repeat指令需要为数据集合中的每个成员复制DOM元素。将编译和链接过程分开可以有效 地提高性能,因为DOM的复制放在compile()里,仅需要执行一次,但链接则发生在每个生成的DOM元素 上,所以指令的link()函数会执行多次。

指令很少需要compile函数,因为大多数指令考虑的是作用于特定的DOM元素实例,而不是改变DOM 的结构。所以link函数更常用。

8.指令/directive

笼统地说,指令是DOM元素(例如属性、元素、CSS类等)上的标记符,用来告诉AngularJS的HTML编译器 ($compile服务)将特定的行为绑定到DOM元素,或者改变DOM元素。

指令可以放置在元素名、属性、CSS类名称及备注中。下面是一些等效的触发"ng-bind"指令的写法:

 <span ng-bind="exp"></span>
<span class="ng-bind: exp;"></span>
<ng-bind></ng-bind>
<!-- directive: ng-bind exp -->

指令的实现本质上就是一个类工厂,它返回一个指令定义对象,编译器根据这个指令定义对象进行操作。

问题是,HTML中的ez-duang,怎么就匹配到了JavaScript中的ezDuang?

9.指令的规范化

AngularJS在进行匹配检测之前,首先对HTML元素的标签和属性名转化成规范的驼峰式字符串:

  1. 去除名称前缀的x-和data-
  2. 以: , - 或 _ 为分割符,将字符串切分成单词,除第一个单词外,其余单词首字母大写
  3. 重新拼接各单词 例如,下面的写法都等效地匹配ngBind指令:

     <span ng-bind="name"></span> <br>
    <span ng:bind="name"></span> <br>
    <span ng_bind="name"></span> <br>
    <span data-ng-bind="name"></span> <br>
    <span x-ng-bind="name"></span> <br>

所以,在前面的课程中,我们在HTML中使用的ez-duang指令,将被规范为ezDuang, 编译器使用这个规范化的名称与注册的指令进行匹配。

AngularJS的启动引导过程的更多相关文章

  1. 浅谈AngularJS启动引导过程

    我们都知道AngularJS默认会执行app.js来启动整个angular项目,但你知道angular具体执行过程吗? 一.自动引导启动框架 例如我们有如下代码,我们想要完成一个指令功能: <h ...

  2. Linux学习笔记之Linux启动引导过程

    早期时,启动一台计算机意味着要给计算机喂一条包含引导程序的纸带,或者手工使用前端面板地址/数据/控制开关来加载引导程序.尽管目前的计算机已经装备了很多工具来简化引导过程,但是这一切并没有对整个过程进行 ...

  3. Linux系统引导过程及排除启动故障

    一.Linux操作系统引导过程二.系统初始化进程1.init进程2.Systemd3.Systemd单元类型三.排除启动类故障[1].修复MBR扇区故障(含实验过程)[2].修复GRUB引导故障●方法 ...

  4. Linux 引导过程内幕

    转载:http://www.ibm.com/developerworks/cn/linux/l-linuxboot/index.html   从主引导记录到第一个用户空间应用程序的指导 引导 Linu ...

  5. The Kernel Boot Process.内核引导过程

    原文标题:The Kernel Boot Process 原文地址:http://duartes.org/gustavo/blog/ [注:本人水平有限,只好挑一些国外高手的精彩文章翻译一下.一来自己 ...

  6. How Computers Boot Up.计算机的引导过程

    原文标题:How Computers Boot Up 原文地址:http://duartes.org/gustavo/blog/ [注:本人水平有限,只好挑一些国外高手的精彩文章翻译一下.一来自己复习 ...

  7. 【转】Linux 高级的视角来查看Linux引导过程

    [原文]https://www.toutiao.com/i6594210975480545800/ 1.概述 图 1 是我们在20,000 英尺的高度看到的视图. 当系统首次引导时,或系统被重置时,处 ...

  8. 了解Linux操作系统的引导过程

    原文地址:http://os.51cto.com/art/200706/49690.htm 1.简介 Linux启动过程指的是从加电到看到shell提示的这一段时间. Linux启动的过程可以大概分为 ...

  9. linux 启动引导流程

    课程大纲: Linux引导流程 Linux运行级别 Linux启动服务管理 GRUB配置与应用 启动故障分析与解决 系统引导流程 1.固件firmware(CMOS(固化在硬件上的程序与硬件统称)/B ...

随机推荐

  1. Unity3D游戏开发从零单排(五) - 导入CS模型到Unity3D

    游戏动画基础 Animation组件 Animation组件是对于老的动画系统来说的. 老的动画形同相应的动画就是clip,每一个运动都是一段单独的动画,使用Play()或CrossFade(),直接 ...

  2. npapi加载失败的几个原因

    本文只讨论加载失败的原因,不复述npapi的使用教程 1. 资源文件是否加上 MIMEType命名的id,和html中的<object>的标签是否对应 如果不相同加载必然失败: 2. 注册 ...

  3. 在实体对象中访问导航属性里的属性值出现异常“There is already an open DataReader associated with this Command which must be closed first”

    在实体对象中访问导航属性里的属性值出现异常“There is already an open DataReader associated with this Command which must be ...

  4. 转:一个strcpy的问题(很容易做错)

    下面的执行结果是什么? #include<stdio.h> #include<string.h> void main() { "; "; strcpy(d, ...

  5. oracle在一个字符串中查找某个字符出现过几次

    SELECT LENGTH(REGEXP_REPLACE(REPLACE('123,45,6,5', ',', '@'),  '[^@]+',  '')) COUNT FROM DUAL; 返回结果为 ...

  6. [置顶] jsp中c标签的使用

    jsp中c标签的使用 核心标签库 它是JSTL中的核心库,为日常任务提供通用支持,如显示和设置变量.重复使用一组项目.测试条件和其他操作(如导入和重定向Web内容).Core标签按功能可分为4种类型: ...

  7. hive原生和复合类型的数据载入和使用

    原生类型 原生类型包含TINYINT,SMALLINT,INT,BIGINT,BOOLEAN,FLOAT,DOUBLE,STRING,BINARY (Hive 0.8.0以上才可用),TIMESTAM ...

  8. 【deep learning学习笔记】Recommending music on Spotify with deep learning

    主要内容: Spotify是个类似酷我音乐的音乐站点.做个性化音乐推荐和音乐消费.作者利用deep learning结合协同过滤来做音乐推荐. 详细内容: 1. 协同过滤 基本原理:某两个用户听的歌曲 ...

  9. uploadify 使用 详细 说明

    简单 常用的 时间 有点 紧  先写 这点 ,  有时间 在更新 下面有 例子  链接 不过要 自己 摘 一下 很简单的啦   <script type="text/javascrip ...

  10. Echarts数据图表插件--开源、大气、强大

    个人觉得不错,分享给大家. 教程地址:http://echarts.baidu.com/, 开源项目:https://github.com/ecomfe/echarts