JavaScript框架之AngularJS学习——作用域与事件(上)

AngularJS学习——作用域与事件


JavaScript对象是基于key-value键值对的,我们可以把JavaScript对象作为一个map数据结构使用,而AngularJS作用域本质上就是一个普通的JavaScript对象。

AngularJS作用域对象和普通JavaScript对象一样,都可以在作用域对象中增加属性或者方法,不同的是我们不需要手动去构造作用域对象,当HTML页面中出现ng-app和ng-controller指令时,AngularJS框架会自动创建作用域对象,我们只需要将其注入即可。

AngularJS程序中作用域的主要功能是存放模型数据,在控制器中,我们可以修改作用域中的模型数据或在作用域中新增模型数据。

eg:

$scope.name = "chenxiaoming"      //在模型中新增模型数据
<!--在视图中展示模型数据-->
<p>{{name}}</p>    
每个AngularJS应用至少会有一个名称为$rootScope作用域,它是AngularJS应用的根作用域。

当页面中出现ng-app指令,启动AngularJS框架,并且自动创建一个根作用域对象$rootScope,接着使用ng-controller指令实例化控制器对象时,AngularJS框架会为我们创建一个子作用域$scope,默认该子作用域会继承$rootScope作用域的所有属性。($rootScope是所有作用域的父作用域,孤立作用域除外。)

eg:

<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
	<meta charset="UTF-8">
	<title>继承$rootScope</title>
	<script src="../lib/angular-1.6.5/angular.min.js"></script>
</head>
<body ng-init="name='chenxiaoming';age=18">
	<div ng-controller="myCtrl"></div>
	<script>
		angular.module("myApp",[])
			.controller("myCtrl", ["$scope", "$log", function($scope, $log){
				$log.info($scope.name);
				$log.info($scope.age);
			}])
	</script>
</body>
</html>

案例中通过ng-init指令在$rootScope作用域对象中新增了两个属性,即name和age。

接着使用ng-controller指令实例化myCtrl控制器,此时AngularJS会创建一个子作用域对象继承自$rootScope,可以在$scope中调用$rootScope中的属性。


作用域嵌套

eg:

<body ng-app="myApp">
	<div ng-controller="myFirstCtrl">
		<div ng-controller="mySecondCtrl"></div>
	</div>
</body>
作用域嵌套就类似案列中的结构一样,图解如下

继承图解


AngularJS作用域对象原型继承

AngularJS作用域对象继承采用构造方法原型链继承。(这个我还没有具体搞懂,搞懂之后慢慢在别的博客中详细说明)


AngularJS作用域高级特性

$rootScope.Scope

主要讲述几个方法,包括作用域属性监视、digest循环等。

1.$watch方法监视作用域

AngularJS为我们提供了一个非常方便的$watch()方法,可以帮助我们监视作用域中的属性的变。

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>模板</title>
	<script src="../lib/angular.min.js"></script>
</head>
<body ng-app="myApp">
	<input type="text" ng-model="name">
	<div>change count: {{ count }}</div>
	<script>
		angular.module("myApp",[])
			.run(["$rootScope",function($rootScope){
				$rootScope.count = 0;
				$rootScope.name = "chenxiaoming";
				$rootScope.$watch("name",function(){
					$rootScope.count ++;
				})
			}])
	</script>
</body>
</html>

$watch()方法对$rootScope中的name属性进行监视,并在它发生变化的时候将$rootScope中的count属性值增加1。

注意:以上$watch监视的内容是一个基本类型。AngularJS作用域对象的$watch方法中,对基本类型和应用类型的操作有所不同。

下面是引用类型的例子

eg:

<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
	<meta charset="UTF-8">
	<title>$watch引用类型</title>
	<script src="../lib/angular-1.6.5/angular.min.js"></script>
</head>
<body>
	<div ng-repeat="item in items">
		<input type="text" ng-model="item.value"> <span>{{item.value}}</span><br><br>
	</div>
	<div>change count: {{count}}</div>
	<script>
		var app = angular.module("myApp",[]);
		app.run(["$rootScope",function($rootScope){
			$rootScope.count = 0;
			$rootScope.items = [
				{"value" : 1},
				{"value" : 2},
				{"value" : 3},
				{"value" : 4},
				{"value" : 5},
			];
			$rootScope.$watch("items",function(){
				$rootScope.count ++;
			},false)
			//$watch中添加第三个参数true/false,默认的false引用监视,true是全等监视
		}])
	</script>
</body>
</html>
例子中,对input框中的内容进行修改,就会发现count的值始终不变。

$watch()方法的三个参数。第一个参数是要监视的属性,第二个参数是在监视属性发生变化时需要回调的方法。第三个参数就是对监视对象的类型进行设置。默认的是false,即引用监视(reference watch),监视的对象引用没有发生变化就不算变化。可修改值为true,即全等监视(equality watch),此时只要监视的属性发生变化,$watch就会执行相应的回调方法。

全等监视固然好,但是在运行时需要先遍历整个监视对象,然后在每次$digest之前使用angular.copy()将整个对象深复制一遍,然后在运行之后用angular.equal()将前后的对象进行对比。全等监视这一个设置消耗大量的资源,会让应用停止不前。实际使用当中,需要权衡。

angular1.1.4版本之后,新增一个$watchCollection()方法针对数组进行监视。性能介于全等监视和引用监视之间,即它并不会对数组中每一项的属性进行监视,但是可以对数组的项目增减做出反应。

2.作用域监视解除

$watch方法的发回值,该方法调用完毕后返回另一个方法,调用返回的方法即可解除作用域监视。

unbindWatcher()解除作用域监视。

eg:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>作用域监视解除</title>
	<script src="../lib/angular.min.js"></script>
</head>
<body ng-app="myApp">
	<input type="number" ng-model="num">
	<div>change count : {{ count }}</div>
	<script>
		angular.module("myApp",[])
			.run(["$rootScope",function($rootScope){
				$rootScope.num = 0;
				$rootScope.count = 100;
				var unbindWatcher = $rootScope
				.$watch("num",function(newValue,oldValue){
					if(newValue == 2){
						unbindWatcher();
					}else{
						$rootScope.count++;
					}
				});
			}])
	</script>
	<!-- 当文本值为2时,我们调用$watch()返回的方法unbindWatcher()解除了作用域监视,所以再次修改文本框内容是count值不再累加 -->
</body>
</html>
3.$apply方法与$digest循环

这两个是AngularJS中的核心概念。深入AngularJS双向数据绑定实现原理,就要理解这两个的概念。

eg:

	<input type="text" ng-model="name">
	<div>{{name}}</div>
上面所示,是一个简单的数据绑定,当input框中的数据改变,div中的AngularJS的表达式的{{name}}也会跟着改变。AngualrJS在实现双向数据绑定时,会在后台自动帮$scope中设置一个watcher,用来在数据发生变化的时候更新View。

即:

$scope.$watch("name",function(newValue, oldValue){
			//数据发生改变会跟新View
		});
AngularJS通过 $digest循环来触发watcher,从而知道name属性是否发生改变,调用相应的回调方法。$digest会周期性的运行来检查scope模型中的数据是否发生变化。

$digest循环中,watchers会被触发。当一个watcher被触发时,AngularJS会检测scope模型,如果他发生了变化,那么关联到该watcher的回调方法就会被调用。
$digest官网说明






以上笔记整理自个人学习,用做个人学习分享

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值