[英]TypeScript: how to NOT use relative paths to import classes?
我目前正在使用 TypeScript 和 Angular2 開發一個 Electron 應用程序,為此我創建了許多不同的類,所有類都在單獨的文件中。 為了使我的應用程序的重構更容易,我希望在導入這些類時不必使用相對路徑。
現在,要導入它們,我使用以下語法: import {Trigger} from './../../trigger/ts/trigger.component';
我想要做的是使用如下所示的語法: import {Trigger} from 'trigger.component';
那可能嗎?
最好在 tsconfig.json 中使用以下配置
{
"compilerOptions": {
"...": "reduced for brevity",
"baseUrl": "src",
"paths": {
"@app/*": ["app/*"],
"@trigger/*": ["app/trigger/ts/*"]
}
}
}
對於您的情況,使用可以import {Trigger} from '@app/trigger/ts/trigger.component';
或import {Trigger} from '@trigger/trigger.component';
或您可以配置的任何級別的路徑。
您可以創建一個文件,例如:components.ts 並在該組件中引用所有組件,例如:
export {Trigger} from '../trigger/ts/trigger.component'
export {Cmp} from '../cmp/ts/cmp.component'
...
然后,當你想加載一個組件時,你可以這樣做:
import {Trigger} from '../components.ts'
這是對事物進行分組的好習慣。
我使用ScriptCS創建了一個導出器來做到這一點。 我是用 C# 編寫的,但歡迎您用您喜歡的任何語言重新編寫它。
它允許您在每個組件目錄的根目錄中有一個導出文件,您可以通過執行以下操作來導入該文件:
import {LoginPage, HomePage} from '../pages/export'
或者
import {NavBarComponent, HeroCardComponent} from '../controls/export'
假設您在特定目錄中有多個組件,例如:
如果你運行scriptcs exporter.cs -- app/pages app/controls
它將在每個指定目錄中生成一個名為export.ts
的輸出文件,其中包含目錄中每個類的導出語句(遞歸迭代)
出口商.cs
// USAGE
// scriptcs exporter.cs -- app/Templates app/Controls
using System.Text.RegularExpressions;
CreateExports();
public void CreateExports() {
// e.g. 'C:\Apps\MyProject'
string rootDir = new DirectoryInfo(@".\").FullName;
string exportFileName = "export.ts";
List<string> exportDirectoryPaths = new List<string>();
foreach (string argument in Env.ScriptArgs) {
if (argument.Contains(".ts"))
exportFileName = argument;
else
exportDirectoryPaths.Add(argument);
}
Console.WriteLine("File Name:" + exportFileName);
foreach (string exportDirPath in exportDirectoryPaths) {
// e.g. 'app\Templates'
var exportDirPathFixed = exportDirPath.Replace("/", "\\");
Console.WriteLine(String.Format("Exporting -> {0}", exportDirPath));
List<ExportEntry> exportEntriesToWrite = new List<ExportEntry>();
// e.g. 'C:\Apps\MyProject\app\Templates'
DirectoryInfo exportDir = new DirectoryInfo(rootDir + exportDirPathFixed);
foreach (FileInfo file in exportDir.EnumerateFiles("*.ts", SearchOption.AllDirectories)) {
// Don't export the export file ;)
if (file.Name == exportFileName)
continue;
// e.g. toAdd = {
// RelativepathToExportDirectory = './app/templates/template-one.component'
// ClassName = 'TemplateOneComponent' (Parsed from file contents, works with interfaces)
ExportEntry toAdd = CreateExportEntry(file, exportDirPathFixed, rootDir);
exportEntriesToWrite.Add(toAdd);
}
CreateExportFile(exportDir.FullName + "\\" + exportFileName, exportEntriesToWrite);
}
}
private void CreateExportFile(string exportFilePath, IEnumerable<ExportEntry> exportEntries) {
string textToWrite = "";
foreach (ExportEntry entry in exportEntries) {
textToWrite += entry.ToString() + Environment.NewLine;
}
Console.WriteLine("Text: " + Environment.NewLine + textToWrite);
File.WriteAllText(exportFilePath, textToWrite);
}
// -- Create Export Entry -- //
private ExportEntry CreateExportEntry(FileInfo exportFile, string exportDirPath, string rootDir) {
ExportEntry toReturn = new ExportEntry() {
ClassName = GetFirstExportClassName(exportFile),
RelativepathToExportDirectory = exportFile.FullName.Remove(0, rootDir.Length + exportDirPath.Length).Replace(".ts", ""),
};
return toReturn;
}
private string GetFirstExportClassName(FileInfo exportFile) {
string className = null;
Regex regular = new Regex(@"(?<=export[\s+]class|interface)[^s+][^\s]+");
using (StreamReader streamer = new StreamReader(exportFile.OpenRead())) {
string contents = streamer.ReadToEnd();
Match componentNameMatch = regular.Match(contents);
className = componentNameMatch.ToString().Replace("{", "");
}
return className;
}
public class ExportEntry {
public string RelativepathToExportDirectory { get; set; }
private string _ClassName;
public string ClassName {
get { return _ClassName; }
set { _ClassName = value.Trim(); }
}
/// <summary>
/// Returns the formatted export entry
/// e.g. " export {MyComponents} from './Components/my-component.component' "
/// </summary>
/// <returns></returns>
public override string ToString() {
// export { AppComponent} from './my-template/my-template.component'
return String.Format("export {{ {0} }} from '.{1}';", this.ClassName, this.RelativepathToExportDirectory).Replace('\\', '/');
}
}
實現這一點的一個簡單方法是使用 Typescript v2.* 的路徑,就像這里使用的一樣: https : //github.com/MarkPieszak/aspnetcore-angular2-universal
總之,您可以將 index.ts 文件添加到文件夾中,例如
export * from './app.component'
export * from './shared/other.component'
然后讓 webpack 來處理它。 你應該添加到你的 webpack.config.js
const clone = require('js.clone');
const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin');
const TsConfigPathsPlugin = require('awesome-typescript-loader').TsConfigPathsPlugin;
[...]
const config = setTypeScriptAlias(require('./tsconfig.json'), {
[...]
plugins: [
new ContextReplacementPlugin(
// The (\\|\/) piece accounts for path separators in *nix and Windows
/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
root('./ClientApp')
),
new TsConfigPathsPlugin({
tsconfig: 'tsconfig.json'
}), [...]
使用這些幫助功能:
function setTypeScriptAlias(tsConfig, config) {
var newConfig = clone(config);
newConfig = newConfig || {};
newConfig.resolve = newConfig.resolve || {};
newConfig.resolve.alias = newConfig.resolve.alias || {};
var tsPaths = tsConfig.compilerOptions.paths;
for (var prop in tsPaths) {
newConfig.resolve.alias[prop] = root(tsPaths[prop][0]);
}
return newConfig;
}
function root(args) {
args = Array.prototype.slice.call(arguments, 0);
return path.join.apply(path, [__dirname].concat(args));
}
最后在你的 tsconfig.js 中定義路徑
"compilerOptions": {
[...]
"paths": {
"app": [ "./ClientApp/app" ]
},[...]
然后你可以通過“app”路徑導入
import { AppModule } from 'app';
我能夠通過將以下內容添加到tsconfig.app.json
來tsconfig.app.json
:
"compilerOptions": {
"baseUrl": "./",
...
}
如https://www.typescriptlang.org/v2/en/tsconfig#moduleResolution 中所述。 它已經在tsconfig.json
,但顯然僅用於IDE 集成。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.