"时间的教训" - 何为时间的教训呢?
所谓时间的教训,那就是,不论这个东西难或者易,本来在一定的时间内,甚至小于这个一定的时间就可以完成的,而你偏偏用了2倍甚至三倍的时间来完成,更有甚者根本完不成的东西,但是最后解决了之后,你却发现,只是因为你少想了一点,只需要再多想一点点,哪怕多往前看一点点,你就能解决了的小功能,或者小组件,或者一段代码。
犯这些错误不要紧,要紧的是自己要将这些错误记录下来,这些都是时间的教训,要记住。
下面开始,时间的教训的记录,如果同样的错误我犯过不是第一次,那么我也会记录下来,我到时要看看,自己是不是会在同一个地方摔倒N次?
大意失荆州
背景:
我只是要写一个简单的组件sino-loading-hint
,这个组件,从外部接收参数state:number
,1:加载中;2:数据获取成功,正常展示;3:加载失败。另外一个参数loadingTitle
如果没有传入参数的则使用默认值,如果传入参数的话,则使用传入的参数。
就这么一个简单的组件,而且只是实现第一步,展示“loading...”字样。
出错的代码
最外侧的使用地方:
<div style="border-bottom: 0.55px solid #c8c7cc;">
<sino-loading-hint>
<sino-data-service [name]="config.name"
[baseUrl]="config.baseUrl"
[idPropertyName]="config.idPropertyName"
[subflagPropertyName]="config.subflagPropertyName">
<!--<sino-list type="todos"></sino-list>
<sino-list type="drafts"></sino-list>-->
<sino-list type="related" (onVoted)="onVoted($event)"></sino-list>
</sino-data-service>
<sino-loading-hint>
</div>
真正sino-loading-hint
该使用的地方:
<sino-loading-hint [state]="state" loadingTitle="loading...">
<h2>{{title}}</h2>
<div *ngFor="let item of datas; let i = index" (click)="toDetail(item, i)">
<h3>{{item.title}}</h3>
<p>
来自:{{item.ngDepartmentName}}的发文申请<br/>
<span>发送时间:{{item.signDate}}</span>
</p>
</div>
</sino-loading-hint>
出现的错误是,无论我如何传递参数,
loadingTitle
和state
的值根本没有改变,而且我也打断点调试了,值是传递过来了,可是就是不显示,在这个地方白白浪费了一晚上的时间。
教训
其实这个地方,我可以有两种方式可以很快的定位到问题的所在。
- 第一种方式就是,我去往上看,具体哪里使用的
sino-list这个组件
,去找到根本的使用它的地方,这个错误也是这样解决的。
2.第二种方式就是,使用Angury这个调试,去查看其中的component树,这样就能很快的查找问题。
所有有工具可以使用的时候,一定要好好的利用工具!!
DI
- 不依赖DI系统的service的依赖注入方式
- 依赖DI系统的service的依赖注入方式
不依赖DI系统的service的依赖注入方式
BaseDataService单元测试的时候,应该是自己将service创建(new)出来,因为我的BaseDataService 不是依赖angular的DI系统来生成的。
service = new BaseDataService(config, http);
当将sino-list
作为sino-base-data-servie
的子组件后,就能获取到父组件中的service,所以这样写之后,单元测试就变得好些的多了。
依赖DI系统的service的依赖注入方式
就是通过模块的封装,将BaseDataService
注入到了angular的DI系统中,这样在模块中的所有组件,都可以通难过angular的DI注入的方式获取到BaseDataService
了,这样就非常的方便了。
@Injectable()
export class BaseDataService {
remoteService: BaseDataRemoteService;
constructor(private config: ModuleConfig, private http: Http) {
this.config.baseUrl = config.baseUrl || config.name;
this.remoteService = new BaseDataRemoteService(this.config.baseUrl, this.config.idPropertyName, this.http);
}
BaseDataService在构造函数中所需要的ModuleConfig和Http都在模块初始化的时候就providers到了模块中,所以可以使用angular的DI系统来进行依赖注入,所以可以在模块中的任何子组件中进行依赖注入,随意使用。
@NgModule({
imports: [
CommonModule,
IonicModule,
],
declarations: [
SinoListComponent,
SinoItemDetailComponent,
SinoLoadingHintComponent,
],
entryComponents: [
SinoItemDetailComponent,
],
exports: [SinoListComponent, SinoItemDetailComponent],
providers: [
BaseDataService,
],
})
export class CrudModule {
static forRoot(config: any, routeConfig?: any): ModuleWithProviders {
return {
ngModule: CrudModule,
providers: [
{
provide: ModuleConfig, // 注入了进来
useValue: config,
}
]
};
}
}
DI注入错误例子
e.g. - service没有写@injectable()
这个例子的错误是,在模块级别注册了类提供商也就是providers:[WorkflowService]
,但是一直报👇这个错误:
造成这个错误的原因就是👇因为缺少红框框起来的code!
e.g. - DI的时候,没有从根本使用的地方进行依赖注入
这就导致了,在最里面的基类调用不到使用的方法。👇是错误:
这个错误一直说的是没有add
这个方法。也就是说sinoButtonsComponent
没有被依赖注入进来。
👇是code:
知识点1
放在位置1的话,创建几个crud模块BaseDataService就会创建几次,而放在forRoot方法中,如果在发文模块中在创建一个小的crud模快的时候是不会调用forRoot方法的,那么也就不会再次创建BaseDataService。
未完待续...