AngularJS控制器详情

前言

为了对AngularJS的控制器了解更深,本次进行详细的测试。

AngularJS控制器基本使用

首先, 定义一个控制器:
controller("XXName", function(……){});
然后绑定到HTML元素中去。这样,在该Controller中定义的值和方法,就可以在此HTML元素中使用。
控制器的作用域是$scope,该变量是一个普通的Json对象。 里面可以定义属性或者方法。在$scope中定义的变量和方法,只能在该controller中使用。
如果要使用全局的作用域,可以使用$rootScope,但是一般情况,尽量避免使用全局作用域。
Controller的定义方法,可以通过另外一种显式的DI注入:
xxx.controller("xxxName",["$scope","$rootScope",function($scope,$rootScope){……}   ]);

AngularJS控制器复用

Controller可以复用。同一个Controller可以在不同的元素中定义。
但是需要注意的是,每个Controller对应的控制域是不同的。也即$scope是独立的,都是继承于$rootScope。但是各自为政,互不干扰。

AngularJS控制器继承

控制器具有继承关系,默认所有的控制器中的$scope继承于$rootScope。继承的关系是$scope可以使用一切在$rootScope中的属性和方法,反过来就不行。
不过在,子Scope与父scope中,子scope可以覆盖父scope的属性。继承关系如下图:

见下面例子:
<!DOCTYPE html>
<html ng-app="exampleApp">
<head>
	<meta charset="utf-8">
    <title>控制器</title>
    <script src="angular.js"></script>
    <link href="bootstrap.css" rel="stylesheet" />
    <link href="bootstrap-theme.css" rel="stylesheet" />
	<script>
		var app = angular.module("exampleApp", []);

		app.controller("parentCtrl", function ($scope) {

			$scope.data = "Hello, Kobe";	//初始值

			$scope.reverseText = function () {
				$scope.data = $scope.data.split("").reverse().join("");		//将数据分割反转再放进一个数组中
			}

			$scope.changeCase = function () {
				var result = [];
				angular.forEach($scope.data.split(""), function (char, index) {
					result.push(index % 2 == 1
						? char.toString().toUpperCase() : char.toString().toLowerCase());
				});
				$scope.data = result.join("");		//将奇数字母转小写,偶数字母转大写
			};
		});

		app.controller("firstChildCtrl", function ($scope) {

			$scope.changeCase = function () {
			   $scope.data = $scope.data.toUpperCase();		//将值转为大写
			};
		});

		app.controller("secondChildCtrl", function ($scope) {

			$scope.changeCase = function () {
			   $scope.data = $scope.data.toLowerCase();		//将值转为小写
			};

			$scope.shiftFour = function () {
				var result = [];
				angular.forEach($scope.data.split(""), function (char, index) {
					result.push(index < 4 ? char.toUpperCase() : char);
				});
				$scope.data = result.join("");		//将前4字母转为大写,后面的不变
			}
		});
	</script>
</head>
<body ng-controller="parentCtrl">

    <div class="well">
        <h4>Parent Controller</h4>
        <div class="input-group">
            <span class="input-group-btn">
                <button class="btn btn-default" type="button" 
                        ng-click="reverseText()">Reverse</button>
                <button class="btn btn-default" type="button"
                        ng-click="changeCase()">Case</button>
            </span>
            <input class="form-control" ng-model="data">
        </div>
    </div>

    <div class="well" ng-controller="firstChildCtrl">
        <h4>First Child Controller</h4>
        <div class="input-group">
            <span class="input-group-btn">
                <button class="btn btn-default" type="button"
                        ng-click="reverseText()">Reverse</button>
                <button class="btn btn-default" type="button"
                        ng-click="changeCase()">Case</button>
            </span>
            <input class="form-control" ng-model="data">
        </div>
    </div>    

    <div class="well" ng-controller="secondChildCtrl">
        <h4>Second Child Controller</h4>
        <div class="input-group">
            <span class="input-group-btn">
                <button class="btn btn-default" type="button"
                        ng-click="reverseText()">Reverse</button>
                <button class="btn btn-default" type="button"
                        ng-click="changeCase()">Case</button>
                <button class="btn btn-default" type="button"
                        ng-click="shiftFour()">Shift</button>
            </span>
            <input class="form-control" ng-model="data">
        </div>
    </div>    
</body>
</html>




效果:

AngularJS控制器 as 别名

angular在view上的绑定都必须使用直接的scope对象,对于controller来说我们也得必须注入$scope这个service。 angular从1.2版本开始带来了新语法Controller as。如下:
<!DOCTYPE html>
<html ng-app="exampleApp" >
<head>
	<meta charset="utf-8"> 
    <title>as别名</title>
    <link href="bootstrap.css" rel="stylesheet" />
    <link href="bootstrap-theme.css" rel="stylesheet" />
    <script src="angular.js"></script>
    <script>
        var myApp = angular.module("exampleApp", []);
        myApp.controller("dayCtrl", function () {
            this.day = new Date();
        });
    </script>

</head>
<body >
    <div class="panel" ng-controller="dayCtrl as dc">
        <div class="page-header">
            <h3>AngularJS as 测试</h3>
        </div>
        <h4>Now is {{dc.day | date:"yyyy-MM-dd HH:mm:ss"}}</h4>
    </div>
</body>
</html>
效果:
其实controller的as语法,只是利用了$scope属性。将as后面的别名作为$scope中的对象。Angularjs源码实现如下:
if (directive.controllerAs) {
    locals.$scope[directive.controllerAs] = controllerInstance;
}  
由此可以看到,controlleras只是$scope对象中的属性。因此,可以通过{{controllerAs.xxx}}访问到controllerInstance中的属性。

AngularJS中的事件传播机制

AngularJS中的作用域有一个非常有层次和嵌套分明的结构。其中它们都有一个主要的$rootScope(也就说对应的Angular应用或者ng-app),然后其他所有的作用域部分都是继承自这个$rootScope的,或者说都是嵌套在主作用域下面的。
那么在作用域之间如何通信呢?其中一个选择就是在应用程序作用域之中创建一个单例服务,然后通过这个服务处理所有子作用域的通信。
在AngularJS中还有另外一个选择:通过作用域中的事件处理通信。不过有所限制,例如,你并不能广泛的将事件传播到所有监控的作用域中。你必须选择是否与父级作用域或者子作用域通信。
$on、$emit和$broadcast使得event、data在controller之间的传递变的简单,关系如下:
  • $emit只能向parent controller传递event与data 
  • $broadcast只能向child controller传递event与data $on用于接收event与data
  • $emit和$broadcast可以传多个参数,$on也可以接收多个参数
例子如下:
<!DOCTYPE html>
<html ng-app="exampleApp">
<head>
    <meta charset="utf-8">
    <title>App Event Test</title>
    <script src="angular.js"></script>
    <link href="bootstrap.css" rel="stylesheet" />
    <link href="bootstrap-theme.css" rel="stylesheet" />
    <script>
        var app =angular.module("exampleApp", []);
		app.controller('SelfCtrl', function($scope) {
			$scope.click = function () {
				$scope.$broadcast('to-child', 'child');
				$scope.$emit('to-parent', 'parent');
			}
		});

		app.controller('ParentCtrl', function($scope) {
			$scope.$on('to-parent', function(event,data) {
				console.log('ParentCtrl', data);       //父级能得到值
			});

			$scope.$on('to-child', function(event,data) {
				console.log('ParentCtrl', data);       //子级得不到值
			});

		});

		app.controller('ChildCtrl', function($scope){
			$scope.$on('to-child', function(event,data) {
				console.log('ChildCtrl', data);         //子级能得到值
			});
			$scope.$on('to-parent', function(event,data) {
				console.log('ChildCtrl', data);         //父级得不到值
			});

		});

		app.controller('BroCtrl', function($scope){ 
			$scope.$on('to-parent', function(event,data) { 
				console.log('BroCtrl', data);          //平级得不到值 
			}); 

			$scope.$on('to-child', function(event,data) { 
				console.log('BroCtrl', data);          //平级得不到值 
			}); 
		});	    
    </script>
</head>
<body >
	<div ng-controller="ParentCtrl">                <!--父级-->
		<div ng-controller="SelfCtrl">              <!--自己-->
			<button type="button" class="btn btn-default" ng-click="click()">click me</button>
			<div ng-controller="ChildCtrl"></div>   <!--子级-->
		</div>
		<div ng-controller="BroCtrl"></div>         <!--平级-->
	</div>
	<br>
</body>
</html>
效果:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值