1,angular的ng-model带来了双向绑定机制
2,用angular的表达式{{...}}现实在HTML中,存储在我们的$scope上
3,在angular中$scope是连接controllers(控制器)和templates(模板view/视图)的主要胶合体。我们可以把我们的model存放在scope上,来达到双向你绑定。
一.html Parser(编译器)
- compile(编译):遍历dom找到所有指令,按指令优先级排序,执行conpile函数,把每个compile函数返回的link函数存到一个总的link函数中;
- link(链接):将$scope绑定到dom上,在元素上注册事件监听器,$watch监控数据模型;
二. 双向数据绑定
主要通过脏检测来完成,就是针对旧值保存一份副本出来,如果值发生变化,就回去比较副本和旧值,如果不一样了,就标记为dirty,如果digest次数过多大于10的话,就会抛出异常。所以要尽量减少digest的次数。UI事件,ajax请求或者 timeout 延迟事件,会触发脏检测。
// 核心代码 function Scope() { this.$$watchers = []; } Scope.prototype.$watch = function(watchFn, listenerFn) { var watcher = { watchFn: watchFn, listenerFn: listenerFn }; this.$$watchers.push(watcher); } Scope.prototype.$$digestOnce = function() { var self = this; var dirty; _.forEach(this.$$watchers, function(watch) { var newValue = watch.watchFn(self); var oldValue = watch.last; if (newValue !== oldValue) { watch.listenerFn(newValue, oldValue, self); dirty = true; } watch.last = newValue; }) return dirty; }; Scope.prototype.$digest = function() { var dirty; do { dirty = this.$$digestOnce(); } while (dirty); };
// 在指令编译时,Angular对input添加了事件监控,会自动将input的值设置到$scope上。 <input ng-model = 'value'> // 在编译时,Angular使用$watch方法在对应的$scope上添加了监控,一旦$scope中的属性值发生了变化,这里就会跟着变($digest过程) <p>{{ value }}</p>
三 . 依赖注入
$injector自动注入:分析匹配参数名 --> fn.$injections = [] --> fn.call或者fn.apply传递需要注入的对象。
angular在每次应用启动时,初始化一个Injector实例,对每一个Angular应用来说,所有的"provider"都是存在相同的providerCache或cache中。
// 拿到依赖项 function getDependency(fn) { var args = fn.toString.match(/^[^(]*(s*([^)]*))/m); return args[1].split(','); } // 查找依赖项对应的对象 function createInjector(cache) { this.cache = cache; } angular.module = function () { modules = {}; injector = new createInjector(modules); return { injector: injector, factory: function (name, fn) { modules[name.trim()] = this.injector.invoke(fn); return this; } } }; // 执行时注入 createInjector.prototype = { invoke: function (fn, self) { argsString = extractArgs(fn); args = []; argsString.forEach(function (val) { args.push(this.cache[val.trim()]); }, this); return fn.apply(self, args); } };
两种声明依赖的方法
// 数组 angular.module('app').controller('myCtrl', ['$scope', '$location', function ($scope, $location) { ... }]) // $inject angular.module('app').controller('myCtrl', Ctrl); function Ctrl($scope) { ... } Ctrl.$inject = ["$scope", "$location"];
四. 封装指令的基础
- 指令嵌套
- 指令处理html元素
- 指令间的交互
五. 杂
- service:单例的功能或function,用来完成一些通用的功能,angular内置很多service(以$开头),可以自动注入(构造器注入);
- angular.module('app') 一切都是从定义模块开始
- 与dom操作相关的放在directive里,controller将所有东西联合起来
- 模块就是个容器,将其他东西都放在里面的一个意思