AngularJS 源码分析1
AngularJS简介
angularjs 是google出品的一款MVVM前端框架,包含一个精简的类jquery库,创新的开发了以指令的方式来组件化前端开发,可以去它的官网看看,请戳这里
再贴上一个本文源码分析对应的angularjs源码合并版本1.2.4,精简版的,除掉了所有的注释, 请戳这里
从启动开始说起
定位到4939行,这里是angularjs开始执行初始化的地方,见代码
bindJQuery(), publishExternalAPI(angular), jqLite(document).ready(function() {
angularInit(document, bootstrap)
})
bindJQuery方法是检查是否引用jquery,没有的话jqlite就用本身自带的,否则切换到jquery中去.这个好理解
publishExternalAPI这个方法是绑定一些公共的方法到angular下面,这些是可以在网站中访问到的,像forEach,copy等公共方法,还有一个重要的任务就是初始化angular核心的模块,publishExternalAPI在465行,现在我们来分析里面的一些重要的代码
function publishExternalAPI(angular) {
extend(angular, {
bootstrap: bootstrap,
copy: copy,
extend: extend,
equals: equals,
element: jqLite,
forEach: forEach,
injector: createInjector,
noop: noop,
bind: bind,
toJson: toJson,
fromJson: fromJson,
identity: identity,
isUndefined: isUndefined,
isDefined: isDefined,
isString: isString,
isFunction: isFunction,
isObject: isObject,
isNumber: isNumber,
isElement: isElement,
isArray: isArray,
version: version,
isDate: isDate,
lowercase: lowercase,
uppercase: uppercase,
callbacks: {
counter: 0
},
$$minErr: minErr,
$$csp: csp
}), angularModule = setupModuleLoader(window);
try {
angularModule("ngLocale")
} catch (e) {
angularModule("ngLocale", []).provider("$locale", $LocaleProvider)
}
angularModule("ng", ["ngLocale"], ["$provide",
function($provide) {
$provide.provider("$compile", $CompileProvider).directive({
a: htmlAnchorDirective,
input: inputDirective,
textarea: inputDirective,
form: formDirective,
script: scriptDirective,
select: selectDirective,
style: styleDirective,
option: optionDirective,
ngBind: ngBindDirective,
ngBindHtml: ngBindHtmlDirective,
ngBindTemplate: ngBindTemplateDirective,
ngClass: ngClassDirective,
ngClassEven: ngClassEvenDirective,
ngClassOdd: ngClassOddDirective,
ngCloak: ngCloakDirective,
ngController: ngControllerDirective,
ngForm: ngFormDirective,
ngHide: ngHideDirective,
ngIf: ngIfDirective,
ngInclude: ngIncludeDirective,
ngInit: ngInitDirective,
ngNonBindable: ngNonBindableDirective,
ngPluralize: ngPluralizeDirective,
ngRepeat: ngRepeatDirective,
ngShow: ngShowDirective,
ngStyle: ngStyleDirective,
ngSwitch: ngSwitchDirective,
ngSwitchWhen: ngSwitchWhenDirective,
ngSwitchDefault: ngSwitchDefaultDirective,
ngOptions: ngOptionsDirective,
ngTransclude: ngTranscludeDirective,
ngModel: ngModelDirective,
ngList: ngListDirective,
ngChange: ngChangeDirective,
required: requiredDirective,
ngRequired: requiredDirective,
ngValue: ngValueDirective
}).directive(ngAttributeAliasDirectives).directive(ngEventDirectives), $provide.provider({
$anchorScroll: $AnchorScrollProvider,
$animate: $AnimateProvider,
$browser: $BrowserProvider,
$cacheFactory: $CacheFactoryProvider,
$controller: $ControllerProvider,
$document: $DocumentProvider,
$exceptionHandler: $ExceptionHandlerProvider,
$filter: $FilterProvider,
$interpolate: $InterpolateProvider,
$interval: $IntervalProvider,
$http: $HttpProvider,
$httpBackend: $HttpBackendProvider,
$location: $LocationProvider,
$log: $LogProvider,
$parse: $ParseProvider,
$rootScope: $RootScopeProvider,
$q: $QProvider,
$sce: $SceProvider,
$sceDelegate: $SceDelegateProvider,
$sniffer: $SnifferProvider,
$templateCache: $TemplateCacheProvider,
$timeout: $TimeoutProvider,
$window: $WindowProvider
})
}
])
}
方法体中的setupModuleLoader方法是一个模块加载器,这也是一个关键方法, 主要作用是创建和获取模块,代码见417行.
1
|
function
setupModuleLoader(window) {
function
ensure(obj, name, factory) {
return
obj[name] || (obj[name] = factory()) }
var
$injectorMinErr = minErr(
"$injector"
), ngMinErr = minErr(
"ng"
);
return
ensure(ensure(window,
"angular"
, Object),
"module"
,
function
() {
var
modules = {};
return
function
(name, requires, configFn) {
var
assertNotHasOwnProperty =
function
(name, context) {
if
(
"hasOwnProperty"
=== name)
throw
ngMinErr(
"badname"
,
"hasOwnProperty is not a valid {0} name"
, context) };
return
assertNotHasOwnProperty(name,
"module"
), requires && modules.hasOwnProperty(name) && (modules[name] =
null
), ensure(modules, name,
function
() {
function
invokeLater(provider, method, insertMethod) {
return
function
() {
return
invokeQueue[insertMethod ||
"push"
]([provider, method, arguments]), moduleInstance } }
if
(!requires)
throw
$injectorMinErr(
"nomod"
,
"Module '{0}' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument."
, name);
var
invokeQueue = [], runBlocks = [], config = invokeLater(
"$injector"
,
"invoke"
), moduleInstance = { _invokeQueue: invokeQueue, _runBlocks: runBlocks, requires: requires, name: name, provider: invokeLater(
"$provide"
,
"provider"
), factory: invokeLater(
"$provide"
,
"factory"
), service: invokeLater(
"$provide"
,
"service"
), value: invokeLater(
"$provide"
|