$scope是一个将视图(一个DOM元素)绑定到控制器的对象。在模型-视图-控制器结构中,$scope对象是模型。它提供了一个绑定到DOM元素(以及它的子元素)的执行上下文。
尽管听起来很复杂,$scope仅仅是一个JavaScript对象。控制器和视图都能获取$scopr因此它被用于两者之间的交流。$scope对象将包含我们想要在视图中运行的数据和函数,我们在下面会看到。
一个AngularJS应用拥有一个$rootScope。$rootScope是创建在包含ng-app指令的DOM元素上的最顶层作用域。
当$scope没有被显式设置时AngularJS将会自动创建$rootScope。这就是第一部分中的例子能够运行的原因。
在这个例子中,我们使用$rootScope.我们在min.'s中干的na'mename的作用域中添加一个属性。把这个函数放置在app.run函数中,我们可以保证它在应用的最前面运行。你可以将run函数看做Angular应用中的main函数。
app.run(function($rootScope){
$rootScope.name = "Ari Lerner";
});
现在,在视图的任何地方,我们都可以使用表达式/模板:{{ }}来引用这个属性,比如:
{{name}}
我们会在后面的文章中深入讨论AngularJS模板语法
运行结果:
Ari Lerner
总结:
- 任何绑定在$scope对象中的东西都能在视图中被获取
- 同样的,任何控制器对模型的改变都将在视图中显示
Wielder真正展示作用域的威力,现在我们创建一个绑定到DOM元素山高的控制器,它将为元素创建一个$scope并允许我们与之进行交互。
ng-controller
为了显式的创建一个$scope对象,我们使用ng-controller指令将一个控制器绑定到一个DOM元素之上,比如:
<div ng-controller="MyController">
{{ person.name }}
</div>
ng-controller为DOM元素创建了一个新的$scope对象并且将DOM对象嵌套在$scope中。在这个例子中,拥有ng-controller的div的父$scope是$rootScope对象。作用域链如下图所示:
现在,MyController设置了一个$scope,我们可以在DOM元素中的任何地方获取这个对象。在这个例子中,我们将在$scope中创建一个person对象,在main.js文件中国:
app.controller('MyController', function($scope) { $scope.person = { name: "Ari Lerner" }; });
现在我们可以在拥有ng-controller="MyController"的div元素的任意子元素中获取person对象,因为它在$scope中。
运行结果:
Ari Lerner
有一个例外,所有的作用域都是原型继承,这意味着他们可以进入父作用域。默认的,对于任何不能在本地作用域中获取的属性,AngularJS将会爬行到包含(父)作用域然后再那里查找属性或方法。如果AngularJS在那里找不到属性,他将会继续向上爬行直至$rootScope。
一个例外:有一些指令可以有选择的创建一个隔离作用域,它不会继承任何父作用域。
例如,我们现在有一个ParentController包含person对象,以及一个ChildController想要引用person对象:
app.controller('ParentController',function($scope){
$scope.person = {greeted:false};
});
app.controller('ChildController', function($scope) {
$scope.sayHello = function() {
$scope.person.greeted = true;
}
});
当我们将ParentController下面的ChildController绑定到视图中时,我么可以引用父作用域中的属性就好像它存在于ChildController中一样:
<div ng-controller="ParentController">
<div ng-controller="ChildController">
<input type="text" ng-model="person.name" placeholder="Name"></input>
<a ng-click="sayHello()">Say hello</a>
</div>
{{ person }}
</div>
整合myApp
现在让我们使用$scope的威力来创建我们的NPR 应用。我么在上一篇文章中定义应用的框架。现在,我们开始打破DOM结构并且创建我们的基础功能。
就像我们在上面例子中看到的一样,我们将创建一个叫做PlayerController的根控制器。我们的RelatedController将会负责跟踪我们的audio元素,并且处理NPR程序的列表。
现在我们来创建控制器,回到main.js:
var app = angular.module('myApp', []);
app.controller('PlayerController', ['$scope', function($scope) {
}]);
app.controller('RelatedController', ['$scope', function($scope) {
}]);
Audio
这些控制器现在没有多大作用,我们来创建一些在应用中播放的audio元素。在这个教程中,我们将使用HTML5的audio元素,因此请你确保使用兼容HTML5的浏览器(我们推荐Google Chrome)。
为了添加一个audio元素,我们可以将它添加到HTML中或者我们的控制器中。既然我们将要在控制器中整合audio元素,那么我们最好在控制器中创建。
在我们的PlayerController中,我们来创建一个audio元素。我们将它存储在我们的作用域中,正如你所知道的一样,这意味着我们将通过$scope对象链接视图和控制器.
app.controller('PlayerController', ['$scope', function($scope) {
$scope.audio = document.createElement('audio');
}]);
现在,这个设置有些无聊,因为它并没有什么作用。我们将在后面的部分中讲述如何“获取”数据,因此现在我们会强行添加一个.mp4地址。
在同一个PlayerController中,设置audio的src属性为我们想要获取的.mp4文件。在这里为了方便,我们使用一个我们拥有的NPR音频文件,但是我们可以指向任何地址。简单的将audio的源设置为音频文件的URL:
app.controller('PlayerController', ['$scope', function($scope) {
$scope.playing = false;
$scope.audio = document.createElement('audio');
$scope.audio.src = '/media/npr.mp4';
}]);
这个音频并不会播放,除非我们让它播放。我们可以简单的调用$scope.audio.play()方法,然后HTML5 audio元素将会开始播放MP4 流。
我们可以为用户提供一个互动元素,通过创建一个按钮在$scope中绑定一个动作。我们将在后面的章节中深入讨论,然而视图的HTML代码看起来是这样:
<div ng-controller="PlayerController">
<button ng-click="play()" class="button" ng-show="!playing">Play</button>
<button ng-click="stop()" class="button alert" ng-show="playing">Stop</button>
Playing audio: <b>{{ playing }}</b>
</div>
注意我们并不不要引用在作用域中创建的audio元素。这是因为控制器来使用document.createElement("audio")载入时创建了audio元素。注意我们将在教程的后面章节中重构这个组件。在控制器中操纵DOM元素不是一个好注意(感谢Brad Green为我们指出这点)。为了简单我们将在这里保持这个组件。
我们已经在视图中添加了一些变量,我们可以在$scopr中跟踪它们。我们在里面使用了一些即将在后面深入讨论的高级概念,因此不要担心没看懂!
app.controller('PlayerController', ['$scope', function($scope) {
$scope.playing = false;
$scope.audio = document.createElement('audio');
$scope.audio.src = '/media/npr.mp4';
$scope.play = function() {
$scope.audio.play();
$scope.playing = true;
};
$scope.stop = function() {
$scope.audio.pause();
$scope.playing = false;
};
$scope.audio.addEventListener('ended', function() {
$scope.$apply(function() {
$scope.stop()
});
});
}]);
到目前为止,我们已经介绍完了AngularJS中的$scope。在下一篇文章中,我们将讲述AngularJS中的数据绑定。