放置”ng-app”到应用的根节点中,如果你想让angular自动启动你的应用,通常可以放置于<html>标签中。
<style type="text/css"> .ng-cloak { display: none; } </style>
<div ng-app class="ng-cloak">{{1+1}}</div>
里面的”ng-cloak”,这个是用于在angular.js编译完成之前, 编译完成后这个class或属性会被删除
也可用 <div ng-bind=""></div>代替,这样未解析之前,用户不会看到 未解析的{{1+1}}了。
directive是一个当编译器在dom中遇到会执行的一个函数,有内置也可自定义。
directive分为 elemet(E) class(C) attribute(A) 注释(M) 四种
<ng-bind></ng-bind> <div class="ng-bind:exp"></div> <div ng-bind="exp></div> <!--directive ng-bind exp-->
angular启动过程
1 浏览器加载HTML,将HTML标签转换成DOM对象;
2 浏览器加载angularjs
3 angularjs等待DOMContentLoaded事件
4 angularjs需找ng-app指令,指定应用边界的范围
5 如果ng-app有指定module,将被用作配置$injector
6 $injector用于创建$complie 和 $rootScope
7 $complie 用于编译 和链接 $rootscope 根作用域
8 ng-init 指令在对应的scope中创建name属性 并对其赋值 如:<div ng-init="name = 'test'">{{name}}</div>
9 将'{{name}}'的值插入表达式的队列中,最终显示为'test'.
dirty checking (脏检查),将原有对象复制一份快照,在某个时间比较现在对象与快照的值,如果不一样表明发生变化,这个策略要保留俩分变量,而且要遍历对象,比较每个属性,会有一个的性能问题。
AngularJs采用的就是此方法。但不会脏检查所有的对象,当对象绑定到html中,这个对象添加为检查对象。属性也是如此在AngularJs程序初始化时,会将绑定的对象的属性添加为监听对象(watcher), 也就是说一个对象绑定了N个属性,就会添加N个watcher。
angularjs $apply源码 : // 1 浏览器通过 event-loop 触发angularjs的脏检查方法(也就是angularjs通过调用$scope.$apply( stimulusFn )进入 angular execution context)。 function$apply(expr) { try { //2 angularjs通过内置的$eval()解析表达式 return $eval(expr); } catch(e) { //出现错误给提示 $exceptionHandler(e); } finally { //3 如果表达式合法,则通过$digest()方法进行所属scope及子scope进行脏检查 $root.$digest(); } } 4 当$digest()方法触发时,$watch()观察的val 与上次执行时的不一样,就会被触发,从而对特定的DOM从新赋值
view与contorller的纽带
Controller
controller的职责是构建model,并通过回调函数将其model推送到view中。view是当前scope和tamplate(HTML)的映射。scope是指挥model到view以及向controller发送event的纽带。
Model可以理解为数据对象,它作用是与tamplate集合产生视图。
View
template与model结合产生view,最终呈现为浏览器DOM。
此图通俗点讲就是 其他很多模板引擎,通过tempalte和model 合并成HTML字符串,再通过类似innerHTML方法渲染到DOM上,当数据改变,Model变化,需要重新也Tempate合并,产生HTML字符串重新渲染。
angularjs模板引擎通过compliter查找directives,依次在model中设置watches。一个一直更新的view,不需要重新拼接model和template,model成为唯一数据来源。
Directive是一个行为或DOM转换,允许你以生命的方式扩展HTML标签 例子:
<!DOCTYPE HTML> <html ng-app="myDirective"> <head> <meta charset="UTF-8"> <title>directive</title> <style type="text/css"> .ng-cloak { display: none; } </style> </head> <body ng-controller="MyCtrl"> <div ng-model="content" contenteditable="true">My Little Dada</div> <pre>modelValue = {{content}}</pre> <button ng-click="reset()">reset(change model)</button> <script src="../angular-1.0.1.js" type="text/javascript"></script> <script type="text/javascript"> angular.module("myDirective",[]) .directive("contenteditable",function() { return { require:'ngModel', link:function (scope, element, attr, ngModel) { function setVal() { ngModel.$setViewValue(element.text()); } // veiw -> model element.bind("keyup",function() { scope.$apply(setVal); }); // model -> view ngModel.$render = function(val) { console.log("render running"); element.html(val); }; //init setVal(); } } } ).controller("MyCtrl",function($scope) { $scope.reset = function() { $scope.content = "My Little Dada"; }; }); </script> </body> </html>
编译三步骤
1 通过浏览器的API,将HTML转换成DOM
2 angularjs通过$complate() 遍历DOM,对directive进行匹配。匹配成功将与对应的DOM加入到directive列表中。他们将按照优先级执行他们的complate()函数。
3 complate返回linking function ,linking fn 将directives绑定到对应的作用域中,创建一个实况视图。使view和model实现双向绑定。