1.angular文件加载完开始启动。
angularjs 是一个自执行函数
(function(window, document, undefined) {
'use strict'
.....
})((window, document))
默认是从document开始。
###启动过程。 1 检测是否angular已经启动
if (window.angular.bootstrap) {
//AngularJS is already loaded, so we can return here...
console.log('WARNING: Tried to load angular more than once.');
return;
}
2 绑定jquery(如果没有引入jQuery则使用内置JQLite)
bindJQuery();
3 通过函数publishExternalAPI(angular),传入angular对象,拓展angular的工具函数和属性。同时设置module函数(angularModule = setupModuleLoader(window);)setupModuleLoader()函数使用多层闭包,把注册的模块缓存到变量modules中。同时在闭包函数中为module添加属性方法。如(controller,directive...)。然后通过angularModule(返回的闭包函数)执行匹配(ng-app || data-ng-app || x-ng-app || ng:)查找模板的开始节点,如果模板中有使用其中指令,则启动,若没有,则需要通过angular.bootstrap手动启动。
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},
'getTestability': getTestability,
'$$minErr': minErr,
'$$csp': csp,
'reloadWithDebugInfo': reloadWithDebugInfo
});
angularModule = setupModuleLoader(window);
try {
angularModule('ngLocale');
} catch (e) {
angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
}
angularModule('ng', ['ngLocale'], ['$provide',
function ngModule($provide) {
// $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
$provide.provider({
$$sanitizeUri: $$SanitizeUriProvider
});
$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,
pattern: patternDirective,
ngPattern: patternDirective,
required: requiredDirective,
ngRequired: requiredDirective,
minlength: minlengthDirective,
ngMinlength: minlengthDirective,
maxlength: maxlengthDirective,
ngMaxlength: maxlengthDirective,
ngValue: ngValueDirective,
ngModelOptions: ngModelOptionsDirective
}).
directive({
ngInclude: ngIncludeFillContentDirective
}).
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,
$$q: $$QProvider,
$sce: $SceProvider,
$sceDelegate: $SceDelegateProvider,
$sniffer: $SnifferProvider,
$templateCache: $TemplateCacheProvider,
$templateRequest: $TemplateRequestProvider,
$$testability: $$TestabilityProvider,
$timeout: $TimeoutProvider,
$window: $WindowProvider,
$$rAF: $$RAFProvider,
$$asyncCallback: $$AsyncCallbackProvider,
$$jqLite: $$jqLiteProvider
});
}
]);
}
4 启动angular服务
jqLite(document).ready(function() {
angularInit(document, bootstrap);
});
2.$watch() 和 $observe()
$watch()
####$watch()是angular上scope对象的一个方法。 任何一个控制器中,但是不推荐在在控制器中使用$watch();因为这样使得测试和维护变得很困难。 任何一个指令中,可以在指令的link函数中使用,这是一种推荐的方式。 他不但可以监测angular expression的变化,还可以检测function(){}函数的变化,监测angular expression的时候会使用$parse将angular expression解析为一个函数,这个函数会在angular的每个脏值检查循环中被调用。 ###$observe() ####$observe()是angular指令中link函数中实例属性即(iAttr)的一个方法。 只可以在指令中使用,也是在指令的link函数中使用。 它只能够监测angular expression的变化,监测的方式和上面$watch()监测angular expression的方式一样。 ####然后我们来说一说它们的区别:
1.在控制器中
因为在控制器中是不推荐使用$watch()的,所以我们稍后的一些讨论主要都是在指令中讨论的。
2。指令(不使用隔离的作用域)
在不使用隔离的作用域的指令中,$watch()只能够监测不带有插值标记的angular expression,比如在<div attr1='expr' attr2='{{expr}}'></div>中,只可以监测attr1='expr'中的attr1,监测attr2只能够得到一个undefined,因为存在{{}}插值符号。 在不使用隔离的作用域的指令中,$observe()只能够监测带有插值标记的angular expression,比如在<div attr1='expr' attr2='{{expr}}'></div>中,只可以监测attr2='{{expr}}'中的attr2,监测attr1只会得到一个一成不变的字符串expr。
3.指令(使用隔离的作用域)
在使用隔离的作用域的指令中,$watch()也可以监测带有插值标记的angular expression;因为使用了@或者=前缀标识符,它们已经帮我们实现了插值,所以可以这样使用。 下面我们来看一个例子: ###$watch() && $observe() 一些建议 监测元素的属性值的时候,是可以使用angular-styleguide但是,会有一些问题,我第一次写示例的时候遇到了一些错误;比如刚开始我使用了controllerAs语法,就是用了MyController as vm并且将监测的一些属性中的变量都使用vm.prop,这样一来就出出现了一些错误,所以我在写这个demo的时候一些地方没有遵循angular-styleguide。 关于结果中出现undefined的解释,因为指令优先级别高于控制器,所以在指令中使用$watch()时,如果监测的表达式其中含有{{}}那么会出现undefined,因为在监测的时候插值字符串中的变量还没有被解析。但是在使用隔离作用域的指令中是可以的,因为@和=已经帮助我们实现了变量的解析。