1. 关于AngularJS
AngularJS 是 Google 开源出来的一套 js 工具。下面简称其为 ng 。这里只说它是“工具”,没说它是完整的“框架”,是因为它并不是定位于去完成一套框架要做的事。更重要的,是它给我们揭示了一种新的应用组织与开发方式。
ng 最让我称奇的,是它的数据双向绑定。其实想想,我们一直在提数据与表现的分离,但是这里的“双向绑定”从某方面来说,是把数据与表现完全绑定在一起——数据变化,表现也变化。反之,表现变化了,内在的数据也变化。有过开发经验的人能体会到这种机制对于前端应用来说,是很有必要的,能带来维护上的巨大优势。当然,这里的绑定与提倡的分离并不是矛盾的。
ng 可以和 jQuery 集成工作,事实上,如果没有 jQuery , ng 自己也做了一个轻量级的 jQuery ,主要实现了元素操作部分的 API 。
关于 ng 的几点:
对 IE 方面,它兼容 IE8 及以上的版本。
与 jQuery 集成工作,它的一些对象与 jQuery 相关对象表现是一致的。
使用 ng 时不要冒然去改变相关 DOM 的结构(不是说不可以,只是你自己要清楚你在做什么)。
2. 关于本文档
这份文档如其名,是我自己学习 ng 的过程记录。只是过程记录,没有刻意像教程那样去做。所以呢,从前至后,中间不免有一些概念不清不明的地方。因为事实上,在某个阶段对于一些概念本来就不可能明白。所以,整个过程只求在形式上的能用即可——直到最后的“自定义”那几章,特别是“自定义指令”,那几章过完,你才能看清 ng 本来的面貌。前面就不要太纠结概念,本质,知道怎么用就好。
3. 开始的例子
我们从一个完整的例子开始认识 ng :
1 |
|
从上面的代码中,我们看到在通常的 HTML 代码当中,引入了一些标记,这些就是 ng 的模板机制,它不光完成数据渲染的工作,还实现了数据绑定的功能。
同时,在 HTML 中的本身的 DOM 层级结构,被 ng 利用起来,直接作为它的内部机制中,上下文结构的判断依据。比如例子中 p 是 div 的子节点,那么 p 中的那些模板标记就是在 div 的 Ctrl 的作用范围之内。
其它的,也同样写一些 js 代码,里面重要的是作一些数据的操作,事件的绑定定义等。这样,数据的变化就会和页面中的 DOM 表现联系起来。一旦这种联系建立起来,也即完成了我们所说的“双向绑定”。然后,这里说的“事件”,除了那些“点击”等通常的 DOM 事件之外,我们还更关注“数据变化”这个事件。
最后,可以使用:
1 | angular.bootstrap(document.documentElement, ['app']); |
来把整个页面驱动起来了。(你可以看到一个可被控制大小的红色方块)
简单来说,就是定义一个 App ,然后 bootstrap 时指定需要用哪些 App 。( App 之间的依赖关系在定义时声明就好了)
这里说的一个 App 就是 ng 概念中的一个 Module 。
4. 依赖注入
injector , 我从 ng 的文档中得知这个概念,之后去翻看源码时了解了一下这个机制的工作原理。感觉就是虽然与自己的所想仅差那么一点点,但就是这么一点点,让我感慨想象力之神奇。
先看我们之前代码中的一处定义:
1 | app.controller('BoxCtrl', function($scope, $element){}); |
在这个函数定义中,注意那两个参数: $scope , $element ,这是两个很有意思的东西。总的来说,它们是参数,这没什么可说的。但又不仅仅是参数——你换个名字代码就不能正常运行了。
事实上,这两个参数,除了完成“参数”的本身任务之外,还作为一种语法糖完成了“依赖声明”的任务。本来这个函数定义,完整的写法应该像 AMD 声明一样,写成:
1 | app.controller('BoxCtrl', |
这样就很明显,表示有一个函数,它依赖于两个东西,然后这两个东西会依次作为参数传入。
简单起见,就写成了一个函数定义原本的样子,然后在定义参数的名字上作文章,来起到依赖声明的作用。
在处理时,通过函数对象的 toString() 方法可以知道这个函数定义代码的字符串表现形式,然后就知道它的参数是 $scope 和 $element 。通过名字判断出这是两个外部依赖,然后就去获取资源,最后把资源作为参数,调用定义的函数。
所以,参数的名字是不能随便写的,这里也充分利用了 js 的特点来尽量做到“反省”了。
在 Python 中受限于函数名的命名规则,写出来不太好看。不过也得利于反省机制,做到这点也很容易:
1 | # -*- coding: utf-8 -*- |
5. 作用域
这里提到的“作用域”的概念,是一个在范围上与 DOM 结构一致,数据上相对于某个 $scope 对象的属性的概念。我们还是从 HTML 代码上来入手:
1 | <div ng-controller="BoxCtrl"> |
上面的代码中,我们给一个 div 元素指定了一个 BoxCtrl ,那么, div 元素之内,就是 BoxCtrl 这个函数运行时, $scope
这个注入资源的控制范围。在代码中我们看到的 click()
, w , h 这些东西,它们本来的位置对应于 $scope.click
, $scope.w
, $scope.h
。
我们在后面的 js 代码中,也可以看到我们就是在操作这些变量。依赖于 ng 的数据绑定机制,操作变量的结果直接在页面上表现出来了。
关注 web翎云阁,定时推送,互动精彩多,若你有更好的见解,欢迎留言探讨!