Requirejs +(多)角+打字稿
我似乎碰壁了,我无法打破。我正在使用angular + typescript,并希望使它与requirejs一起工作。定义了多个角度应用程序,这些应用程序根据正文中的data-app-name属性加载。Requirejs +(多)角+打字稿
文件夹结构(简化):
|- Libs
|- angular
|- some-plugin
|- angular-some-plugin // Exposes an angular.module("ngSomePlugin")
|- require.js
|- Common
|- Common.ts // Exposes an angular.module("common")
|- App1
|- Controllers
|- SomeController.ts
|- SomeOtherController.ts
|- Services
|- SomeService.ts
|- Main.ts
|- App.ts
|- App2
// same as above
|- AppX
// same as above
|- Index.html
|- Main.ts
内容:
的index.html:
// All these attributes are set dynamically server-side
<body id="ng-app-wrapper" data-directory="App1" data-app-name="MyApp">
<script src="Libs/require.js" data-main="Main"></script>
</body>
Main.ts:
console.log("Step 1: Main.js");
requirejs.config({
paths: {
"angular": "Libs/angular/angular",
"common": "Common/common"
},
shim: {
"angular": {
exports: "angular"
}
}
});
require(["angular"], (angular: angular.IAngularStatic) => {
angular.element(document).ready(function() {
var $app = angular.element(document.getElementById("ng-app-wrapper"));
var directory = $app.data("directory");
var appName = $app.data("app-name");
requirejs.config({
paths: {
"appMain": directory + "/Main"
}
});
require([
'common',
'appMain'
], function() {
console.log("Step 5: App1/Main.js loaded");
console.log("Step 6: Bootstrapping app: " + appName);
angular.bootstrap($app, [appName]);
});
});
});
Main.ts在App1的:
console.log("Step 2: App1/Main.js");
requirejs.config({
paths: {
"app": "App1/App",
"somePlugin": "Libs/some-plugin/some-plugin", // This is an AMD module
"ngSomePlugin": "Libs/angular-some-plugin/angular-some-plugin"
},
shim: {
"ngSomePlugin": {
exports: "ngSomePlugin",
deps: ["somePlugin"]
}
}
});
define([
"app"
],() => {
console.log("Step 4: App.js loaded");
});
应用1/App.ts:
console.log("Step 3: App.js");
import SomeController = require("App1/Controllers/SomeController");
import SomeOtherController = require("App1/Controllers/SomeOtherController");
import SomeService = require("App1/Services/SomeService");
define([
"angular",
"ngSomePlugin"
], (angular: angular.IAngularStatic) => {
// This isn't called, so obviously executed to late
console.log("Defining angular module MyApp");
angular.module("MyApp", ["common", "ngSomePlugin"])
.controller("someCtrl", SomeController.SomeController)
.controller("someOtherCtrl", SomeOtherController.SomeOtherController)
.service("someService", SomeService.SomeService)
;
});
然而,这似乎打破,用好旧的错误:未捕获 错误:[$注射器:NOMOD]模块 'MyApp的' 不可!您拼错了模块名称或忘记加载模块名称。
问题1:
我在做什么错在这里?如何确保angular.module()
调用在我启动我的应用程序之前完成?
这是console.logs,在那里你可以看到角的输出尚未定义的模块angular.module(“MyApp的”),所以这样做是为了后期明显:
UPDATE 我可以解开App.ts中的角度调用,所以它不需要任何东西(顶部的导入除外)。然后,如果我将应用程序添加到App1/Main.ts中的垫片,并在那里放置依赖关系,它似乎可以工作。这是解决这个问题的好方法吗?
UPDATE2 如果我使用需要,而不是在App.ts定义的,它实例化角模块,但仍试图引导之后。
问题2:
是否有任何的方式来传递下来的自定义配置,例如其中的lib目录名?我想这似乎没有工作如下(Main.ts):
requirejs.config({
paths: {
"appMain": directory + "/Main"
},
config: {
"appMain": {
libsPath: "Libs/"
},
"app": {
name: appName
}
}
});
应用1/Main.ts:
define(["module"], (module) => {
var libsPath = module.config().libsPath;
requirejs.config({
paths: {
"somePlugin": libsPath + "somePlugin/somePlugin"
// rest of paths
}
});
define([ // or require([])
"app"
],() => {});
});
App.ts:
define([
"module"
// others
], (module) => {
angular.module(module.config().name, []);
});
但是这样一来从逻辑上讲,angular.bootstrap()不会等待App.ts被加载。因此,角度模块尚未定义,它无法启动。看起来你不能在App1/Main.ts中做一个嵌套定义?我应该如何配置?
对问题1相关:
在App1的/ App.ts,不应该函数返回的角模块为它被注入。
例如。
define([
"angular",
"ngSomePlugin"
], (angular: angular.IAngularStatic) => {
return angular.module("MyApp", ["common", "ngSomePlugin"])
.controller("someCtrl", SomeController.SomeController)
.controller("someOtherCtrl", SomeOtherController.SomeOtherController)
.service("someService", SomeService.SomeService)
;
});
问题1
亚历山大Beletsky写了great article约搭售requireJS和角度在一起(和为什么它是值得的)。其中,我认为他有第一个问题的答案:从另一个模块加载角度,然后进行引导调用。 这个强制要求JS在执行任何代码之前加载这些模块的依赖关系。
假设这是您的main.ts
console.log("Step 1: Main.js");
requirejs.config({
paths: {
"angular": "Libs/angular/angular",
"common": "Common/common".
"mainT1": "t1/main.js"
},
shim: {
"angular": {
exports: "angular"
}
}
});
添加在T1的主,你使实际应用中非常结束通话到下一个模块
requirejs(["app"], function(app) {
app.init();
});
这里,并把它加载了一次全部。
t1/main.ts
define("app-name", ['angular'], function(angular){
var loader = {};
loader.load = function(){
var app = angular.module("app-name",[]);
return app;
}
return loader;
}
最后,让我们说你是这儿的临时文件拿它你叫app.js
。在这里,您将设置排序以获取已完成角度加载顺序的对象。一旦完成,那么你可以在init()函数中调用bootstrapping。
t1/app.js
define("app", function(require){
var angular = require('angular');
var appLoader = require('mainT1');
var app = {}
app.init = function(){
var loader = new appLoader();
loader.load();
angular.bootstrap(document, ["app-name"]);
}
}
我有怀疑,require.config的'多层()'调用将正常工作。 (Side-question:是吗?)但是由于'data-directory' /'data-app-name'是在服务器端生成的,我建议你也动态生成'require.config()'调用。您甚至可能希望动态地将服务器端的适当片段直接包含到Index.html中。从那里,你需要调整AMD模块中的路径。还有一个旁注:为什么不使用Typescript对AMD的原生支持,即'import Foo = require('Foo')'语法? –
我在angular-app层面上执行'import'东西(在App.ts和所有其他角度组件中)。如果我使用的是打字稿,那么在各处使用导入语法会更好吗?我认为它不适用于非AMD第三方库? – devqon
是的,'require.config()'的多个层似乎工作:) – devqon