我对typescript非常陌生,我正在为WebGl编写一个小型原型框架.我目前正在重构我的项目,遇到了一些问题,比如如何组织我的项目,因为(模块和名称空间)方法似乎都有严重的缺陷.
This post is not about HOW to use these patterns, but how to overcome the problems each of these brings.
Status Quo: Using namespaces
来自C#这似乎是最自然的方式.每个类/模块都会得到相应的名称空间,我在tsconfig中提供"outFile"参数.json,因此所有内容都被连接到一个大文件中.
示例文件
namespace Cross.Eye {
export class SpriteFont {
//code omitted
}
}
用法示例(在html中提供js文件之前,必须确保跨命名空间加载到全局命名空间中)
namespace Examples {
export class _01_BasicQuad {
context: Cross.Eye.Context;
shader: Cross.Eye.ShaderProgram;
//code omitted
}
}
赞成的意见
- 如果你是从C#/Java提交,使用起来很简单
- 与文件名无关——重命名文件不会 destruct 代码.
- 易于重构:IDE可以很容易地重命名名称空间/类,这些更改将在整个代码中得到一致的apply.
- 便利性:向项目中添加一个类非常简单,只需添加一个文件并在所需的命名空间中声明即可.
欺骗
对于大多数项目,我们建议使用外部模块和名称空间进行快速演示,并移植旧的JavaScript代码.
从https://basarat.gitbooks.io/typescript/content/docs/project/namespaces.html
- 根命名空间总是(?)全局对象(坏)
- 不能(?)可以与browserify或webpack等工具一起使用,这对于将库与其依赖项Bundle 在一起或在实际使用时将自定义代码与库Bundle 在一起是必不可少的.
- 如果你计划发布一个npm模块,这是错误的做法
State of the art (?): Modules
Typescript支持ES6模块,它们是新的和shiny 的,每个人似乎都同意它们是future 的发展方向.其 idea 似乎是,每个文件都是一个模块,通过在import语句中提供这些文件,您可以非常明确地定义依赖项,这使得Bundle 工具能够轻松有效地打包代码.我通常每个文件都有一个类,这似乎不适合dhte模块模式.
这是我重构后的文件 struct :
我还有一个索引.每个文件夹中都有一个ts文件,这样我就可以在import * as FolderModule from "./folder"
之前导入它的所有类
export * from "./AggregateLoader";
export * from "./ImageLoader";
export * from "./TiledLoader";
export * from "./XhrLoaders";
export * from "./XmlSpriteFontLoader";
示例文件 - I think the problem becomes clearly visible here..
import {SpriteFont} from "./SpriteFont";
import {ISpriteTextGlyph, ISpriteChar} from "./Interfaces";
import {Event,EventArgs} from "../../Core";
import {Attribute, AttributeConfiguration} from "../Attributes";
import {DataType} from "../GlEnums";
import {VertexStore} from "../VertexStore";
import {IRectangle} from "../Geometry";
import {vec3} from "gl-matrix";
export class SpriteText {
// code omitted
}
示例用法.如您所见,我不再需要遍历名称空间,因为我可以直接导入类.
import {
Context,
Shader,
ShaderProgram,
Attribute,
AttributeConfiguration,
VertexStore,
ShaderType,
VertexBuffer,
PrimitiveType
} from "../cross/src/Eye";
import {
Assets,
TextLoader
} from "../cross/src/Load";
export class _01_BasicQuad {
context: Context;
shader: ShaderProgram;
// code omitted.
}
赞成的意见
- 使代码更加模块化,因为它不再绑定到名称空间.
- 您可以使用browserfy或webpack等Bundle 工具,它们也可以Bundle 所有依赖项
- 导入类时更加灵活,不再需要遍历名称空间链.
欺骗
- 如果每个类都是不同的文件,那么就必须反复输入相同的导入语句.
- 重命名文件会 destruct 代码(错误).
- 重构类名不会传播到您的导入中(非常糟糕——可能取决于您的IDE,我使用的是vs代码)
这两种方法似乎都有缺陷.名称空间似乎非常过时,不适用于大型项目,与常用工具不兼容,而使用模块非常不方便,并且 destruct 了我最初调整typescript的一些功能.
在一个完美的世界里,我会使用名称空间模式编写我的框架,并将其导出为一个模块,然后可以将其导入并与其依赖项Bundle 在一起.然而,如果没有一些丑陋的黑客,这似乎是不可能的.
所以我的问题是:你是如何处理这些问题的?如何最大限度地减少每种方法的缺点?
Update
在获得了更多关于typescript和javascript开发的经验之后,我必须指出,模块可能是所有用例中90%的使用方法.
最后10%希望是使用全局名称空间的遗留项目,您希望用一点typescript(顺便说一句,它非常有效)来增加这些项目的趣味性.
我对模块的许多批评可以(并且已经)通过更好的IDE支持来解决.Visual Studio代码添加了自动模块解析功能,效果非常好.