angularjs中的$watch

在使用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来对$rootScope中的name进行监视,并在它发生变化的时候将$rootScope中的count属性增加1。因此,每当我们对name进行一次修改时,下面显示的count数字就会增加1。

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

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

<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,难道没有检测到吗?其实$watch()还有第三个参数,默认是false,我们称这种监视叫做“引用监视”。即“reference watch”,它的意思是只要监视的对象引用没有发生变化,就不算它发生了变化。具体来说,在上面的例子中,只要是items的引用没有发生变化,就算items中的一些属性发生了变化,$watch也不与理会,那什么时候才能检测到这种属性变化呢?

如果我们将$watch的第三个变量设置为true,那么此时我们进行的监视叫做“全等监视”,原词是“equality watch”。如果增加或者删除,$watch将会检测到。

既然“全等监视”那么功能那么好用,为什么不经常使用呢?那是因为它的性能问题,它在运行时需要先遍历整个监视对象,然后在每次$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++;
                            })
                     }]);

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

时间: 2024-08-04 21:47:41

angularjs中的$watch的相关文章

angularJs中关于ng-class的三种使用方式说明

在开发中我们通常会遇到一种需求:一个元素在不同的状态需要展现不同的样子. 而在这所谓的样子当然就是改变其css的属性,而实现能动态的改变其属性值,必然只能是更换其class属性 这里有三种方法: 第一种:通过数据的双向绑定(不推荐) 第二种:通过对象数组 第三种:通过key/value 下面简单说下这三种: 第一种:通过数据的双向绑定 实现方式: function changeClass(){   $scope.className = "change2"; } <div clas

AngularJs中的directives(指令)

一.指令的职责   指令的职责是修改DOM结构,并将作用域和DOM连接起来.即指令既要操作DOM,将作用域内的数据绑定到DOM节点上,又要为DOM绑定事件调用作用域内的对应的方法. 二.创建自定义指令 调用自定义指令的4种方式:元素.属性.样式类.注释. 常用的是前两种,实例如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title>

黄聪:AngularJS中的$resource使用与Restful资源交互(转)

原文:http://blog.csdn.net/he90227/article/details/50525836 1.AngularJS中的 $resource 这个服务可以创建一个资源对象,我们可以用它非常方便地同支持RESTful的服务端数据源进行交互,当同支持RESTful的数据模型一起工作时,它就派上用场了.      REST是Representational State Transfer(表征状态转移)的缩写,是服务器用来智能化地提供数据服务的一种方式 1)我们首先需要引入ng-Re

Spring Boot+AngularJS中因为跨域导致Session丢失

http://blog.csdn.net/dalangzhonghangxing/article/details/52446821 如果还在为跨域问题烦恼,请查看博主的 解决angular+spring boot的跨域问题 那篇文章. 博主在项目开发过程中,遇到了由于跨域而导致的Session丢失问题,非常的恶心,但是经过在网上查阅各种资料,发现解决方法十分简单. 在我们每一次的数据请求中,浏览器都会向后台发送一个JSession,后台会根据这个值自动查找Id为JSession的那个sessio

后端接收不到AngularJs中$http.post发送的数据的问题

1.问题: 后端接收不到AngularJs中$http.post发送的数据,总是显示为null 示例代码: $http.post(/admin/KeyValue/GetListByPage, { pageindex: 1, pagesize: 8 }) .success(function(){ alert("Mr靖"); }); 代码没有错,但是在后台却接收不到数据,这是为什么呢? 用火狐监控:参数是JSON格式 用谷歌监控:传参方式是request payload 可以发现传参方式是

Angularjs中的事件广播-浅谈$broadcast,$emit,$on

Angularjs中不同作用域之间可以通过组合使用$broadcast,$emit,$on的事件广播机制来进行通信 介绍: $broadcast的作用是将事件从父级作用域传播至子级作用域,包括自己.格式如下:$broadcast(eventName,args) $emit的作用是将事件从子级作用域传播至父级作用域,包括自己,直至根作用域.格式如下:$emit(eventName,args) $on用于在作用域中监控从子级或父级作用域中传播的事件以及相应的数据.格式如下:$on(event,dat

AngularJs中,如何在父元素中调用子元素为自定义Directive中定义的函数?

最近一段时间准备使用AngularJs中的自定义Directive重构一下代码. 在这里说明一下,把自定义控件封装成Directive并不一定是要复用,而是要让代码结构更加清晰.就好像你将一个长方法拆分成多个独立的小方法,也未必要复用它们一样.职责独立等一票好处,会让后期维护更加轻松. 在重构的过程中,我遇到了这样一个问题,先上图: 图一: 这就是我要重构的界面,由于之前时间紧,将这三个Filter和两个button都写在了一个页面中.当时我已经预感到,如果将这里面的状态都写到一个scope上,

Javacript和AngularJS中的Promises

promise是Javascript异步编程很好的解决方案.对于一个异步方法,执行一个回调函数. 比如页面调用google地图的api时就使用到了promise. function success(position){ var cords = position.coords; console.log(coords.latitude + coords.longitude); } function error(err){ console.warn(err.code+err.message) } na

AngularJS中实现Model缓存

在AngularJS中如何实现一个Model的缓存呢? 可以通过在Provider中返回一个构造函数,并在构造函数中设计一个缓存字段,在本篇末尾将引出这种做法. 一般来说,Model要赋值给Scope的某个变量. 有的直接把对象赋值给Scope变量:有的在Provider中返回一个对象再赋值给Scope变量:有的在Provider中返回一个构造函数再赋值给Scope变量.本篇来一一体验. 首先自定义一个directive,用来点击按钮改变一个scope变量值. angular .module('

通过几段代码,理清angularJS中的$injector、$rootScope和$scope的概念和关联关系

$injector.$rootScope和$scope是angularJS框架中比较重要的东西,理清它们之间的关系,对我们后续学习和理解angularJS框架都非常有用. 1.$injector其实是一个IOC容器,包含了很多服务(类似于spring框架中的bean),其它代码能够通过       $injector.get("serviceName")的方式,从injector中获取所需要的服务.详情参考这篇文章 2.scope是angularJS中的作用域(其实就是存储数据的地方)