参考资料:
慕课网:Angular 实战
《Angular 权威指南》
一切基于模块
在 Angular 应用中,一切都是基于模块的:控制器、服务、指令、过滤器、配置。这些都是基于模块来实现的,因此,在创建 Angular 时,首先应该创建一个模块。
var app = angular.module("myApp",[])
然后,你需要在某个 HTML 元素上应用 ng-app
指令,表示这块区域归 Angular 管了。
Document
之后的一切东西,都基于模块创建。我们来看下模块 app
中有哪些属性和方法:
console.log(app)
animation:ƒ (recipeName, factoryFunction)
component:ƒ (recipeName, factoryFunction)
config:ƒ ()
constant:ƒ ()
controller:ƒ (recipeName, factoryFunction)
decorator:ƒ (recipeName, factoryFunction)
directive:ƒ (recipeName, factoryFunction)
factory:ƒ (recipeName, factoryFunction)
filter:ƒ (recipeName, factoryFunction)
name:"myApp"
provider:ƒ (recipeName, factoryFunction)
requires:[]
run:ƒ (block)
service:ƒ (recipeName, factoryFunction)
value:ƒ ()
_configBlocks:[]
_invokeQueue:[Array(3)]
_runBlocks:[]
app
对象中提供了我们构建 Angular 项目中一些必要元素的方法,我们要创建一些东西,就需要调用这些方法:
-
controller
:创建一个控制器 -
filter
:创建一个过滤器 -
service
:创建一个 Service -
run
:初始化全局数据,因此仅对$rootScope
其作用 - ...
这里有一张图片来描述一切基于模块:
应用控制器
ng-app
指令用来在页面的一块区域上应用某个模块,在这个模块中,如果有一部分视图需要应用控制器,就需要使用 ng-controller
指令:
...
{{str}}
...
控制器通过 $scope
对象连接视图:
var app = angular.module("myApp",[])
app.controller("TestController",function($scope){
$scope.str = "Hello Angular"
})
控制器嵌套
控制器是可以嵌套的,在 $scope
中查找属性或方法时,会沿着 $scope
链一直向上寻找,直到 $rootScope
。
controller.js:
var app = angular.module("myApp",[])
app.controller("ParentScope",function($scope){
$scope.str = "Hello Angular"
})
.controller("ChildScope",function($scope){
console.log($scope.str) // "Hello Angular"
})
index.html:
Document
{{str}}
$scope 基于原型继承
上面我们创建了嵌套的控制器,在创建 ParentController
时,会为该控制器创建一个作用域对象,该对象以其外层的 $scope
对象为原型,由于 ParentController
之外没有控制器了,因此和 ParentController
控制器绑定的 $scope
会以 $rootScope
作为原型。同理,ChildController
控制器相关联的 $scope
以和 ParentController
相关联的 $scope
对象作为原型。
因为原型继承的遮罩效应,当父控制器的 $scope
对象中属性发生变化是,会影响到引用该属性的子控制器,但如果为子控制器中的同名属性重新赋值(或者说改变其值)时,不会影响到父控制器中的相关属性。
不要复用控制器
如果多个控制器之间都有相同的功能,我们可能想到将这些功能抽取到一个公共的父类控制器中,子控制器复用父控制器中的方法。但在 Angular 中不推荐这样做,Angular 推荐将公共功能抽取成服务,而不要复用控制器,控制器应该是细粒度的,只专注于某一块视图。代码复用不是控制器的职责。
使用控制器的其他注意点
除了不要使用控制器复用代码以外,还有以下几个注意点:
- 不要在控制器中操作 DOM,DOM 操作应该放在指令中
- 不要在控制器中做过滤操作,过滤操作应该使用 Angular 的
$filter
服务 - 一般来说,控制器之间是不会相互调用的,控制器之间应该通过事件来通信
完。