controller - acelan86/angular GitHub Wiki
从一段常见的代码入手: html:
<html ng-app>
<head>
<script src="angular.js"></script>
<script src="controllers.js"></script>
</head>
<body>
<div ng-controller='HelloController'>
<p>{{greeting.text}}, World</p>
</div>
</body>
</html>
controller.js
function HelloController($scope) {
$scope.greeting = { text: 'Hello' };
}
anguler启动后,会调用helloController作为初始controller,那么它是怎么做的:
//$ControllerProvider
function $ControllerProvider() {
var controllers = {}; //存储当前注册的controller
/*
* 注册controller,这个方法在通过module.controller('name', function () {})声明一个controller的时候调用
* 将controller写入controllers对象中
*/
this.register = function(name, constructor) {
if (isObject(name)) {
extend(controllers, name)
} else {
controllers[name] = constructor;
}
};
/*
* provider的$get方法,用来获取它提供的实际controller
*/
this.$get = ['$injector', '$window', function($injector, $window) {
//重点在这里
return function(constructor, locals) {
if(isString(constructor)) {
var name = constructor;
//先从controllers里面找是否有注册name的controller
constructor = controllers.hasOwnProperty(name)
? controllers[name] //有,直接返回
: getter(locals.$scope, name, true) || getter($window, name, true); //没有,从locals.$scope中找,没有,再从window中找
assertArgFn(constructor, name, true); //mock用
}
return $injector.instantiate(constructor, locals); //这里简单看作调用injector.invoke进行依赖注入并调用controller的定义方法。
};
}];
从这里可以看出,上面的例子在读到ng-controller指令的时候,会从controllerProvider中要求获取实际controller,也就是使用$get方法,因为没有使用module.controller进行注册,所以这里应该是从window上取到实际的controller。 下面的例子展示了从controllers中获取的情况:
angular.module('mymodule', [])
.controller('myctrl', function () { ... });