如何跨角度模块正确导入/导出类? [英] How to properly import/export classes across angular modules?

查看:77
本文介绍了如何跨角度模块正确导入/导出类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题来自企业应用程序的上下文.

This question comes from the context of Enterprise Application.

从我读过的所有书籍和有关角度应用程序的在线示例中,每次我们创建类(组件,服务,实体等)时,我们都会根据类型定义导出它们,然后直接将它们导入无论我们需要两个类属于相同或不同的角度模块,我们都需要引用的地方(类似于在C#上使用名称空间).

From all the books I've read and online samples I've seen about angular applications, each time we create a class (component, service, entity, etc.) we export them on the type definition and then directly import them wherever we require a reference (similar to using namespaces on C#) regardless both classes belongs to the same or distinct angular modules.

例如:

// In 'Commons/logger.service.ts'
export class LoggerService { ... }

// In 'Core/common.service.ts'
export class CommonService { ... }

// In 'Products/' module
import { LoggerService } from '../Commons/logger.service'
import { CommonService } from '../Core/common.service'

export class ProductComponent { ... }

我开始从事一个(大型)企业应用程序项目,并注意到一种我从未见过的方法,他们创建了文件来收集每种类型的类(服务,实体,方法参数,组件),并分别导出它们,进行导出.这些文件中的每个文件都放在其相应的角度模块文件上,然后,而不是直接从类型的文件中导入类型,而是从给定的模块中执行导入.

I started working on a (big) enterprise application project and noticed an approach I had never seen before, they created files to gather each type of class (service, entity, method parameter, component) exporting each one of them, export each one of these files on its corresponding angular module file and then, instead of importing the type directly from the type's file, perform the importing from the given module.

前面的示例将被转换为如下形式:

The previous example would be transformed to something like this:

// In 'Commons/logger.service.ts'
export class LoggerService { ... }

// In 'Commons/services.ts'
export * from './logger.service.ts'
export * from './other.service.ts'
export * from './another.service.ts'

// In 'Commons/commons.module.ts'
export * from 'services.ts'
export * from 'entities.ts'
/* ... */


// In 'Products/' module
import { LoggerService, OtherService } from '../Commons/commons.module'

export class ProductComponent { ... }

鉴于此方法比以前的方法冗长得多,并且在某些情况下会引起尴尬的结果(如果在同一模块中导入类,则会出现循环引用警告)

Given that this approach is much more verbose than the one before and that it provokes awkward results in some cases (cyclic reference warning if importing classes within the same module)

我的问题是:

  1. 从良好的设计或最佳实践的角度,推荐哪种方法?
  2. 与前者相比,此方法是否值得推荐?为什么?在哪些情况下?
  3. 为什么没有在主要文档来源(有角度的在线文档,有角度的书籍等)上引入这种方法?
  4. 这种方法的优缺点是什么.

推荐答案

这是一个称为桶文件的概念.这些文件使导入类更加方便.对于Angular而言,这并不是一个概念.在TypeScript中使用它们似乎是一种最佳实践.

This is a concept known as a barrel file. These files make importing classes more convenient. It isn't a concept to Angular alone. It seems to be a best practice in TypeScript to use them.

当您有一个较小的项目时,创建这些文件可能不会带来太多好处,但是当它们与多个团队成员一起进行较大的项目时,它们会非常有用.以下是我所知道的一些优点/缺点.

When you have a smaller project, you may not see much of a benefit of creating these files, but they come in to be super helpful when working on larger projects with multiple team members. Below are some of the pros/cons that I'm aware of.

专业版:模块内部知识较少

当一个组件需要引用某个东西时,它不必不必知道类等所在的确切文件.当您不对模块中的东西进行打包时,则该文件之外的所有其他文件模块将需要确切知道哪个文件(包括子路径)包含该项目.如果将物品装入单个模块桶中,则只需要知道它来自哪个模块即可.这也给您带来了重构模块的好处,即不需要在文件移动时确保路径得到更新(您的工具可能会也可能不会对此有所帮助).

When a component needs to have a reference to something, it shouldn't have to know what exact file the class, etc. is in. When you don't barrel the stuff within a module then every other file outside of the module will need to know exactly what file (including the sub path) contains that item. If you barrel the items up into a single module barrel, you simply need to know what module it is from. This also gives you the benefit of refactoring a module not requiring you to make sure the path gets updated if the file moves (your tooling may or may not help out with this).

// without barrel files
import { Class1 } from 'app/shared/module1/subpath1/subpath2/class1.service';

// using barrel files
import { Class1 } from 'app/shared/module1';

专业版:明确导出模块外部

另一个好处是,一个模块可以包含一堆类,接口等,这些类,接口等实际上只能在该模块中使用.通过为模块创建桶文件,您可以让其他开发人员知道在模块外部使用的含义.此外,您还让他们确切地知道要使用哪些项目,因此他们无需四处寻找所需的接口(同样,您的工具可能会也可能不会对此提供帮助).

Another benefit is that a module may contain a bunch of classes, interfaces, etc. that really are only meant to be used within that module. By creating a barrel file for a module, you are letting other devs know what is meant to be used outside of the module. Additionally, you are letting them know exactly what items there are to be used, so they don't need to hunt around to find an interface that they need (again, your tooling may or may not assist in this).

// export these items from module as others need to have references to these
export { ExampleModule } from './example.module';
export { ExampleService } from './example.service';
export { ExampleInterface } from './example.model';

// these also exist in module but others don't need to know about them
// export { ExampleComponent } from './example.component';
// export { Example2Service } from './example2.service';
// export { ExampleInterface2 } from './example.model';

专业版:清洁进口

我要提到的最后一个好处是,它有助于清理您的进口商品.它不仅可以使您更清楚地了解哪些项目来自哪些模块,还可以使导入的from部分更短,因为您无需遍历子目录等.惯例似乎是将Barn文件放在文件夹中index.ts,因为当给定要导入的文件夹时,TypeScript编译器将默认查找该文件.

The final benefit I'll mention is that it helps to clean up your imports. Not only does it make it more clear what items come from what modules, it also helps to make the from portion of your import much shorter as you don't need to traverse down sub directories, etc. As a note, the best practice seems to be to have the barrel file be index.ts in a folder since the TypeScript compiler will look for that file as default when given a folder to import from.

// without barrel files (hopefully they would be not randomly ordered to make it even harder...)
import { Class1 } from 'app/shared/module1/subpath1/subpath2/class1.service';
import { Class2 } from 'app/shared/module1/subpath1/class2.component';
import { Interface1 } from 'app/shared/module1/module1.model';
import { Class3} from 'app/shared/module2/subpath3/class3.service';
import { Interface2 } from 'app/shared/module2/module2.model';

// using barrel files
import { Class1, Class2, Interface1 } from 'app/shared/module1';
import { Class3, Interface2 } from 'app/shared/module2';

缺点:附加文件

在尝试确定缺点时,我唯一想到的就是您正在为每个模块创建另一个文件(或者可能是子文件夹,具体取决于您要执行的操作).据我所知,它没有运行时或编译时的影响.

In trying to identify the cons, the only thing that I can think of is that you are creating another file for each module (or maybe sub folder depending on how you want to do it). It has no run-time or compile-time effect as far as I am aware though.

这篇关于如何跨角度模块正确导入/导出类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆