我正在尝试创建一个脚本,其中包含所有必需的脚本,以使我的Angular应用程序正常工作但似乎不起作用:
function include(destination) {
var e = window.document.createElement('script');
e.setAttribute('src', destination);
window.document.body.appendChild(e);
}
include('../Scripts/myApp/main.js');
include('../Scripts/myApp/appConfig.js');
include('../Scripts/myApp/MyAppController.js');
include('../Scripts/myApp/Service1.js');
include('../Scripts/myApp/Service2.js');
不幸的是,如果我尝试包含这样的应用程序脚本(它工作正常,它们被完美地加载到页面中),我得到一个错误,因为角度检测到我的“ng-app ='myAppName'”指令但发现没有为它声明的模块(我想是因为角度检查时脚本尚未加载)。如果我然后尝试至少将模块实例化放在由HTML页面(main.js)直接调用的脚本上,那么它会抱怨控制器,服务等不存在,如果我将它们附加到自己的应用程序中文件(app.controller(),app.factory,...)它没有抱怨,但它也没有发生。
看起来像这样加载脚本使得Angular不会执行它们,因为它们可能加载太晚或者某些东西。唯一的方法是设置一个脚本标签来调用HTML上的脚本。
但是我觉得我错过了一些东西,有一种方法可以做到这一点,我只是看不到它。
有人知道如何通过调用其中一个来加载所有必需的脚本吗?在角度应用程序配置上有什么东西可以设置为这样吗?
看起来太脏了,不能打这么多电话,而且性能也不好。
我已经检查过有一种名为Yeoman的东西,但它看起来像我想要的那么大,然后我看到了RequireJS,但我不确定这是我真正想要的,并且再次不确定我是否只想安装另一个库这个。最后,我已经看到在应用程序配置中你可以设置查找视图的位置,甚至是加载控制器的方法(我想,我现在不确定任何东西,我的脑袋是如此头晕)所以我在想也许Angular已经做了一些看起来很自然的东西,将脚本加入到一个?
非常感谢。
答案 0 :(得分:3)
这是因为您的脚本是异步加载的,而angular正在加载页面时同步编译文档(因为我在脚本中包含了angular.js,因为我没有看到它以上)。在这种情况下,您必须手动引导应用程序,因为在使用RequireJS时您也必须这样做。这是一个例子......因为你没有使用像RequireJS这样的库,所以我也放了一个hacky计数器来查看当所有脚本加载完所有脚本加载到回调和引导角度时:
function include(destination) {
var e = window.document.createElement('script');
e.setAttribute('src', destination);
//IE detect when script has fully loaded... Increase number of loaded scripts and
//call bootstrap if all have loaded.
e.onreadystatechange = function () {
if (newjs.readyState === "loaded" || newjs.readyState === "complete") {
e.onreadystatechange = null;
loadedScripts++;
}
if (loadedScripts === numScripts) {
bootstrapAngular("myAppName");
}
}
//Other browsers. Same logic as above - Increase scripts loaded and call bootstrap when complete
e.onload = function () {
loadedScripts++;
if (loadedScripts === numScripts) {
bootstrapAngular("myAppName");
}
}
window.document.body.appendChild(e);
}
//5 scripts being loaded
var numScripts = 5;
//0 currently loaded
var loadedScripts = 0;
include('../Scripts/myApp/main.js');
include('../Scripts/myApp/appConfig.js');
include('../Scripts/myApp/MyAppController.js');
include('../Scripts/myApp/Service1.js');
include('../Scripts/myApp/Service2.js');
function bootstrapAngular(appName) {
//Assuming you are putting ng-app at document level... Change to be your specific element.
angular.bootstrap(document, [appName]);
}
上面的解决方案有点hacky,因为我们正在跟踪已加载的所有脚本。这就是像RequireJS这样的库可以很好地播放的地方,因为它会在你想要的脚本被加载时调用你的回调函数。一个例子是:
require(['angular', 'jquery', 'appConfig', 'MyAppController', 'Service1', 'Service2'], function (ng, $) {
//bootstrap when all is ready
$(function () {
ng.bootstrap(document, ["myAppName"]);
});
});
答案 1 :(得分:2)
如果您正在使用AngularJS(或任何类似的高级框架),那么您肯定有时间了解模块加载。当您开始构建更多模块并开始处理更复杂的依赖链时,快速注入<script>
标记会变得站不住脚。
RequireJS是一个很棒的套餐,可以在阳光下做任何事情。这里的tutorial on using the two together看起来很不错。 Browserify是一个类似的库,可让您使用NPM管理依赖项。它比RequireJS稍微简单一点,这对你来说可能是一个加分。这是tutorial that looks decent。
RequireJS和Browserify都带有命令行构建工具,这很棒,因为当您准备好将应用程序部署到服务器时,它们可以将所有源代码合并到一个文件中。
但是,我应该警告你,这些东西并不容易。学习曲线相当陡峭。但是,很有可能,这是你迟早需要学习的东西。