AngularJS特輯: can i have multiple ng-app in a html? Ans. yes

我沒有偏好學習任何框架, 會學習框架只是因為在台灣職場, 多會一套薪水越多(但我覺得這想法見仁見智拉), 當初會學AngularJS也是因為該工作需要而自學, 就這麼單純。

當時學到ng-app在整個AngularJS應用程式中只能有一個, 但最近發現如果實務上需要同一個HTML中有多個ng-app的話, 要如何實現?

聽到這需求, 直覺合理推斷這應該要有解才對, 畢竟開發AngularJS的是一個團隊, 怎麼可能沒考慮這點? 所以一直想知道而去找資料, 就找到這篇文章 http://www.simplygoodcode.com/2014/04/angularjs-getting-around-ngapp-limitations-with-ngmodule/  有很多人引用, 且我看來是目前的最佳解

文章作者的觀點是: AngularJS開發團隊當初設計ng-app只能有一個的限制是為了讓大家好入手這個框架, 讓大家不易混淆, 畢竟AngularJS主打之一為SPA觀念和實踐...

文章中有提到github上有人實作這解法:
https://github.com/luisperezphd/ngModule


這解法就是使用ng-module, 文章中作者特別提到這點:
In keeping with Angular’s convention I allow you to use any variation of the directive name. For example, the following are all valid: ng:module, x-ng-modules, data-ng-modules, etc.

以下是我試著實作文章和github中的最佳解版本的完整原始碼:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<script>
<!-- this piece of script is so-called "angular.ng-modules.js" -->
(function() {
function initNgModules(element) {
var elements = [element],
moduleElements = [],
modules = [],
names = ['ng:module', 'ng-module', 'x-ng-module', 'data-ng-module', 'ng:modules', 'ng-modules', 'x-ng-modules', 'data-ng-modules'],
NG_MODULE_CLASS_REGEXP = /\sng[:\-]module[s](:\s*([\w\d_]+);?)?\s/;

function append(element) {
element && elements.push(element);
}

for(var i = 0; i < names.length; i++) {
var name = names[i];
append(document.getElementById(name));
name = name.replace(':', '\\:');
if (element.querySelectorAll) {
var elements2;
elements2 = element.querySelectorAll('.' + name);
for(var j = 0; j < elements2.length; j++) append(elements2[j]);

elements2 = element.querySelectorAll('.' + name + '\\:');
for(var j = 0; j < elements2.length; j++) append(elements2[j]);

elements2 = element.querySelectorAll('[' + name + ']');
for(var j = 0; j < elements2.length; j++) append(elements2[j]);
}
}

for(var i = 0; i < elements.length; i++) {
var element = elements[i];

var className = ' ' + element.className + ' ';
var match = NG_MODULE_CLASS_REGEXP.exec(className);
if (match) {
moduleElements.push(element);
modules.push((match[2] || '').replace(/\s+/g, ','));
} else {
if(element.attributes) {
for(var j = 0; j < element.attributes.length; j++) {
var attr = element.attributes[j];

if (names.indexOf(attr.name) != -1) {
moduleElements.push(element);
modules.push(attr.value);
}
}
}
}
}

for(var i = 0; i < moduleElements.length; i++) {
var moduleElement = moduleElements[i];
var module = modules[i].replace(/ /g,'').split(",");
angular.bootstrap(moduleElement, module);
}
}

angular.element(document).ready(function() {
initNgModules(document);
});
})();
</script>
<script>
var moduleA = angular.module("MyModuleA", []);
moduleA.controller("MyControllerA", function($scope) {
console.log($scope);
$scope.name = "Bob A";
});

var moduleB = angular.module("MyModuleB", []);
moduleB.controller("MyControllerB", function($scope) {
console.log($scope);
$scope.name = "Steve B";
});
</script>
</head>
<body>
<div ng-modules="MyModuleA, MyModuleB">
<h1>Module A, B</h1>
<div ng-controller="MyControllerA">
{{name}}
</div>
<div ng-controller="MyControllerB">
{{name}}
</div>
</div>

<div ng-module="MyModuleB">
<h1>Just Module B</h1>
<div ng-controller="MyControllerB">
{{name}}
</div>
</div>
</body>
</html>


我想知道兩個modules中的$scope內容, 下圖是我得到的結果:(點圖可放大)




留言

熱門文章