2014-06-30 33 views
1

我试图创建一个脚本,将包括所有需要的人,使我的角度应用程序的工作,但似乎并没有工作:角脚本加载:如何将所有脚本只需一个电话

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已经有一些东西可以做到这一点,看起来很自然,将脚本加入到一个中?

非常感谢。

回答

2

如果您使用的是AngularJS(或任何类似的高级框架),那么您肯定有时间了解模块加载。当您开始构建更多模块并开始处理更复杂的依赖链时,注入<script>标签很快变得站不住脚。

RequireJS是一个很大的包,可以在阳光下做的一切。这是一个tutorial on using the two together,看起来不错。 Browserify是一个类似的库,可让您管理NPM的依赖关系。这比RequireJS简单一点,这对你来说可能是个好东西。这是tutorial that looks decent

两个RequireJS和Browserify来使用命令行构建工具,这是伟大的,因为他们可以在所有的源代码合并到一个单一的文件,当您准备好您的应用程序部署到服务器。

但是,我应该警告你,这东西不容易。有一个相当陡峭的学习曲线。不过,很可能,这是你无论如何迟早都需要学习的东西。

+0

非常感谢,我一直在寻找RequireJS,它看起来像我正在寻找的,其他答案也很好,但它看起来像RequireJS是要走的路。 –

3

这是因为你的脚本是异步加载的,角度是在页面加载时同步编译文档(因为我的脚本中包含angular.js,因为我没有在上面看到它)。在这种情况下,您将不得不手动引导应用程序,因为在使用RequireJS时您也必须执行此操作。这是一个例子...既然你没有使用像RequireJS图书馆,我也把哈克柜台看看,当你所有的脚本加载回调,并引导角当所有的脚本已加载:

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]); 
} 

上面的解决方案是一个有点哈克因为我们正在跟踪所有已加载的脚本。这就是像RequireJS这样的库可以很好地播放的地方,因为当你想要加载的脚本时它会调用你的回调函数。一个例子是:

require(['angular', 'jquery', 'appConfig', 'MyAppController', 'Service1', 'Service2'], function (ng, $) { 
    //bootstrap when all is ready 
    $(function() { 
     ng.bootstrap(document, ["myAppName"]); 
    }); 
}); 
+0

非常感谢这个例子,它真的很好,但我最终会尝试使用RequireJS,因为它看起来更加灵活和标准化,以防我们得到更多的开发人员或移动到另一个公司:) –