您的位置:首页 > Web前端 > AngularJS

Angular双向数据绑定

2017-06-01 14:50 901 查看
1、什么是双向数据绑定

双向数据绑定:

Angular实现了双向绑定机制。所谓的双向绑定,无非是从界面的操作能实时反映到数据,数据的变更能实时展现到界面。即数据模型(Module)和视图(View)之间的双向绑定。

例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
输入: <input ng-model="name">
<h1>你输入了: {{name}}</h1>
</div>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.name = "test";
});
</script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[/code]



当你在输入框中进行输入时,也会修改网页中的文本内容。

这里我使用了{{}}来实现了最简单数据绑定,{{}}进行的数据绑定时单向的,只实现了数据展示。然后我用input标签配合ng-model 实现了一个简单的双向数据绑定的例子,双向绑定最常用的场景就是表单,这样当用户在前端页面完成输入后,不用任何操作,我们就已经拿到了用户的数据存放到数据模型中了。

2、双向数据绑定与单向数据绑定

单向数据绑定:



数据模型–>视图

El表达式中常见 ${变量名}以及{{}} ,它只提供从数据源到视图的单方向的数据展示。

缺点:HTML代码一旦生成完以后,就没有办法再变了,如果有新的数据来了,那就必须把之前的HTML代码去掉,重新整合生成一次。

双向数据绑定:



数据模型<==>视图

用户在视图上的修改会自动同步到数据模型中去,同样的,如果数据模型中的值发生了变化,也会立刻同步到视图中去。

缺点:双向数据绑定的应用场景非常有限。

3、双向数据绑定原理

带着问题看下面的代码。

问题:绑定数据是怎么生效的?

如图示例,当点击+1按钮时,显示的数据是否会正常的增加?

如果会正常增加,说明原因。

如果不会,说明原因并修改代码使其可以正常显示。



<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>

<body ng-app="test">
<div ng-controller="CounterCtrl">
<br>
<button myclick>+1</button>

<br>

{{counter}}
</div>
<script>

var app = angular.module("test", []);

app.directive("myclick", function() {
return function (scope, element, attr) {
element.on("click", function() {
scope.counter++;
});
};
});

app.controller("CounterCtrl", function($scope) {
$scope.counter = 0;
});
</script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[/code]

上一段代码为无法实现页面显示数据增加的功能。

修改方法:



原因从脏检查机制开始说起。
脏检查机制:Angular将双向绑定转换为一堆watch表达式,然后递归这些表达式检查是否发生过变化,如果变了则执行相应的watcher函数(指view上的指令,如ng-bind,ng-show等或是{{}})。等到model中的值不再发生变化,也就不会再有watcher被触发,一个完整的digest循环就完成了。
脏检查机制的触发:Angular中在view上声明的事件指令,如:ng-click、ng-change等,会将浏览器的事件转发给$scope上相应的model的响应函数。等待相应函数改变model,紧接着触发脏检查机制刷新view。
所以,上文中的代码无法实现相应功能的原因就是缺乏触发Angular脏检查机制的条件,而手动添加了scope.$digest()使其执行了脏检查机制更新了view。
watch表达式:可以是一个函数、可以是$scope上的一个属性名,也可以是一个字符串形式的表达式。$watch函数所监听的对象叫做watch表达式。
watcher函数:指在view上的指令(ngBind,ngShow、ngHide等)以及{{}}表达式,他们所注册的函数。每一个watcher对象都包括:监听函数,上次变化的值,获取监听表达式的方法以及监听表达式,最后还包括是否需要使用深度对比(angular.equals())。
1
2
3
4
5
[/code]


脏检查机制(dirty-checking)是实现双向数据绑定的重要基础。

Angular中的$digest函数:当接受view上的事件指令转发的事件时,就会切换到Angular的上下文环境,来影响这类事件,$digest循环就会触发。
$digest函数的工作过程:
1
2
[/code]



遍历一遍所有的watcher函数就是一轮脏检查,执行完一轮之后,只要有watcher监听的值改变过,那么就会重新在进行一轮,直到所有的值都没有变化。从第一轮到所有数据稳定称为一个完整的$digest循环。当循环结束后,才把模型的变化结果更新到dom中去,防止频繁的dom操作。

我们已经知道什么时候以及怎么开始digest循环了,那么digest循环具体做了些什么?
  在digest循环中,AngularJS会遍历整个$watch列表,所有watcher都会被触发,当一个wathcer被触发时,AngularJS会检测Scope模型相应的数据,如果它发生了变化,那么关联到该watcher的回调函数就会被触发。
  如果执行了一次digest循环后某个值发生了变化,那么AngularJS会再次循环,直至不再有任何变化。这是因为你在$watch中更新某个值,如果该值对应的$watch已在这遍循环通过,AngularJS将检测不到变化无法更新。如果循环运行了10次或更多次,AngularJS会抛出异常并停止。(就算没有更新值,AngularJS也会多运行一次来确保没有改变,也就是至少运行两次)。
1
2
3
4
5
[/code]

以上就是Angular的数据双向绑定的原理。

最后附上官网说明:http://docs.ngnice.com/guide/scope
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: