如何仅按文件夹名称导入桶?

Bra*_*Rem 27 javascript angular

角2桶

在Angular 2中,我正试图让文件中描述的桶工作.

官方的Angular 2风格指南讨论了使用桶来汇总和缩短import陈述.

我发现对于一些桶,我必须index在导入时指定JavaScript文件名,而不是必须的.

桶示例

(修改第12行的app/app.component.ts文件)

在我的实际项目中遇到这个(在ASP.NET下运行)后,我创建了一个Plunker来演示我修改了英雄之旅以使用桶的问题.

在app/app.component,导入的基本方法是这样的:

import { HeroService } from './hero.service';
import { HeroesComponent } from './heroes.component';
import { HeroDetailComponent } from './hero-detail.component';
Run Code Online (Sandbox Code Playgroud)

但是,要使用桶,导入定义将如下所示:

import {
  HeroService,
  HeroesComponent,
  HeroDetailComponent
} from '../app';
Run Code Online (Sandbox Code Playgroud)

该from '../app';行表示名称中index.ts包含导出/导入组件的文件:

// app/index.ts
export * from './hero-detail.component';
export * from './hero.service';
export * from './heroes.component';
Run Code Online (Sandbox Code Playgroud)

但在所有情况下,这对我都不起作用.我正确使用它的唯一方法是明确包含index文件名:

import {
  HeroService,
  HeroesComponent,
  HeroDetailComponent
} from '../app/index'; // have to indicate 'index'
Run Code Online (Sandbox Code Playgroud)

如何在index.js隐含文件名的地方使用它?

Ank*_*ngh 8

AFAIK SystemJS本身并不了解桶,但Webpack确实如此.顺便说一句,在深入了解Angular它的模块之后,我找到了一个解决方案


在system.config.js你需要做以下事情

注意:a的父目录index.ts是barrelICYDK

  • 添加桶的路径

// map tells the System loader where to look for things
  var map = {
    'app':                        'app', // 'dist',
    'rxjs':                       'node_modules/rxjs',
    'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
    '@angular':                   'node_modules/@angular',

    'barrel':                 'path/to/your/barrel'
  };
Run Code Online (Sandbox Code Playgroud)
  • 不要添加桶packages (后面会说明)##

// packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app':                        { main: 'app/boot.js',  defaultExtension: 'js' },
    'rxjs':                       { defaultExtension: 'js' },
    'angular2-in-memory-web-api': { defaultExtension: 'js' }
  };
Run Code Online (Sandbox Code Playgroud)
  • packageNames像角度一样添加它们

var packageNames = [
    '@angular/common',
    ...
    '@angular/upgrade',

    'barrel'
  ];
Run Code Online (Sandbox Code Playgroud)

而且你已经完成了.


##

为什么我们使用packageNames而不是packages因为你必须{ main: 'index.js', defaultExtension: 'js' }为每个重复(文件名和扩展名)barrel,但是角度已经通过循环使用它来完成.

packageNames.forEach(function(pkgName) {
    packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
});
Run Code Online (Sandbox Code Playgroud)

哪个最终将它们添加到packages.


用法

import {something} from '../../barrel'; // relative path to directory of barrel
Run Code Online (Sandbox Code Playgroud)

和

import {something} from 'barrel'; // name of barrel
Run Code Online (Sandbox Code Playgroud)

两者都有效,但后者无法提供intellisense并显示错误说明cannot find module 'barrel'.我没有解决方案.但是当我这样做时我会添加它.

  • 不会是新的[typescript 2模块分辨率增强](https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#module-resolution-enhancements-baseurl-path-mapping-rootdirs-and -racing)从'桶'问题中帮助`import {something}? (2认同)

MrL*_*Loh 5

这一切看起来都过于复杂.

没有必要添加任何东西来映射,因为app它应该包含所有内容.我们可以用子包创建一个数组.在我的情况下是:

var subPackageNames = [
        '+heroes',
        '+heroes/shared',
        '+heroes/hero-list',
        '+heroes/hero-detail',
        '+heroes/hero-dashboard'
    ];
Run Code Online (Sandbox Code Playgroud)

然后修改提供的packIndex函数以获取第二个参数

function packIndex(pkgName, baseName) {
    packages[baseName+pkgName] = { main: 'index.js', defaultExtension: 'js' };
}
Run Code Online (Sandbox Code Playgroud)

现在我们可以像angular一样将子包添加到packages对象中.

ngPackageNames.forEach(name => setPackageConfig(name, '@angular/'));
subPackageNames.forEach(name => packIndex(name, 'app/'));
Run Code Online (Sandbox Code Playgroud)