在Angular 2中,我试图按照documentation中的描述让桶工作。
官方Angular 2 style guide谈论使用桶来汇总和缩短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';
但是,要使用桶,导入定义将如下所示:
import {
HeroService,
HeroesComponent,
HeroDetailComponent
} from '../app';
from '../app';
行表示名称为index.ts
的文件,其中包含导出/导入的组件:
// app/index.ts
export * from './hero-detail.component';
export * from './hero.service';
export * from './heroes.component';
但在所有情况下,这对我都不起作用。我通过明确包含index
文件名的唯一方法是:
import {
HeroService,
HeroesComponent,
HeroDetailComponent
} from '../app/index'; // have to indicate 'index'
如何在隐含index.js
文件名的情况下使其工作?
答案 0 :(得分:8)
AFAIK SystemJS
本身并不了解桶,Webpack
。
顺便说一句,在深入了解Angular
为它的模块做了什么之后,我找到了一个解决方案
在system.config.js
中,您需要执行以下操作
注意: index.ts
的父目录是 barrel
,ICYDK
// 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'
};
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' }
};
packageNames
,就像角度
var packageNames = [
'@angular/common',
...
'@angular/upgrade',
'barrel'
];
你已经完成了。
##
为什么我们使用packageNames
代替packages
是因为您必须为每个{ main: 'index.js', defaultExtension: 'js' }
重复barrel
(文件名和扩展名),但有角度已经在做通过循环使用它。
packageNames.forEach(function(pkgName) {
packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
});
最终将它们添加到packages
。
<强>用法强>
import {something} from '../../barrel'; // relative path to directory of barrel
和
import {something} from 'barrel'; // name of barrel
两者都有效,但后者无法提供intellisense
并显示错误cannot find module 'barrel'
。我没有解决方案。但是当我这样做时,我会添加它。
答案 1 :(得分:5)
This is all seems overly complicated.
There's no need to add anything to map, since app
, which should be containing everything is already in there. We can just create an array with the subpackages. In my case that was:
var subPackageNames = [
'+heroes',
'+heroes/shared',
'+heroes/hero-list',
'+heroes/hero-detail',
'+heroes/hero-dashboard'
];
and then modify the provided packIndex
function to take a second argument
function packIndex(pkgName, baseName) {
packages[baseName+pkgName] = { main: 'index.js', defaultExtension: 'js' };
}
now we can add our sub packages to the packages object just like angular does.
ngPackageNames.forEach(name => setPackageConfig(name, '@angular/'));
subPackageNames.forEach(name => packIndex(name, 'app/'));
答案 2 :(得分:0)
我遵循 A_Singh的想法,但由于我的systemjs.config.js
不同,因此我必须根据tour-of-heroes教程进行调整。 (2016年6月3日 - RC1)。
此修改有效,在VisualStudio Code下,Intellisense
对我来说效果很好。
我也一直在使用目录结构来保持模块化,这里的桶是有意义的。
这就是我修改tour-of-heroes
项目
app
|- main.ts
|- app.component.ts
|- app.component.css
|-+ components
| |-+ dashboard
| |- dashboard.component.css
| |- dashboard.component.html
| |- dashboard.component.ts
|-+ modules
| |-+ hero
| |- index.ts <-- //The barrel for the Hero module
| |-+ components
| | |-+ detail
| | | |- hero-detail.component.css
| | | |- hero-detail.component.html
| | | |- hero-detail.component.ts
| | |-+ list
| | |- hero-list.component.css
| | |- hero-list.component.html
| | |- hero-list.component.ts
| |-+ models
| | |- hero.model.ts
| |-+ services
| |- hero.service.ts
| |- mock-heroes.ts
此处更新了systemjs.config.js
(function(global) {
// map tells the System loader where to look for things
var map = {
'app': 'app', // 'dist',
'@angular': 'node_modules/@angular',
'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
'rxjs': 'node_modules/rxjs',
// The added barrel map
'hero': 'app/modules/hero'
};
var packages = {
'app': { main: 'main.js', defaultExtension: 'js' },
'rxjs': { defaultExtension: 'js' },
'angular2-in-memory-web-api': { defaultExtension: 'js' },
// The package definition (notice I had to declare index.js)
'hero': { main: 'index.js', defaultExtension: 'js' }
};
var ngPackageNames = [
'common',
'compiler',
'core',
'http',
'platform-browser',
'platform-browser-dynamic',
'router',
'router-deprecated',
'upgrade',
];
ngPackageNames.forEach(function(pkgName) {
packages['@angular/'+pkgName] = { main: pkgName + '.umd.js', defaultExtension: 'js' };
});
var config = {
map: map,
packages: packages
}
System.config(config);
})(this);
最后,这是app.component.ts
现在的样子
import { Component } from '@angular/core';
import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from '@angular/router-deprecated';
import { DashboardComponent } from './components/dashboard/dashboard.component';
import { HeroListComponent, HeroDetailComponent, HeroService } from './modules/hero';
@Component({
selector: 'my-app',
directives: [ROUTER_DIRECTIVES],
providers: [
ROUTER_PROVIDERS,
HeroService
],
template: `
<h1>{{title}}</h1>
<nav>
<a [routerLink]="['Dashboard']">Dashboard</a>
<a [routerLink]="['HeroList']">Hero List</a>
</nav>
<router-outlet></router-outlet>
`,
styleUrls: ['app/app.component.css']
})
@RouteConfig([
{
path: '/dashboard',
name: 'Dashboard',
component: DashboardComponent,
useAsDefault: true
},
{
path: '/hero-list',
name: 'HeroList',
component: HeroListComponent
},
{
path: '/detail/:id',
name: 'HeroDetail',
component: HeroDetailComponent
}
])
export class AppComponent {
title: string = 'Tour of Heroes';
}
最后一点,你可以进行导入
import { HeroListComponent, HeroDetailComponent, HeroService } from 'hero';
然而,它会起作用,因为它在技术上不是NodeJS导入的模块,VS Code抱怨它无法找到它。
所以,我个人的选择是留下明确的./modules/hero
,它帮助我知道它是我的模块之一而不是导入的模块,我很高兴看不到红线。