AngularJS中$Scope作用域与控制器继承机制详解

作者:异步漫步时间:2026-10-30 08:31:37浏览:372

本文深入解析AngularJS中$Scope的作用域机制。通过对比单控制器与多控制器实例,阐明即使复用同一控制器,每个实例仍拥有独立作用域。文章进一步介绍利用$rootScope进行跨作用域通信的三种方法:$on、$emit和$broadcast,并演示控制器间的继承关系及数据共享实现。

Controller的创建与基础作用域

Controller的创建

AngularJS中的控制器应用非常广泛,下面通过一段简单的代码来演示控制器的创建过程。


<!DOCTYPE html>
<html xmlns="http://www.w.org//xhtml" ng-app="exampleApp">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-"/>
<title>App</title>
<script src="angular.js"></script>
<link href="bootstrap-theme.css" rel="stylesheet" />
<link href="bootstrap.css" rel="stylesheet" />
<script>
angular.module("exampleApp", [])
.controller("defaultCtrl", function ($scope) {
$scope.setInput = function (value) {
console.log("print:" + value);
}
});
</script>
</head>
<body ng-controller="defaultCtrl"> 
<div class="well">
<h>Count</h>
<div class="form-group">
<input class="form-control" required ng-model="value" />
<button ng-click="setInput(value)">Click</button>
</div>
</div>
</body>
</html> 

在这个示例中,控制器逻辑相对简单。首先,在HTML元素中添加了ng-app属性,用于定义AngularJS模块的作用范围。

接着,在body标签中添加了ng-controller属性,指定了defaultCtrl控制器的作用范围。

在input标签中使用ng-model指令进行数据绑定,实现了双向数据绑定(MVVM模式)。

$scope是AngularJS内置的作用域对象。

该实例的功能仅将输入的值打印到控制台,效果如图所示:

Controller的创建与基础作用域

整个过程非常直观,操作也很简单。

多控制器作用域隔离与$rootScope通信

多个控制器Controller的作用域问题

现在我们对程序进行改造,


<body >
<div class="well" ng-controller="defaultCtrl">
<h>Count</h>
<div class="form-group">
<input class="form-control" required ng-model="value" />
<button ng-click="setInput(value)">Click</button>
</div>
</div>
<div class="well" ng-controller="defaultCtrl">
<h>Count</h>
<div class="form-group">
<input class="form-control" required ng-model="value" />
<button ng-click="setInput(value)">Click</button>
</div>
</div>
</body> 

其余代码保持不变,只是将原本放置在body中的ng-controller属性移动到了两个独立的div中。这里复用了defaultCtrl控制器,不妨推测一下:如果在第一个input标签中输入内容,然后点击第二个控制器下的button按钮,会出现预期的结果吗?

Controller的创建与基础作用域

实际结果可能与预期不符,可以看到输出结果为undefined。这很容易解释,因为尽管复用了同一个控制器,但每次创建时都会生成不同的作用域,导致它们之间无法直接共享数据。

每次调用工厂函数都会返回不同的作用域实例。

那么,如何实现不同作用域之间的访问呢?在AngularJS中,可以通过$rootScope来实现跨作用域的数据访问。

在此需要介绍三个相关的方法:

$on(name, handler):注册一个事件处理函数,当当前作用域收到特定事件时调用该函数。

$emit(name, args):向当前父作用域发送一个事件,直至根作用域。

$broadcast(name, args):向当前作用域下的子作用域发送事件,参数包括事件名称以及一个用于向事件提供额外数据的对象。

现在来更改代码:


<script>
angular.module("exampleApp", [])
.controller("defaultCtrl", function ($scope,$rootScope) {
$scope.$on("UpdateValue", function (event, args) {
$scope.input = args.zip;
});
$scope.setInput = function (value) {
$rootScope.$broadcast("UpdateValue", { zip: value });
console.log("print:" + $scope.input);
}
$scope.copy = function () {
console.log("copy:" + $scope.input);
};
});
</script> 
<div class="well" ng-controller="defaultCtrl">
<h>Count</h>
<div class="form-group">
<input class="form-control" required ng-model="value" />
<button ng-click="copy()">Copy</button>
</div>
</div> 

在这段代码中,我添加了几个函数,同时修改了第二个控制器的逻辑。

运行结果:

Controller的创建与基础作用域

确实实现了预期的效果。

控制器继承机制

Controller继承


<script>
angular.module("exampleApp", [])
.controller("defaultCtrl", function ($scope, $rootScope) {
//$scope.$on("UpdateValue", function (event, args) {
// $scope.input = args.zip;
//});
$scope.setInput = function (value) {
//$rootScope.$broadcast("UpdateValue", { zip: value });
$scope.input = value;
console.log("print:" + $scope.input);
}
$scope.copy = function () {
console.log("copy:" + $scope.input);
};
})
.controller("simpleCtrl", function ($scope) {
$scope.copy = function () {
console.log("copy:" + $scope.input);
};
});
</script>
<body ng-controller="defaultCtrl">
<div class="well">
<h>Count</h>
<div class="form-group">
<input class="form-control" required ng-model="value" />
<button ng-click="setInput(value)">Click</button>
</div>
</div>
<div class="well" ng-controller="simpleCtrl">
<h>Count</h>
<div class="form-group">
<input class="form-control" required ng-model="value" />
<button ng-click="copy()">Copy</button>
</div>
</div>
</body> 

我添加了一个名为simpleCtrl的控制器。仔细观察可以发现,defaultCtrl包含了simpleCtrl,因此simpleCtrl也继承了相应的作用域特性。

结果图显示:当在第一个窗口中输入内容时,第二个窗口也随之变化,因为它们共享同一个value值。

Controller的创建与基础作用域

在使用Controller时,必须明确理解$scope作用域的问题,以避免潜在的数据隔离或共享错误。

作者最新文章