有人可以解释一下Console.WriteLine
和call void [mscorlib]System.Console::WriteLine(string)
代表的是什么吗?
我一直在观看有几个项目正在使用这种方法来构建其角度项目。
SharedModule
,CoreModule
,imports
?答案 0 :(得分:112)
CoreModule
应该只有services
,并且只能在AppModule
中导入一次。SharedModule
应该包含services
以外的所有内容,并且可以在需要共享内容的所有模块中导入(也可以是AppModule
)。可是:
真实世界的模块通常是有意偏离[上述]指南的混合模块。这些准则不是法律;除非你有充分的理由不遵守它们。
所以,在完成整个NgModules' docs(以及其他一些事情来理解背景)之后,我很容易找到第2和第3个问题的答案 there。他们是:
- 使用您在应用中随处可用的
SharedModule
,components
和directives
创建pipes
。该模块应完全由declarations
组成,其中大部分都是导出的。SharedModule
可能会重新导出其他窗口小部件模块,例如CommonModule
,FormsModule
和模块以及您最常使用的UI控件。- 由于之前解释的原因,
SharedModule
不应该有providers
。任何进口或再出口的模块也不应该有供应商。如果您偏离本指南,请了解您正在做什么以及为什么。- 导入功能模块中的
SharedModule
,包括应用启动时加载的功能模块和稍后延迟加载的功能模块。
- 为应用程序启动时加载的单件服务创建
CoreModule
providers
。- 仅在根
CoreModule
中导入AppModule
。切勿在任何其他模块中导入CoreModule
。- 考虑将
CoreModule
设为纯服务模块而不使用declarations
。
虽然这些比上面的TLDR
版本更详细,但您现在可以继续并继续编码,但它提到了一些您必须阅读文档才能理解的内容(即'小部件模块和#34 ;,"先前解释过的原因","纯粹的服务模块"),它也没有回答你的第一个问题。
所以,让我们试着这样做!
您不需要两个模块。这就是文档中的内容:
在具有少量组件的简单应用程序中,您只需要根模块。
话虽如此,首先提出另一个问题非常重要:
对此的基本解释恰好在文档中的上述陈述之后:
随着应用程序的增长,您将根模块重构为表示相关功能集合的要素模块。然后,将这些模块导入根模块。
但你问'为什么?"这需要的不仅仅是基本的解释。因此,让我们开始解释如果您的应用程序开始增长并且不将功能分离到功能模块中,可能会发生什么问题:
虽然你可能认为上面的例子并不完全是问题(也许你独自工作并且可以忍受自己的混乱,或者你的所有队友也很混乱),但请记住,其他人肯定不同意你和这就是为什么你"一直在看几个项目......使用这种方法" 。
考虑到您同意并希望将不断增长的应用程序组织到功能模块中,请注意以下文档中的声明:
根模块和功能模块共享相同的执行上下文。它们共享相同的依赖注入器,这意味着一个模块中的服务可供所有人使用。
这些模块具有以下重大技术差异:
- 启动根模块以启动应用程序;导入功能模块以扩展应用程序。
- 功能模块可以从其他模块中公开或隐藏其实现。
永远不会忘记的信息: "一个模块中的服务可用于所有[模块]",而其他内容,如组件,指令和管道必须注入每个想要使用它们的模块。
通过这些信息,我们现在可以通过回答以下问题更接近您想要了解的内容:
所有功能模块是否相同?
不!至少建议它们不应该相等,因为建议您不应该只拥有根模块,但是你可以做任何你做的事情想。但你不应该。
文档中有一个表格,显示建议的要素模块组之间的差异。我们来看一下它的摘录:
FEATURE SHOULD HAVE SHOULD HAVE SHOULD HAVE
MODULE DECLARATIONS PROVIDERS EXPORTS
Domain Yes Rare Top component
Routed Yes Rare No
Routing No Yes (Guards) RouterModule
Service No Yes No
Widget Yes Rare Yes
注意!他们非常清楚这是一个......
...基于早期使用经验的初步指导 NgModules在一些应用程序中。
所以,再一次,你不会坚持这个指导方针并且可能会发生偏差,但你应该知道你在做什么以及为什么。
现在让我们分析一下这张表:
Service
和Widget
组是每个列中唯一具有完全不同值的组。Domain
和Routed
组基本上与Widget
组相同,只有有限或无出口。Routing
组基本上是Service
组,具有导出例外,仅限于特定提供商。因此,让我们将Domain
,Routed
和Routing
组视为Service
或Widget
的变体,并关注最后两个
服务应引起您的注意。请记住,您永远不应忘记一个模块中的服务可用于所有[模块]"?好吧,如果他们调用功能模块组Services
,那是因为它必须与其他模块隔离,因此只能导入一次。例如,您可以拥有UserModule
,其中包含SignUpService
,SignInService
,SocialAuthService
和UserProfileService
等服务。无论您在何处导入UserModule
,其所有服务都将在应用范围内提供。根据上表,它不应该有声明,也不应该只有提供者。
小部件听起来更通用,但它应该告诉你一些事情。请记住,您也应该永远不要忘记"其他内容,例如组件,指令和管道必须注入每个想要使用它们的模块中。" ?所以这是你将用于那些模块的类型。例如,您可以拥有UIModule
ButtonComponent
,NavComponent
,SlideshowComponent
,HighlightLinkDirective
,CtaPipe
。每次您需要使用其中一个或所有导出的元素时,只需导入UIModule
。
所以,基本上,由于Angular处理服务的方式,当你开始将功能分成功能模块时,你必须将服务隔离到他们自己的模块中,而其他东西可以按照你的意愿在它们之间进行组织。
CoreModule
和SharedModule
如何适应这种情况?
为了简单起见,CoreModule
是Service
模块,SharedModule
是Widget
模块。这就是为什么你应该在AppModule
中导入第一个,而在需要它的所有模块中导入后者。从上面的示例中,UserModule
将导出CoreModule
,UIModule
导出SharedModule
。
但是,如前所述,这些是指导方针,并且可能会发生偏差,即使在他们自己的例子中,他们在CoreModule
中声明了组件,但有一个观察结果:
此页面示例通过声明和导出[在
CoreModule
]两个仅在AppModule声明的根AppComponent中使用的组件来脱离该建议。严格遵守本指南的人会在AppModule中声明这些组件。
就我个人而言,我认为最大的困惑在于命名选择。一般来说,人们会认为应用程序核心的所有内容(即用户内容,导航栏,加载栏,烤面包机等)都会进入CoreModule
以及所有共享的内容多个功能将进入SharedModule
。
这实际上并不是真的,有点误导,因为所有服务都是在所有模块之间共享的,而且#34;本质上是"并且SharedModule
中不应包含任何服务,NavbarComponent
也是应用核心的一部分,CoreModule
中不应包含任何组件。
无论如何,建议遵循指南,直至找到不这样做的理由。
以上表格的其余部分有助于更好地理解指南:
FEATURE CAN BE SOME
MODULE IMPORTED BY EXAMPLES
Domain Feature, AppModule ContactModule (before routing)
Routed Nobody ContactModule, DashboardModule,
Routing Feature (for routing) AppRoutingModule, ContactRoutingModule
Service AppModule HttpModule, CoreModule
Widget Feature CommonModule, SharedModule
干杯!
答案 1 :(得分:4)
我自己也使用这种方法,这就是为什么/如何:
(这是一种方法,也许其他人会有!=想法很好)
我希望app.module
尽可能保持清洁。如果你想使用通用或用AOT构建项目(当不使用angular-cli时),你可能需要一个重复的app.module,所有这些文件都有很小的变化。
因此,如果您将许多模块导入app.module
,则必须在不同的文件中保持该列表的最新状态。
以下是core.module
:
将您想要导入的每个模块放在此处一次。主要是具有forRoot
方法的模块(导出其提供者的方法,应该只导入一次)。
在此处导入您的提供商。 (例如,如果您使用ngrx,请在此处声明您的商店。)
然后,shared.module
:
将您需要重用的每个模块放在您的应用程序中( CommonModule,HttpModule,RouterModule,MaterialModule,FlexLayoutModule等)。
最后,app.module
:
导入app.module
core.module
仅限 。 CoreModule只能加载一次。在所有子公共中,您可以加载SharedModule
。
使用该配置,如果您需要为通用或其他创建另一个app.module,则无需在不同文件中复制和维护整个模块列表。只需导入core.module
,就可以了。
答案 2 :(得分:0)
根据Angular的样式指南和我的观察:
CoreModule(core.module.ts) 核心功能模块
此处应提供所有应单身的服务。例如
HelperService
,LoggerService
。
应用范围广告组件应在CoreModule
中声明,例如header
,footer
。
CoreModule提供一个或多个单例服务。 Angular使用app根注入器注册提供者,使每个服务的单例实例可用于任何需要它们的组件,无论该组件是否被急切地或懒惰地加载。
只有根AppModule才能导入CoreModule。
SharedModule(shared.module.ts) 共享功能模块
在共享模块中声明组件,指令和管道,这些项目将被其他功能模块中声明的组件重用和引用
建议避免在共享模块中使用services
。服务通常是为整个应用程序或特定功能模块提供一次的单例。
所有要素模块所需的模块应该在像CommonModule
&的共享模块中导入。 FormsModule
。
可共享组件/管道/指令的声明应该在SharedModule中。如果这些组件/管道/指令需要由其他功能模块使用,则必须将其导出。
如果使用Material,则最好导入和重新导出Angular Material组件。
参考文献: CoreModule,SharedModule
答案 3 :(得分:-1)
我认为这个问题过于笼统,对于一般性问题,你会得到一般答案......例如,共享模块是为了保留几个组件/模块使用的东西:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
//import { AwesomePipe } from './awesome.pipe';
//import { HighlightDirective } from './highlight.directive';
@NgModule({
exports: [ /*AwesomePipe, HighlightDirective,*/
CommonModule, FormsModule, ReactiveFormsModule ]
})
export class SharedModule { }
CoreModule更像您认为的页面核心(Nav,Spinner,Alert ...)。这非常具有启发性,取决于我的想法。例如:
import { NgModule, Optional, SkipSelf } from '@angular/core';
import { NavComponent } from './nav/nav.component';
import { SpinnerComponent } from './spinner/spinner.component';
import { SpinnerService } from './spinner/spinner.service';
import { AlertComponent } from './alert/alert.component';
import { AlertService } from './alert/alert.service';
import { SharedModule } from '../shared/shared.module';
import { CoreRoutingModule } from './core-routing.module';
@NgModule({
imports: [
SharedModule,
CoreRoutingModule,
],
exports: [//Other modules use these components, so we export them
AlertComponent,
NavComponent,
SpinnerComponent,
],
declarations: [ //we use them in CoreModule, so we declare them
AlertComponent,
NavComponent,
SpinnerComponent,
],
providers: [
SpinnerService,
AlertService,
]
})
export class CoreModule {
constructor (@Optional() @SkipSelf() parentModule: CoreModule) {
if (parentModule) {
throw new Error(
'CoreModule est déjà chargé. Importer le uniquement dans AppModule');
}
}
}