AngularJS作用域:提供了在一个模型中表示的数据,把AngularJS应用程序的其他组件,模块,服务和模板都绑定在一起
1.了解作用域
一个应用程序的数据模型(结合视图,业务逻辑,服务器端数据)
1.1.根作用域和应用程序之间的关系
应用程序启动,根作用域创建。($rootScope将数据储存在应用层)
在run()块初始化(也可在模块组件中访问)。
angular.module('myApp',[]).run(function($rootScope){
$rootScope.rootValue=5;
})
.controller('myController',function($scope,$rootScope){
$scope.value=10;
$scope.difference=function(){
return $rootScope.rootValue-$scope.value;
}
})
1.2.作用域和控制器之间的关系
控制器:扩大作用域来提供业务逻辑。(Model对象上的controller()方法创建:把控制器注册为模块中的提供器,实例的创建发生在ng-controller指令被链接到AngularJS模板)
angular.module('myApp',[]).
value('start',200).controller('Counter',['$scope','start',function($scope,startingValue){
//新子作用域创建,$scope访问,start提供器被注入到控制器,作为startingValue被传递到控制器函数
}])
控制器负责连接到该作用域内的任何业务逻辑。意味着处理对作用域的更新更改,操作作用域值,发出基于该作用域的状态的事件
实现依赖注入的控制器,初始化值,inc(),dec(),calcDiff() 实现基本逻辑
var myModule = angular.module('myApp', []);
myModule.value('start', 200);
myModule.controller('Couter', ['$scope', start, function($scope, start) {
$scope.start = start;
$scope.current = start;
$scope.difference = 0;
$scope.change = 1;
$scope.inc = function() {
$scope.current += $scope.change;
$scope.calcDiff();
};
$scope.dec = function() {
$scope.current -= $scope.change;
$scope.calcDiff();
}
$scope.calcDiff = function() {
$scope.difference = $scope.current - $scope.start;
};
}])
1.3.作用域和模板之间的关系
模板为AngularJS应用程序提供视图。(HTML元素使用ng-controller属性被定义为控制器)(控制器的HTML元素及子元素内部,控制器可用于表达式和其他AngularJS功能)
在一个作用域中的值可以用 ng-model 指令链接到模板的 <input> <select> <textarea> 元素的值中(当用户改变输入元素的值时,作用域被自动更新)
<input type="number" ng-model="valueA">
{{expression}}:把作用的属性 函数 添加到表达式
<span ng-click="addValues(valueA,valueB)">Add Values{{valueA}}&{{valueB}}</span>
ng-click指令把浏览器单击事件绑定到作用域中:addValues()函数 addValues()函数中,不是必须的 ng-click和其他的AngularJS指令会自动对表达式求值。
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<title>scope_template</title>
<link rel="stylesheet" href="bootstrap.css">
</head>
<body>
<div class="panel panel-primary">
<div class="panel-heading">cal with sums(AngularJS)</div>
<div class="panel-body">
<div class="row">
<div class="col-md-12">
<form class="form-horizontal" role="form" ng-controller="SimpleTemplate">
<div class="form-group">
<label class="col-md-2 control-label">ValueA:</label>
<div class="col-md-10">
<input class="form-control" type="number" ng-model="valueA">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">ValueB:</label>
<div class="col-md-10">
<input class="form-control" type="number" ng-model="valueB">
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button class="btn btn-primary" ng-click="addValues(valueA,valueB)">click to add value</button>
<button class="btn btn-primary" ng-click="clearValues(valueA,valueB)">click to clear value</button>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">ValueB:</label>
<label class="col-md-10 control-label" style="text-align: left">{{valueC}}</label>
</div>
</form>
</div>
</div>
</div>
</div>
<script src="angular-1.3.0.js"></script>
<script type="text/javascript">
angular.module('myApp',[]).controller('SimpleTemplate', function($scope){
$scope.valueA=10;
$scope.valueB=20;
$scope.valueC=30;
$scope.addValues=function(v1,v2){
var v=angular.$rootScope;
$scope.valueC=v1+v2;
}
$scope.clearValues=function(v1,v2){
$scope.valueA=0;
$scope.valueB=0;
// v1=0;
// v2=0;
}
})
</script>
</body>
</html>
(基本Angular模板,实现控制器 把多个字段链接到作用域 提供值并显示结果(CSS用bootstrap))
1.4.作用域和后端服务器数据之间的关系
用于AngularJS的数据 往往是后端数据源(如数据库)。
- 经 由 AngularJS服务 来访来自数据库或其他后端资源的数据(包括读取 更新数据)
- 确保从 数据库读出的数据 对 作用域 更新(又更新了视图),避免直接从数据库中操作HTML值 (可能会导致作用域与视图不同步)
- 把对 数据库或其他后端源 所做的更改 反映到作用域。可以先更新作用域,然后用一个服务对数据库进行更新 执行此操作。也可以先更新数据库,然后用来自数据库的结果在作用域内重新填充适当的值。
1.5.作用域的生命周期
作用域的数据经过:
1.创建
2.监听器注册
3.模型变化
4.变化观察
5.作用域销毁
创建阶段:一个作用域初始化时,创建阶段产生。启动应用程序会创建根作用域(ng-controller or ng-repeat)创建子作用域模板
$scope.$digest() digest循环与浏览器事件循环互动。把对模型的更改更新到DOM元素,执行任何已注册的监听函数。
监听注册器阶段:为作用域中的值注册监视函数。监视器自动将模型的更改传播到DOM元素
$.scope.watchedItem='myItem';
$scope.counter=0;
$scope.$watch('name',function(newValue,oldValue){
$scope.watchedItem=$scope.counter+1;
})
模型变化阶段:发生在作用域内的数据变化时。AngularJS代码进行更改时,名为$apply()的作用域函数更新模型,调用$digest()函数更新DOM和监听器(或由$http,$timeout和$interval服务所做的更改自动在DOM中更新)
变化观察阶段:$digest()方法被digest循环,$apply()调用或手动执行,变化观察发生。会对所有用于更改的监听器求值。发生变化,$digest调用$watch监听器更新DOM
作用域销毁阶段:$destroy()从浏览器内存中删除作用域。停止$digest()调用并删除监听器。
2.实现作用域层次结构
作用域特点:被组织成层次结构。
保持作用域条理,将它们与所代表的视图上下文联系起来($digest()方法用作用域层次来为适当的监听器和DOM元素传播作用域的变更)
兄弟关系作用域:
<div ng-controller="controllerA"></div>
<div ng-controller="controllerB"></div>
父子作用域:(controllerA是controllerB的父)
<div ng-controller="controllerA">
<div ng-controller="controllerB"></div>
</div>
可以从一个控制器访问父作用域的值,但不能访问它的兄弟或子作用域的值。(父元素作用域改变,子控制器中的DOM值改变)
实现基本作用域:访问层次结构每个级别的属性
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<title>AngularJS Scope Hierarchy</title>
</head>
<body>
<div ng-controller="LevelA">
<h3>{{title}}</h3>
ValueA={{valueA}}
<input type="button" ng-click="inc()" value="+" />
<div ng-controller="LevelB">
<hr>
<h3>{{title}}</h3>
ValueA={{valueA}}<br/>
ValueB={{valueB}}
<input type="button" ng-click="inc()" value="+">
<div ng-controller="LevelC">
<h3>{{title}}</h3>
ValueA={{valueA}}<br/>
ValueB={{valueB}}<br/>
ValueC={{valueC}}
<input type="button" ng-click="inc()" value="+">
</div>
</div>
</div>
<script type="text/javascript" src="angular-1.3.0.js"></script>
<script type="text/javascript" src="scope_hierarchy.js"></script>
</body>
</html>
实现控制器的层次结构并呈现作用域的多个层次的结果
angular.module('myApp', []).
controller('LevelA',function($scope){
$scope.title="Level A";
$scope.valueA=1;
$scope.inc=function(){
$scope.valueA++;
}
}).
controller('LevelB',function($scope){
$scope.title="Level B";
$scope.valueB=1;
$scope.inc=function(){
$scope.valueB++;
}
}).
controller('LevelC',function($scope){
$scope.title="Level B";
$scope.valueC=1;
$scope.inc=function(){
$scope.valueC++;
}
});
3.发出和广播活动
作用域特点:具有在作用域层次结构内发出和广播事件的能力。
$emit():沿着父作用域层次向上发送一个事件。任何已注册该事件的祖先作用域都会收到通知
$broadcast():把一个事件广播给下方的子作用域层次。任何已注册该事件的后代作用域都会收到通知
$on():处理发出或者广播的事件。scope.$on(name,listener)
在层次结构中实现$emit() $broadcast()事件
var myModule=angular.module('myApp', []);
myModule.controller('Characters', function($scope){
$scope.names=['Frodo','Aragorn','Legolas','Gimli'];
$scope.currentName=$scope.names[0];
$scope.changeName=function(){
$scope.currentName=this.name;
$scope.$broadcast('CharacterChanged', this.name);
};
$scope.$on('CharacterDeleted', function(event,removeName){
var i=$scope.names.indexOf(removeName);
$scope.names.splice(i,1);
$scope.currentName=$scope.names[0];
$scope.$broadcast('CharacterChanged', $scope.currentName);
});
})
myModule.controller('Character', function($scope){
$scope.info={
'Frodo':{weapon:'Sting',race:'Hobbit'},
'Aragorn':{weapon:'Sword',race:'Man'},
'Legolas':{weapon:'Bow',race:'Elf'},
'Gimli':{weapon:'Axe',race:'Dwarf'}
};
$scope.currentInfo=$scope.info['Frodo'];
$scope.$on('CharacterChanged', function(event,newCharacter){
$scope.currentInfo=$scope.info[newCharacter];
});
$scope.deleteChar=function(){
console.log("delete char")
delete $scope.info[$scope.currentName];
$scope.$emit('CharacterDeleted',$scope.currentName);
};
})
控制器的作用域层次结构
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<title>scope events</title>
<style type="text/css">
div {padding: 5px;font: 18px bold;}
span {padding: 3px;margin: 12px;border: 5px ridge;cursor: pointer;}
label {padding: 2px;margin: 5px;font: 15px bold;}
p {padding-left: 22px;margin: 5px;}
</style>
<link rel="stylesheet" type="text/css" href="bootstrap.css">
</head>
<body>
<div ng-controller="Characters" class="panel panel-primary">
<div class="panel-body">
<button ng-repeat="name in names" ng-click="changeName()" class="btn btn-primary">{{name}}</button>
<div ng-controller="Character">
<hr>
<label>Name:</label>
<p>{{currentName}}</p>
<label>Race:</label>
<p>{{currentInfo.race}}</p>
<label>Weapon:</label>
<p>{{currentInfo.weapon}}</p>
<button ng-click="deleteChar()">delete</button>
</div>
</div>
</div>
</body>
<script type="text/javascript" src="angular-1.3.0.js"></script>
<script type="text/javascript" src="scope_events.js"></script>
</html>
使用$broadcast() $emit()发送更改 通过作用域层次删除事件
作用域与模板视图,控制器,模块和服务有直接关系。作用域也可作为数据库或其他服务器端数据源的代表。
作用域的生命周期被链接到浏览器的事件循环中