笔者AngularJS接触时间差很少是两年多,虽然这两年多AngularJS版本突飞猛进,可是笔者的版本是比较老的1.4.3,一方面是本身对这个版本比较熟悉,另外一方面是老项目须要维护,固然本文笔者也尽量地写到通俗易懂,毕竟AngularJS在不少设计上也有独到之处,可是人无完人,笔者可能有疏漏的话,烦请提醒留言。下面回归正文,整体而言,AngularJS在设计上有两点比较重要的地方,分别是指令(directive)和做用域(scope)。directive实现了对经常使用DOM操做的简要封装,而渲染的数据源于scope,而这中间的媒介(或者说是反应的容器、载体)是controller,三者相互做用造成AngularJS的基础设计模式。MVVM框架下就须要双向绑定,而双向绑定的实现是基于脏值检测的digest loop,这也是AngularJS设计比较先进的地方(固然也有缺陷,这个后续再讲)。git
本文入门门槛比较高,若对AngularJS刚接触的同窗请先看一下官方教程,第一讲重点讲scope,后续讲指令。angularjs
AngularJS数据交互示意图:github
一般来讲AngularJS经过scope来抽象化地实现directive和DOM之间的交流,而scope存在controller上的,所以AngularJS不会过多干涉原生的东西,而是拓展一些新的带$前缀的内部功能属性,好比以一个$符号的前缀,以两个$($$)符号做为前缀的是AngularJS的私有属性,通常不推荐使用。设计模式
在AngularJS中,一个scope(做用域)必须与标签元素关联,而标签元素却不必定跟scope关联,它们之间不是充要条件,元素能够经过如下三种方式被指定到一个scope上。数组
- 经过controller或者directive,scope会被指定在一个标签元素上
- 若标签元素上没有指定,则继承于父标签上的scope
- 反之,则不指定为任何一个scope
第一和第二种状况若接触过AngularJS,则不难理解,第三种状况属于超出AngularJS的执行范围即在ng-app指令范围以外。app
digest循环是数据双向绑定的关键,也是AngularJS设计上的关键。AngularJS是基于数据绑定特征,经过一个脏值检测循环去追踪数据变化和事件变化,而数据绑定在scope上的,所以scope上确定有触发这一检测的方法,而这个就是scope.$digest方法,相应的状态表现为$$phase。框架
- $digest-触发digest循环
- $$phase-digest循环执行状态{null, '$apply', '$digest'}
讲这一过程的以前咱们先介绍watcher(监听器)及相关属性函数
- $watch(watchExp, listener,objectEquality)-增长scope监听器
- $watchCollection-监听数据对象或者数组
- $$watchers-保持监听器与scope的关联
数据双向绑定的基础就是$wathch,而数据及时的更新变化却要依赖于$digest循环,当你每次使用ng-bind,ng-model时都会自动建立一个$watch,所以每当数据变化时都会及时更新到界面上,那么问题来了,这个及时的背后依靠的是什么呢?又是何时触发$digest呢?oop
digest在AngularJS设计上处于核心的位置,要么被直接触发,要么手动调用$apply触发,而思路上就是service、directive致使直接或者间接地触发了digest,而digest触发了scope上的watcher,watcher更新界面数据,这是设计上最基本的思路。设计
而这个间接指的是有些AngularJS封装过的函数,好比$timeout服务内置$apply方法。而这个直接是指ngModel或者ngBind值上的变动直接致使watcher触发digest。