Angular双向数据绑定

来源:互联网 发布:java jdk 64位 编辑:程序博客网 时间:2024/05/17 08:56

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

例1

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

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

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

单向数据绑定:

例2

数据模型–>视图 
El表达式中常见 ${变量名}以及{{}} ,它只提供从数据源到视图的单方向的数据展示。 
缺点:HTML代码一旦生成完以后,就没有办法再变了,如果有新的数据来了,那就必须把之前的HTML代码去掉,重新整合生成一次。

双向数据绑定:

例2

数据模型<==>视图 
用户在视图上的修改会自动同步到数据模型中去,同样的,如果数据模型中的值发生了变化,也会立刻同步到视图中去。 
缺点:双向数据绑定的应用场景非常有限。

3、双向数据绑定原理

带着问题看下面的代码。 
问题:绑定数据是怎么生效的? 
如图示例,当点击+1按钮时,显示的数据是否会正常的增加? 
如果会正常增加,说明原因。 
如果不会,说明原因并修改代码使其可以正常显示。

例3

<!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

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

例3

原因从脏检查机制开始说起。

脏检查机制: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

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

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

例3

遍历一遍所有的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

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

最后附上官网说明:http://docs.ngnice.com/guide/scope

原创粉丝点击