AngularJs作用域高级特性,作用域属性监视、digest循环等
基于AngularJS入门与进阶(江荣波 著)这本书的笔记
AngularJS 1.x的demo
AngularJS1.x和Angular2,4,5是不一样的两个东西,构建方式,语法,都很多不同
$watch方法监视作用域
在传统的JavaScript中如果要监视一个方法是比较繁琐的事情,不过在AngularJs中可以使用$watch 对对像进行手工监视,让对像发生变化的时候触发
$watch(watchFn,watchAction,deepWatch)
- watchFn:angular表达式或函数的字符串
- watchAction(newValue,oldValue,scope):watchFn发生变化会被调用
- deepWatch:可选的布尔值命令检查被监控的对象的每个属性是否发生变化
示例代码
Title
改变次数:{{changeNum}}
控制台输出
newValue:undefined oldValue:undefined changeNum:1newValue:2 oldValue:undefined changeNum:2newValue:23 oldValue:2 changeNum:3newValue:231 oldValue:23 changeNum:4newValue:2314 oldValue:231 changeNum:5
从控制台输出可以看出,才进去的时候新的值和旧的值都是未定义,改变次数为1,当在文本框录入一次值后,新的值变为2,旧值是未定义,改变次数为2,再次输入新值变为23,旧值变为2,改变次数为3。通过这个方法我们能很简便的监控某些特定的值或者字段。
需要注意的是,示例代码中$watch只用了两个参数,如果不定义第三个参数,默认为false,不会监控引用数据类型例如数组等类型的变化。如果需要监控引用数据类型,需要显式定义为true,就可以实现监控。
在angular 1.1.4版本之后,新增加了一个$watchCollection()方法来针对数组(也就是集合)进行监视,它的性能介于全等监视和引用监视之间,即它并不会对数组中每一项的属性进行监视,但是可以对数组的项目增减做出反应。
对于多个变量的监视变化,执行同一函数的话,可以将这几个变量转为字符串,以‘+’号隔开来进行监视
$scope.$watch('count + page',function(){...});
作用域监视解除
如果在某种特定的条件下需要解除监视,可以调用unbindWatcher();方法
var scopeApp = angular.module("scopeApp",[]); scopeApp.controller("scopeController",function ($scope,$log) { $scope.changeNum = 0; // $watch 回调函数可以解除监视 var unbindWatcher = $scope.$watch('userName',function (newValue,oldValue) { ++$scope.changeNum; console.log("newValue:" + newValue + " " + "oldValue:" + oldValue + " " + "changeNum:" + $scope.changeNum); if($scope.changeNum == 3){ unbindWatcher(); } }); });
示例代码样式在改变次数到3后,就不会再出发watch方法了
newValue:undefined oldValue:undefined changeNum:1newValue:2 oldValue:undefined changeNum:2newValue:22 oldValue:2 changeNum:3
$apply与$digest
在AngularJS作用域中的数据发生变化时,会自动触发$digest循环,从而达到自动更新视图,实现数据的双向绑定。不过如果我们在angularjs中使用了原生的javascript改变了作用域中的值,是不会更新视图的,这个时候就需要手动调用 $apply来触发 $digest。
示例代码,就是书中的代码,使用setTimeout的JS触发,可以发现控制台输出了改变的值,但是视图中没有改变
Title
姓名:{{userName}}
![2d8c7d50c1c1554481ecdb4736cc662e.png](https://i-blog.csdnimg.cn/blog_migrate/3c21e5b28ff035552718c8c0e770f6af.jpeg)
代码修改一下,能成功触发
$scope.clickTest = function () { // js 延时触发 setTimeout(function () { // 使用apply手工触发digest $scope.$apply(function () { $scope.userName = '改变姓名'; console.log("改变姓名" + $scope.userName); }); },1000); }
![c3ab220f13de12ccb124febfb15a8f90.png](https://i-blog.csdnimg.cn/blog_migrate/044326cd8bdb249685223941575bc3b7.jpeg)
$timeout与$interval服务介绍
JavaScript的`setTimeout()`方法达到延迟执行某个方法的效果。还有一个的方法`setInterval()`,作用是每隔一段时间调用一次方法。两个方法都需要我们手动调用`$apply()`方法来触发`$digest`循环。
AngularJS中有对应的`$timeout`和`$interval`,不需要我们手动调用$apply()方法触发$digest循环。