一、AngularJS应用剖析
AngularJS存在一些最主要的构件,如模型,视图和控制器。但AngularJS中也有许多其他可供灵活使用的部件,包括模块,指令,过滤器,工厂和服务。
一 . 1 依赖注入
没有依赖注入(dependencies injector),就不得不以某种方式找到自己所需要的组件,很可能得使用到全局变量。虽然这样子也能工作,但是不如AngularJS的依赖注入来的简单。依赖注入,可以通过让某个组件的工厂函数的参数上声明依赖来实现,这个函数使用参数来提出需求: "Hey! AngularJS兄弟,我需要这样子的一个构件!"
app.controller("HelloController", function($scope, $timeout){ //hey, AngularJS 我需要$scope,和$timeout //为了我能正常运行,麻烦你先把这两个构件帮我准备一下吧! })
依赖注入的主要好处是AngularJS辅助管理组件,并在需要时提供给相应的函数。依赖注入还为测试带来好处。
一 . 2 工人和工人函数
简单的概念:AngularJS在需要建立构件时将调用工厂函数,当需要使用该构件时就会调用工人。相当于,工厂函数是模具,工人则是通过这个模具制造出来的实体。工厂函数负责创建那些来执行工作的对象,工厂函数往往会返回一个工人函数。下面的这个例子中,第一个function便是工厂函数,return的内容则是一个工人(对象实例)。
app.directive("Hello", function(){ return function(scope, ele, attrs){ //.... } })
一 . 3 . 1 使用模块工作
随着应用程序随着时间的推移会变得复杂,因此我们需要使用模块来使我们对程序进行更有效、编辑的管理测试和工作。模块具有三种主要角色:1. 将一个AngularJS程序与HTML文档中的一部分进行关联(ng-app作用范围)。2. 帮助我们组织AngularJS应用程序中的代码和组件
var app = angular.module("myApp", ["app.Controllers", "app.Filters", "app.Servers", "app.Directive"]); ...
其中,这些依赖并不是必须按照某种特定的顺序定义的。但是AngularJS会保证这些具有依赖的模块(此处的app模块)会首先调用其(app模块)所依赖("app.Controllers", "app.Filters", "app.Servers", "app.Directive")的回调函数。相当于,有个哥们想自己组装一部四驱车,那他会把轮子,车身,电池什么的先给准备好。
一 . 3. 2 config与run
config方法会接受一个函数,这个函数会在相应模块被调用之后被调用。config方法常常会通过注入其他服务的值的方式来配置模块
app.config(function($httpProvider){ //... })
run方法也会接受一个函数,但是该函数之会在所有模块都加载完以及解析完它们的依赖之后才会被调用
app.run(function($rootScope){ //... ])
执行顺序——一个例子
App.Servives模块的config回调函数
App模块的config回调函数
App.Servives模块的run回调函数
App模块的run回调函数
二、AngularJS指令系统
二、1 数据绑定类指令
数据绑定类指令是负责执行数据绑定的,数据绑定是使用模型中的值并将它插入到HTML文档中。
1. ng-bind-template 大家都知道ng-bind会替换它被用到的元素内容,而且ng-bind受限于只能处理单个数据绑定的表达式 <span ng-bind="bool"></span,
当需要进行创造多个数据绑定便可以使用灵活的ng-bind-template
<div ng-bind-template="First: {{my.mum}} and {{my.dad}}">
2. ng-non-bindable 阻止内联数据绑定
AngularJS不是说唯一使用{{ }}符号的JavaScript包,因此如果同时使用多个库可能会遇到问题,或者我仅仅是想输出"{{ }}"这个符合。AngularJS在请求绑定到一个不存在的模型属性时不会报错。例如 AngularJS uses {{ and }} characters for tempalte 会被替换成 AngularJS uses characters for tempalte ,因此使用ng-non-bindable可以为我们解决这个问题,以下实例会输出 AngularJS uses {{ and }} characters for tempalte
<div ng-non-bindable> AngularJS uses {{ and }} characters for tempalte </div>
二、2 模板类指令
1. ng-repeat
<li ng-repeat="(key, value) in item"> {{key}} = {{value}} </li>
当遍历目标是对象时, key为当前属性名,value为对象属性的值。而当遍历目标是集合(如一个数组)时, key为当前的遍历下标(从0开始),value为集合的值
ng-repeat的内置变量
$index: 返回当前的遍历下标
$first/$last: 若当前对象时遍历集合的第一/最后一个元素,则返回true
$even/$odd: 若当前对象时遍历集合的第偶数个/第奇数个元素,则返回true
$middle: 若当前对象时遍历集合的中间元素(不是第一或者最后一个元素),则返回true
ng-repeat + ng-if
我们无法再ng-repeat指令所应用到的同一个元素上使用ng-if <li ng-repeat="item in Objs" ng-if="item.exist">{{item.name}}</li> 这样子会报错。我们应该先把数据通过filter服务整合出来后,再用ng-repeat遍历访问 <li ng-repeat="item in Objs | filter: {exist: 'true'}" >{{item.name}}</li>
2. ng-include
<ng-include src=" 'template.html' "></ng-include> 请注意,此处有坑,双引号里面还有一个单引号。
ng-include的配置参数
src: 指定加载内容的URL;onload: 指定一内容被加载后调用的计算表达式;autoscroll: 指定内容被加载时,是否滚动到这部分视图所在区域(注:小鹏我在实验时发现这个配置参数并没有运行..不知道是不是哪里引用错误了)
ng-include VS ng-switch
ng-switch适合用于复杂度不高,内容较小的时候使用。ng-include适用于复杂性较大,内容较多的页面,但首次加载时,AngularJS会使用ajax来请求模板,因此会有延迟。
二、3 事件类指令
我们可以通过分辨发事件对象中event.type属性,来处理在发生同一元素上不同的事件<li ng-repeat="item in items" ng-mouseenter="handle($event)" ng-mouseleave="handle($event)"> 。但是应该注意:AngularJS为事件指令所用的事件名称和底层事件的type属性之间存在不匹配的情况。例如 ng-mouseenter="handle($event)" 但他的 event.type == "mouseover" 。因此,我们在处理此类情况情况时,应当先确认事件的底层名称。
$scope.handle(event){ console.log(event.type) }
二、4 布尔属性类指令
ng-check 管理checked属性(input="checkbox")
ng-diabled 管理disabled属性(input与button元素)
ng-open 管理open属性(detail元素)
ng-readonly 管理readonly属性(input元素)
ng-selected 管理selectes属性(option元素)