angularJS进阶阶段(4)
angularJS进阶阶段(4)
编译器/$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函数更常用。
指令/directive
笼统地说,指令是DOM元素(例如属性、元素、CSS类等)上的标记符,用来告诉AngularJS的HTML编译器 ($compile服务)将特定的行为绑定到DOM元素,或者改变DOM元素。
指令可以放置在元素名、属性、CSS类名称及备注中。下面是一些等效的触发”ng-bind”指令的写法:
|
|
指令的规范化
AngularJS在进行匹配检测之前,首先对HTML元素的标签和属性名转化成规范的驼峰式字符串:
1.去除名称前缀的x-和data-
2.以: , - 或 _ 为分割符,将字符串切分成单词,除第一个单词外,其余单词首字母大写
3.重新拼接各单词
例如,下面的写法都等效地匹配ngBind指令:
12345 <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, 编译器使用这个规范化的名称与注册的指令进行匹配。
控制器
控制器的作用
简单地说,没有控制器/controller,我们没有地方定义业务模型。<div ng-init="sb={name:'somebody',gender:'male',age:28}">
控制器让我们有机会在scope上定义我们的业务逻辑,具体说,可以使用控制器:
1.对scope对象进行初始化
2.向scope对象添加方法在模板中声明控制器
在一个HTML元素上使用ng-controller指令,就可以引入一个控制器对象:
<div ng-controller="myController">...</div>
控制器的实现
|
|
控制器的一次性
控制器构造函数仅在AngularJS对HTML文档进行编译时被执行一次。从这个角度看, 就更容易理解为何将控制器称为对scope对象的增强:一旦控制器创建完毕,就意味着scope对 象上的业务模型构造完毕,此后就不再需要控制器了- scope对象接管了一切。
控制器对scope的影响
ng-controller指令总是创建一个新的scope对象:
在图中,我们看到:
1.ng-app指令引发$rootScope对象的创建。开始时,它是一个空对象。
2.body元素对应的scope对象还是$rootScope。ng-init指令将sb对象挂在了$rootScope上。
3.div元素通过ng-controller指令创建了一个新的scope对象,这个对象的原型是$rootScope。
4.因为原型继承的关系,在do函数中对sb的引用指向$rootScope.sb。$scope对象
初始化$scope对象
通常在应用启动时,需要初始化scope对象上的数据模型。我们之前曾使用ng-init指令进行初始化, 而使用控制器则是更为规范的做法。
请注意,控制器仅仅负责在编译时在scope对象上建立视图对象vm,视图对象和模板的绑定则是由 scope负责管理的。
1234567891011121314151617181920212223242526272829 <html ng-app="ezstuff"><head><script src="http://lib.sinaapp.com/js/angular.js/angular-1.2.19/angular.min.js"></script></head><body><div ng-controller="ezController"><div>name : {{vm.sb.name}}</div><div>gender : {{vm.sb.gender}}</div><div>age : {{vm.sb.age}}</div><div>career : {{vm.sb.career}}</div><div><img ng-src="{{vm.sb.photo}}"></div></div></body></html>var ezControllerClass = function($scope){//view model$scope.vm = {sb : {大专栏 angularJS进阶阶段(4) name : "Jason Stantham",gender : "male",age : 48,career : "actor",photo : "http://b.hiphotos.baidu.com/baike/w%3D268/sign=a03742145bee3d6d22c680cd7b176d41/359b033b5bb5c9eae4c45250d739b6003af3b34a.jpg"}};};angular.module("ezstuff",[]).controller("ezController",ezControllerClass);
向scope对象添加方法
业务模型是动态的,在数据之外,我们需要给业务模型添加动作。在之前建立的业务模型上,我们增加一个随机挑选的方法:shuffle,这个方法负责 从一个小型的名人库中随机的选择一个名人来更新模型的sb属性:
通过在button上使用ng-click指令,我们将模型的shuffle方法绑定到了鼠标点击 事件上。试着用鼠标点击【shuffle】按钮,我们的模型将从库里随机的选出一个 名人,显示在视图里。
1234567891011121314151617181920212223242526272829303132333435363738394041424344 <html ng-app="ezstuff"><head><script src="http://lib.sinaapp.com/js/angular.js/angular-1.2.19/angular.min.js"></script></head><body><div ng-controller="ezController"><button ng-click="vm.shuffle();">shuffle</button><div>name : {{vm.sb.name}}</div><div>gender : {{vm.sb.gender}}</div><div>age : {{vm.sb.age}}</div><div>career : {{vm.sb.career}}</div><div><img ng-src="{{vm.sb.photo}}"></div></div></body></html>var ezControllerClass = function($scope){//view model$scope.vm = {sb : {name : "Jason Stantham",gender : "male",age : 48,career : "actor",photo : "http://b.hiphotos.baidu.com/baike/w%3D268/sign=a03742145bee3d6d22c680cd7b176d41/359b033b5bb5c9eae4c45250d739b6003af3b34a.jpg"},shuffle : (){var repo = [{name:"Jason Stantham",gender:"male",age:48,career:"actor",photo:"http://b.hiphotos.baidu.com/baike/w%3D268/sign=a03742145bee3d6d22c680cd7b176d41/359b033b5bb5c9eae4c45250d739b6003af3b34a.jpg"},{name:"Jessica Alba",gender:"female",age:32,career:"actress",photo:"http://h.hiphotos.baidu.com/baike/w%3D268/sign=ce8cdcb43bdbb6fd255be2203125aba6/b219ebc4b74543a91d7092831c178a82b9011411.jpg"},{name:"Nicolas Cage",gender:"male",age:53,career:"actor",photo:"http://f.hiphotos.baidu.com/baike/w%3D268/sign=e97412d2359b033b2c88fbdc2dcf3620/4a36acaf2edda3cc4187b7f600e93901203f9280.jpg"},{name:"崔永元",gender:"male",age:48,career:"independent journalist",photo:"http://e.hiphotos.baidu.com/baike/w%3D268/sign=856e3aab34d3d539c13d08c50286e927/8c1001e93901213ff48a548956e736d12f2e952d.jpg"},{name:"Sheetal Sheth",gender:"female",age:36,career:"actress",photo:"http://h.hiphotos.baidu.com/baike/c0%3Dbaike80%2C5%2C5%2C80%2C26/sign=f3627d0333fa828bc52e95b19c762a51/060828381f30e924f7c565374c086e061d95f757.jpg"},{name:"Barack Obama",gender:"male",age:58,career:"president",photo:"http://a.hiphotos.baidu.com/baike/w%3D268/sign=2a0045f7f1d3572c66e29bdab2126352/f7246b600c338744cb293d62520fd9f9d72aa03b.jpg"},{name:"Владимир Владимирович Путин",gender:"male",age:63,career:"president",photo:"http://h.hiphotos.baidu.com/baike/w%3D268/sign=657e210bb17eca8012053ee1a9239712/8435e5dde71190efa1a915f7cf1b9d16fdfa604c.jpg"}];var idx = Math.floor(Math.random()*repo.length);$scope.vm.sb = repo[idx];}};};angular.module("ezstuff",[]).controller("ezController",ezControllerClass);
服务
创建服务组件
在AngularJS中创建一个服务组件很简单, 只需要定一个具有$get方法的构造函数 然后使用模块的provider方法进行登记:
123456789 //定义构造函数var myServiceProvider = (){this.$get = (){return ....};};//在模块中登记angular.module("myModule",[])provider("myService",myServiceProvider);
可配置的服务
有时我们希望服务在不同的场景下可以有不同的行为,这意味着服务可以进行配置。
比如,我们希望小计算器可以根据不同的本地化区域,给计算结果追加货币符号前缀, 那么需要在这个服务创建之前,首先配置本地化区域的值,然后在具体的计算中, 根据这个值选择合适的货币符号。
AngularJS使用模块的config()方法对服务进行配置,需要将实例化的服务提供者 (而不是服务实例)注入到配置函数中:
1234 angular.module("myModule",[])config(["myServiceProvider",function(myServiceProvider){//do some configuration.}]);
友情提醒
如有疑问和错误之处,请告知程序员小鲁
angularJS进阶阶段(4)的更多相关文章
- AngularJS进阶(四十)创建模块、服务
AngularJS进阶(四十)创建模块.服务 学习要点 使用模块构架应用 创建和使用服务 为什么要使用和创建服务与模块? 服务允许你打包可重用的功能,使之能在此应用中使用. 模块允许你打包可重用的功能 ...
- AngularJS进阶学习
参考:http://***/class/54f3ba65e564e50cfccbad4b 1. AJAX:Asynchronous JavaScript and XML(异步的 JavaScript ...
- AngularJS进阶(三十九)基于项目实战解析ng启动加载过程
基于项目实战解析ng启动加载过程 前言 在AngularJS项目开发过程中,自己将遇到的问题进行了整理.回过头来总结一下angular的启动过程. 下面以实际项目为例进行简要讲解. 1.载入ng库 2 ...
- AngularJS进阶(一)深入理解ANGULARUI路由_UI-ROUTER
深入理解ANGULARUI路由_UI-ROUTER 最近在用 ionic写个webapp 看到几个demo中路由有好几种,搞的有点晕,查下资料研究下,做个笔记,其中大部分为摘抄别人的,做个说明免得被人 ...
- Angularjs进阶笔记(2)-自定义指令中的数据绑定
有关自定义指令的scope参数,网上很多文章都在讲这3种绑定方式实现的效果是什么,但几乎没有人讲到底怎么使用,本篇希望聊聊到底怎么用这个话题. 一. 自定义指令 自定义指令,是Angularjs用来实 ...
- AngularJS进阶(三十八)上拉加载问题解决方法
AngularJS上拉加载问题解决方法 项目中始终存在一个问题:当在搜索栏输入关键词后(见图1),按照既定的业务逻辑应该是服务端接收到请求后,首先返回查询的前7条数据,待客户端出现上拉加载时,继续查找 ...
- AngularJS进阶(二十五)requirejs + angular + angular-route 浅谈HTML5单页面架构
requirejs + angular + angular-route 浅谈HTML5单页面架构 众所周知,现在移动Webapp越来越多,例如天猫.京东.国美这些都是很好的例子.而在Webapp中,又 ...
- AngularJS进阶(三十七)IE浏览器兼容性后续
IE浏览器兼容性后续 前言 继续尝试解决IE浏览器兼容性问题,结局方案为更换jquery.angularjs.IE的版本. 1.首先尝试更换jquery版本为1.7.2 jquery-1.9.1.js ...
- AngularJS进阶(三十六)AngularJS项目开发技巧之利用Service&Promise&Resolve解决图片预加载问题(后记)
AngularJS项目开发技巧之利用Service&Promise&Resolve解决图片预加载问题(后记) 前言 在"AngularJS项目开发技巧之图片预加载" ...
随机推荐
- LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现
首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点. 换句话说,就是两个点在这棵 ...
- IMX6开发板qt creator直接编译ARM架构程序
除了通过 11.2.2 小节通过命令行的操作来编译在 iTOP-imx6 开发板上运行的程序,还可以直接在 qtcreator 上设置,然后每次编译的程序都可以在开发板上运行.如下图所示,打开 qtc ...
- android weight
- 表查询语句及使用-连表(inner join-left join)-子查询
一.表的基本查询语句及方法 from. where. group by(分组).having(分组后的筛选).distinct(去重).order by(排序). limit(限制) 1.单表查询: ...
- Mac环境下pyCharm的安装,激活及使用
1.pyCharm的安装 安装地址: https://www.jetbrains.com/pycharm/download/#section=mac 2.激活 获取注册码地址: http://idea ...
- Log4J基础
Log4j由三个重要的组件构成:日志信息的优先级,日志信息的输出目的地,日志信息的输出格式.日志信息的优先级从高到低有ERROR.WARN. INFO.DEBUG,分别用来指定这条日志信息的重要程度: ...
- 计算a^b==a+b在(l,r)的对数Codeforces Round #597 (Div. 2)
题:https://codeforces.com/contest/1245/problem/F 分析:转化为:求区间内满足a&b==0的对数(解释见代码) ///求满足a&b==0在区 ...
- cnn可视化 感受野(receptive field)可视化
网址: https://befreeroad.github.io/#/editor 参考: http://ethereon.github.io/netscope/#/editor 在此基础上添加 感受 ...
- erp和crm的区别
CRM(Customer Relationship Management)即客户关系管理.从字面上来看,是指企业用CRM来管理与客户之间的关系.在不同场合下,CRM可能是一个管理学术语,可能是一个软件 ...
- Python练习五-函数
1.简述普通参数.指定参数.默认参数.动态参数的区别1)普通参数中,有形参和实参,其中形参是定义函数时写的参数,实参是调用函数时传给函数的参数:2)默认参数是在定义函数时,参数设定一个默认值:3)指定 ...