angularjs中的$watch

来源:互联网 发布:域名出售系统源码 编辑:程序博客网 时间:2024/04/28 15:55

在使用AngulaJS编写应用时,我们经常需要做的一件事情就是对模型中的变量进行监视,并对其发生的变化做出相应的回应。AngularJS为我们提供了一个非常方便的$watch方法,它可以帮助我们在每个scope中监视其中的变量。下面是一个非常简单的例子:

<html ng-app=’myApp’>
<head>
<meta charset=”UTF-8”>
<script src=’../lib/angular.js’></script>
</head>
<body>
<input ng-model=’name’ type=’text’/>
<div>change count: {{count}}</div>
<script>
angular.module(‘myApp’,[])
.run([‘rootScope,function(rootScope){
rootScope.count=0;rootScope.name = ‘hcc’;
rootScope.watch(‘name’,function(){
rootScope.count++;  
                                })  
                         }]);  
        </script>  
    </body>  
    </html>  
上面的代码很简单,它用
上面的代码很简单,它用watch来对rootScopenamerootScope中的count属性增加1。因此,每当我们对name进行一次修改时,下面显示的count数字就会增加1。

在AngularJS内部,每当我们对ng-model绑定的name属性进行一次修改,AngularJS内部的digest使watch来监视的东西,如果和进行上一次$digest之前相比有了变化,则执行我们在其中绑定的处理函数。

然而,我们在实际运用中常常不只是对一个原始类型的属性进行监视,还可能对集合进行监视,如果你还记得Javascript中的五种基本类型(number, boolean, null, undefined, string)。对于原始类型,如果我们使用了一个赋值操作,则这个原始类型变量会“真正的”被进行一次复制,然而对于引用类型,在进行赋值时,仅仅时将赋值的变量指向了这个引用类型。在AngularJS的watchrootScope,没有什么特别之处,然而如果要对一个引用类型,尤其是在实际运用中常见的对象数组进行监视时,情况就不一样了。我们来看下面的例子:

<html ng-app=’myApp’>
<head>
<meta charset=”UTF-8”>
<script src=’../lib/angular.js’></script>
</head>
<body>
<div hg-repeat=’item in items’>
<input ng-model=’item.a’/><span>{{item.a}}</span>
</div>
<div>change count: {{count}}</div>
<script>
angular.module(‘myApp’,[])
.run([‘rootScope,function(rootScope){
rootScope.count=0;rootScope.items = [
{ “a”: 1 },
{ “a”: 2 },
{ “a”: 3 },
{ “a”: 4 }
]
rootScope.watch(‘items’,function(){
rootScope.count++;  
                                })  
                         }]);  
        </script>  
    </body>  
    </html>  
通过运行上面的代码,我们发现count的值始终是1,难道没有检测到吗?其实
通过运行上面的代码,我们发现count的值始终是1,难道没有检测到吗?其实watch()还有第三个参数,默认是false,我们称这种监视叫做“引用监视”。即“reference watch”,它的意思是只要监视的对象引用没有发生变化,就不算它发生了变化。具体来说,在上面的例子中,只要是items的引用没有发生变化,就算items中的一些属性发生了变化,$watch也不与理会,那什么时候才能检测到这种属性变化呢?

如果我们将watchtrueequalitywatchwatch将会检测到。

既然“全等监视”那么功能那么好用,为什么不经常使用呢?那是因为它的性能问题,它在运行时需要先遍历整个监视对象,然后在每次$digest之前使用angular.copy()将整个对象深拷贝一遍然后在运行之后用angular.equal()将前后的对象进行对比,上面的例子中因为items比较简单,因此可能性能上不会有什么差别,但是到了实际生产时,我们要面对的数据千千万万,可能因为全等监视这一个设置就会消耗大量的资源。

除了上面提到的两种方式之外,在angular 1.1.4版本之后,添加了一个$watchCollection()方法来针对数组(也就是集合)进行监视,它的性能介于全等监视和引用监视二者之间,即它并不会对数组中每一项的属性进行监视,但是可以对数组的项目的增减做出反应。比如还是上面的例子:

                $rootScope.items = [                        { "a": 1 },                        { "a": 2 },                        { "a": 3 },                        { "a": 4 }                        ]                        $rootScope.$watchCollection('items',function()                            {                            $rootScope.count++;                        })                 }]);

对集合的操作,推荐使用这种方式。

0 0