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:可选的布尔值命令检查被监控的对象的每个属性是否发生变化
示例代码
<!DOCTYPE html>
<html lang="en" ng-app="scopeApp">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="/lib/angular/angular.js"></script>
<script type="text/javascript">
var scopeApp = angular.module("scopeApp",[]);
scopeApp.controller("scopeController",function ($scope,$log) {
$scope.changeNum = 0;
$scope.$watch('userName',function (newValue,oldValue) {
++$scope.changeNum;
console.log("newValue:" + newValue + " " + "oldValue:" + oldValue + " " + "changeNum:" + $scope.changeNum);
});
});
</script>
</head>
<body >
<div ng-controller="scopeController">
<input ng-model="userName" type="text">
<span>改变次数:{{changeNum}}</span>
</div>
</body>
</html>
控制台输出
newValue:undefined oldValue:undefined changeNum:1
newValue:2 oldValue:undefined changeNum:2
newValue:23 oldValue:2 changeNum:3
newValue:231 oldValue:23 changeNum:4
newValue: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:1
newValue:2 oldValue:undefined changeNum:2
newValue:22 oldValue:2 changeNum:3
$apply
与$digest
在AngularJS作用域中的数据发生变化时,会自动触发apply来触发
$digest`。
示例代码,就是书中的代码,使用setTimeout的JS触发,可以发现控制台输出了改变的值,但是视图中没有改变
<!DOCTYPE html>
<html lang="en" ng-app="scopeApp">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="/lib/angular/angular.js"></script>
<script type="text/javascript">
var scopeApp = angular.module("scopeApp",[]);
scopeApp.controller("scopeController",function ($scope,$log) {
$scope.userName = '初始姓名';
console.log("姓名" + $scope.userName);
$scope.clickTest = function () {
// js 延时触发
setTimeout(function () {
$scope.userName = '改变姓名';
console.log("改变姓名" + $scope.userName);
},1000);
}
});
</script>
</head>
<body >
<div ng-controller="scopeController">
<input value="点击测试" type="button" ng-click="clickTest()"><br/>
<span>姓名:{{userName}}</span>
</div>
</body>
</html>
代码修改一下,能成功触发
$scope.clickTest = function () {
// js 延时触发
setTimeout(function () {
// 使用apply手工触发digest
$scope.$apply(function () {
$scope.userName = '改变姓名';
console.log("改变姓名" + $scope.userName);
});
},1000);
}
$timeout
与$interval
服务介绍
JavaScript的setTimeout()
方法达到延迟执行某个方法的效果。还有一个的方法setInterval()
,作用是每隔一段时间调用一次方法。两个方法都需要我们手动调用$apply()
方法来触发$digest
循环。
,AngularJS中有对应的$timeout
和$interval
,不需要我们手动调用digest循环。