angularjs-bootstrap
放置”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
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-->
concepts
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'.
Runtime
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从新赋值
Scope
view与contorller的纽带
Controller
controller的职责是构建model,并通过回调函数将其model推送到view中。view是当前scope和tamplate(HTML)的映射。scope是指挥model到view以及向controller发送event的纽带。
Model
Model可以理解为数据对象,它作用是与tamplate集合产生视图。
View
template与model结合产生view,最终呈现为浏览器DOM。
此图通俗点讲就是 其他很多模板引擎,通过tempalte和model 合并成HTML字符串,再通过类似innerHTML方法渲染到DOM上,当数据改变,Model变化,需要重新也Tempate合并,产生HTML字符串重新渲染。
angularjs模板引擎通过compliter查找directives,依次在model中设置watches。一个一直更新的view,不需要重新拼接model和template,model成为唯一数据来源。
Directives
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>
Compilation process, and directive matching
编译三步骤
1 通过浏览器的API,将HTML转换成DOM
2 angularjs通过$complate() 遍历DOM,对directive进行匹配。匹配成功将与对应的DOM加入到directive列表中。他们将按照优先级执行他们的complate()函数。
3 complate返回linking function ,linking fn 将directives绑定到对应的作用域中,创建一个实况视图。使view和model实现双向绑定。