簡體   English   中英

TypeScript:如何不使用相對路徑來導入類?

[英]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# 編寫的,但歡迎您用您喜歡的任何語言重新編寫它。

這是 GitHub 上的示例

它允許您在每個組件目錄的根目錄中有一個導出文件,您可以通過執行以下操作來導入該文件:

import {LoginPage, HomePage} from '../pages/export'

或者

import {NavBarComponent, HeroCardComponent} from '../controls/export'

假設您在特定目錄中有多個組件,例如:

  • 應用程序/頁面/登錄頁面/登錄頁面.ts
  • app/pages/home-page/home-page.ts
  • 應用程序/控件/導航欄.ts
  • 應用程序/控件/hero-card.ts

如果你運行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.jsontsconfig.app.json

"compilerOptions": {
  "baseUrl": "./",
  ...
}

https://www.typescriptlang.org/v2/en/tsconfig#moduleResolution 中所述 它已經在tsconfig.json ,但顯然僅用於IDE 集成

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM