zl程序教程

您现在的位置是:首页 >  .Net

当前栏目

5.把作用域实现为数据模型

2023-02-18 16:29:38 时间

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()发送更改 通过作用域层次删除事件

 

作用域与模板视图,控制器,模块和服务有直接关系。作用域也可作为数据库或其他服务器端数据源的代表。

作用域的生命周期被链接到浏览器的事件循环中