@yiranphp
2016-04-08T18:14:22.000000Z
字数 4781
阅读 3475
angular
一个自执行函数,简化如下
(function(window, document, undefined) {
// 定义变量和函数
// 其他操作
if (window.angular.bootstrap) {
console.log('WARNING: Tried to load angular more than once.');
return;
}
bindJQuery();
publishExternalAPI(angular);
jqLite(document).ready(function() {
angularInit(document, bootstrap);
});
})(window, document);
整体思路为:
绑定jQuery,简化如下
var bindJQueryFired = false;
function bindJQuery() {
if (bindJQueryFired) {
return;
}
var jqName = jq();
jQuery = window.jQuery;
if (isDefined(jqName)) {
jQuery = jqName === null ? undefined : window[jqName];
}
if (jQuery && jQuery.fn.on) {
jqLite = jQuery;
// ... ...
} else {
jqLite = JQLite;
}
angular.element = jqLite;
bindJQueryFired = true;
}
总结起来,绑定的jQuery可以的来源有三个:ng-jq指定、引入的jQuery库、内置实现的JQLite,其使用流程为:
如果有ng-jq
- 如果ng-jq的值不为空,则使用它指定的库
- 如果ng-jq指定的值为空,则变量jQuery的值为undefined,此时强制使用JQLite,无论是否引入了jQuery库
如果没有ng-jq
如果引入了jQuery库,则使用它; 如果没有引入jQuery库,则使用JQLite
代码简化如下
function publishExternalAPI(angular) {
extend(angular, {
// ... ...
});
angularModule = setupModuleLoader(window);
try {
angularModule('ngLocale');
} catch (e) {
angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
}
angularModule('ng', ['ngLocale'], ['$provide',
function ngModule($provide) {
// ... ...
}
]);
}
主要功能:
1. 扩展angular对象,挂载工具函数
2. 执行setupModuleLoader(window),该方法主要是创建了模块加载器:angular.module方法,用于注册及获取模块;angular.module只有一个参数的时候为获取模块,否则为注册模块;
3. 如果没有注册ngLocal模块,则对其进行注册;
4. 注册ng模块,也就是AngularJS的核心模块。
启动Angular应用,相关代码为:
jqLite(document).ready(function() {
angularInit(document, bootstrap);
});
// angularInit定义
var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];
function getNgAttribute(element, ngAttr) {
var attr, i, ii = ngAttrPrefixes.length;
for (i = 0; i < ii; ++i) {
attr = ngAttrPrefixes[i] + ngAttr;
if (isString(attr = element.getAttribute(attr))) {
return attr;
}
}
return null;
}
function angularInit(element, bootstrap) {
var appElement,
module,
config = {};
// The element `element` has priority over any other element
forEach(ngAttrPrefixes, function(prefix) {
var name = prefix + 'app';
if (!appElement && element.hasAttribute && element.hasAttribute(name)) {
appElement = element;
module = element.getAttribute(name);
}
});
forEach(ngAttrPrefixes, function(prefix) {
var name = prefix + 'app';
var candidate;
if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) {
appElement = candidate;
module = candidate.getAttribute(name);
}
});
if (appElement) {
config.strictDi = getNgAttribute(appElement, "strict-di") !== null;
bootstrap(appElement, module ? [module] : [], config);
}
}
需要说明的是,AngularJS支持的属性前缀有多种,包括ng-、data-ng、ng:和x-ng-。
- 首先对element进行检测,看它是否有ng-app等属性,如果有则设定appElement和module;
- 如果element元素没有ng-app等属性,则对其后代元素进行查找,找到第一个有ng-app等属性的元素,从而设定appElement和module;
- 如果appElement不为空,即找到了应用的入口元素,则执行bootstrap。
- 需要注意的是,如果有多个元素都有ng-app属性,则只会找到第一个并启动它,而后面的应用则不会自动启动。
启动总结:自动启动、手动启动
1、自动启动:
<body ng-app="plunker">
<div ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
</div>
</body>
<script>
var app = angular.module('plunker', []);
app.controller('MainCtrl', ['$scope', function($scope) {
$scope.name = 'alex';
}]);
</script>
上面的例子使用了ng-app指令:http://plnkr.co/edit/HJNL9gDbECjX0SsU4IIG?p=info
2、手动启动
<body>
<div ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
</div>
</body>
<script>
var app = angular.module('plunker', []);
app.controller('MainCtrl', ['$scope', function($scope) {
$scope.name = 'alex';
}]);
angular.element(document).ready(function() {
angular.bootstrap(document.body, ['plunker']);
});
</script>
上面的例子没有使用ng-app指令,用angular.bootStrap启动:http://plnkr.co/edit/DFHhpwA0fKzERF2JgDJn?p=info
3、多启动:首先是应用是不能嵌套的,如果使用了多个ng-app,只有第一个是自动启动
<body>
<div ng-controller="MainCtrl1" ng-app="app1">
<p>Hello {{name}}!</p>
</div>
<div ng-controller="MainCtrl2" ng-app="app2" id="app2">
<p>Hello {{name}}!</p>
</div>
</body>
<script>
var app1 = angular.module('app1', []);
app1.controller('MainCtrl1', ['$scope', function($scope) {
$scope.name = 'alex';
}]);
var app2 = angular.module('app2', []);
app2.controller('MainCtrl2', ['$scope', function($scope) {
$scope.name = 'yiranphp';
}]);
angular.element(document).ready(function() {
angular.bootstrap(document.getElementById('app2'), ['app2']);
});
</script>
上面的例子第一个ng-app自动启动,第二个手动启动:http://plnkr.co/edit/xnNqm7NSQKRegGkAshTH?p=preview
本篇文章到此结束,欢迎指正