从源码入手
如同其他常见脚本框架一样,angular的核心代码包裹在一个自调用的匿名函数里边
(function(window, document, undefined) { //... var angular = window.angular || (window.angular = {}); })(window, document);
在自调用匿名函数内部angular是一个对象,通过publishExternalAPI给angular对象赋值方法,angular.module通过setupModuleLoader赋值。
function publishExternalAPI(angular) { extend(angular, { 'bootstrap': bootstrap, 'copy': copy, //... }); //... angularModule = setupModuleLoader(window); //... }
angular.module返回一个module对象,下图是module对象的方法
依赖注入
先看一个实例
<html> <head> <title>AngularJS Dependency Injection</title> </head> <body> <h2>AngularJS Sample Application</h2> <div ng-app="app" ng-controller="CalcController"> <p>Enter a number: <input type="number" ng-model="number" /> <button ng-click="square()">X<sup>2</sup></button> <p>Result: {{result}}</p> </div> <script src="https://code.angularjs.org/1.5.0/angular.min.js"></script> <script> var app = angular.module("app", []); app.config(function($provide) { $provide.provider('MathService', function() { this.$get = function() { var factory = {}; factory.multiply = function(a, b) { return a * b; } return factory; }; }); }); app.value("defaultInput", 5); app.factory('MathService', function() { var factory = {}; factory.multiply = function(a, b) { return a * b; } return factory; }); app.service('CalcService', function(MathService) { this.square = function(a) { return MathService.multiply(a, a); } }); app.controller('CalcController', function($scope, CalcService, defaultInput) { $scope.number = defaultInput; $scope.result = CalcService.square($scope.number); $scope.square = function() { $scope.result = CalcService.square($scope.number); } }); </script> </body> </html>
config、value、factory、server、controller等方法会向invokeQueue队列中推入相关数组,在document发生DOMContentLoaded事件后启动angularInit。
jqLite(document).ready(function() { angularInit(document, bootstrap); });
jqLite是一个类似jQuery的对象( jQuery、jqLite 与 angular.element)
function angularInit(element, bootstrap) { //... if (appElement) { bootstrap(appElement, module ? [module] : [], config); } //... }
angularInit中的bootstrap是一个函数,在angularInit中用来根据ng-app初始化angular应用。bootstrap也可以用来手动启动angular应用,可以通过angular.bootstrap来访问
function bootstrap(element, modules, config) { //... }
手动启动angular应用
<!doctype html> <html> <body> <div ng-controller="WelcomeController"> {{greeting}} </div> <script src="https://code.angularjs.org/1.5.0/angular.min.js"></script> <script> var app = angular.module('demo', []) .controller('WelcomeController', function($scope) { $scope.greeting = 'Welcome!'; }); angular.bootstrap(document, ['demo']); </script> </body> </html>
推断式注入
app.controller("myCtrl1", function ($scope, hello1, hello2) { $scope.hello = function () { hello1.hello(); hello2.hello(); } });
标记式注入
var myCtrl2 = function ($scope, hello1, hello2) { $scope.hello = function () { hello1.hello(); hello2.hello(); } } myCtrl2.$injector = ['hello1', 'hello2']; app.controller("myCtrl2", myCtrl2);
内联式注入
app.controller("myCtrl3", ['$scope', 'hello1', 'hello2', function ($scope, hello1, hello2) { $scope.hello = function () { hello1.hello(); hello2.hello(); } }]);