Javascript 如何在Angular:NullInjectorError:ChangeDetectorRef中强制更新依赖项注入组件
我有两个UI组件 表3页面:保存数据 表2页面:加载数据 将TAB2页注入TAB3页 当数据通过Tabd3Page保存时,我尝试在Tab2Page中自动加载数据 目前,当我在tab3中保存数据时,tab2不会自动更新,直到我手动刷新页面浏览器。有没有办法强制呈现像react as SetState()中那样的页面 以下是组件选项卡3页Javascript 如何在Angular:NullInjectorError:ChangeDetectorRef中强制更新依赖项注入组件,javascript,angular,ionic-framework,Javascript,Angular,Ionic Framework,我有两个UI组件 表3页面:保存数据 表2页面:加载数据 将TAB2页注入TAB3页 当数据通过Tabd3Page保存时,我尝试在Tab2Page中自动加载数据 目前,当我在tab3中保存数据时,tab2不会自动更新,直到我手动刷新页面浏览器。有没有办法强制呈现像react as SetState()中那样的页面 以下是组件选项卡3页 @Component({ selector: 'app-tab3', templateUrl: 'tab3.page.html', styleUrls
@Component({
selector: 'app-tab3',
templateUrl: 'tab3.page.html',
styleUrls: ['tab3.page.scss']
})
export class Tab3Page implements OnInit {
pics: Picture[] = [];
constructor(public fileservice: FileService, private tab2: Tab2Page) {}
ngOnInit() {
console.log('ng init');
this.pics = PICS;
}
saveContent(pic: Picture) {
this.fileservice.savefile(pic);
this.tab2.updatePics();
this.tab2.refreshComponent();
}
}
下面是组件选项卡2页
@Component({
selector: 'app-tab2',
templateUrl: 'tab2.page.html',
styleUrls: ['tab2.page.scss']
})
export class Tab2Page implements
OnInit,
OnChanges {
@Input() pics: Picture[];
constructor(public fileservice:FileService, private cdr: ChangeDetectorRef) { }
// constructor(public fileservice: FileService) { }
ngOnInit() {
console.log('ng init');
this.updatePics();
}
ngOnChanges(changes: SimpleChanges) {
// changes.prop contains the old and the new value...
console.log('changes', changes);
}
async updatePics() {
this.pics = await this.fileservice.getSavedPics();
}
refreshComponent() {
this.cdr.detectChanges();
console.log('component refresh triggred');
}
}
<ion-list *ngFor="let pic of pics">
<ion-item-sliding>
<ion-item>
<ion-grid>
<ion-row>
<ion-col size="3">
<ion-thumbnail>
<img [src]="(pic.url | safeurl)">
</ion-thumbnail>
</ion-col>
<ion-col size="9">
<ion-label>{{pic.name}}</ion-label>
</ion-col>
</ion-row>
</ion-grid>
</ion-item>
<ion-item-options side="end">
<ion-item-option>Delete</ion-item-option>
</ion-item-options>
</ion-item-sliding>
</ion-list>
数据通过组件Tab2Page中的pics变量以Html格式绑定,如下所示
@Component({
selector: 'app-tab2',
templateUrl: 'tab2.page.html',
styleUrls: ['tab2.page.scss']
})
export class Tab2Page implements
OnInit,
OnChanges {
@Input() pics: Picture[];
constructor(public fileservice:FileService, private cdr: ChangeDetectorRef) { }
// constructor(public fileservice: FileService) { }
ngOnInit() {
console.log('ng init');
this.updatePics();
}
ngOnChanges(changes: SimpleChanges) {
// changes.prop contains the old and the new value...
console.log('changes', changes);
}
async updatePics() {
this.pics = await this.fileservice.getSavedPics();
}
refreshComponent() {
this.cdr.detectChanges();
console.log('component refresh triggred');
}
}
<ion-list *ngFor="let pic of pics">
<ion-item-sliding>
<ion-item>
<ion-grid>
<ion-row>
<ion-col size="3">
<ion-thumbnail>
<img [src]="(pic.url | safeurl)">
</ion-thumbnail>
</ion-col>
<ion-col size="9">
<ion-label>{{pic.name}}</ion-label>
</ion-col>
</ion-row>
</ion-grid>
</ion-item>
<ion-item-options side="end">
<ion-item-option>Delete</ion-item-option>
</ion-item-options>
</ion-item-sliding>
</ion-list>
由于上面的错误建议将ChangeDetectorRef添加为提供程序,因此尝试在模块文件中执行此操作。但在编译中再次出现错误,因为ChangeDetectorRef的提供程序类型不受支持
@NgModule({
imports: [
IonicModule,
CommonModule,
FormsModule,
RouterModule.forChild([{ path: '', component: Tab2Page }])
],
declarations: [Tab2Page, SafeurlPipe],
providers: [ChangeDetectorRef]
})
export class Tab2PageModule {}
**更新(修复)
无法使用组件依赖项注入完成此操作。然而,通过在组件之间使用共享数据服务以及使用rxjs“主题”和订阅,我们能够实现相同的预期结果。在下面的角度文档中可以找到这样做的过程。它需要一点来包装它的头部,但对于动态UI呈现的东西来说非常强大
我仍然有点担心为什么我不能在ionic应用程序中使用ChangeDetectorRef,以防将来需要它。Inject
ChangeDetectorRef
:
constructor(
private cdr: ChangeDetectorRef,
) {}
然后触发更改事件:
async updatePics() {
//do something
this.cdr.detectChanges();
}
对于您的问题,您不需要使用
changeDetectorRef
。这里的问题是,在Tab3Page
中,您试图插入Tab2Page
,并使用它调用Tab2Page
中的函数。不能直接在其他组件中插入组件并使用它们。请参见,以了解组件如何相互交互。您可以使用调用updatePics()
在Tab3Page
中,从构造函数中删除Tab2Page
,并添加ViewChild(从@angular/core
导入)
表3.page.ts
导出类Tab3Page实现OnInit{
图片:图片[]=[];
@ViewChild('tab2')tab2:Tab2Page;
构造函数(公共文件服务:文件服务){}
恩戈尼尼特(){
console.log('nginit');
this.pics=pics;
}
保存内容(图:图片){
这个.fileservice.savefile(pic);
this.tab2.updatePics();
}
}
在html中添加模板变量,以便ViewChild
可以访问该组件
tab3.page.html
还有一种方法可以更新数据。由于pics
是从Tab3Page
传递的Input
,只需将updatePics
从Tab2Page
移动到Tab3Page
并调用它即可
表3.page.ts
导出类Tab3Page实现OnInit{
图片:图片[]=[];
构造函数(公共文件服务:文件服务){}
恩戈尼尼特(){
console.log('nginit');
this.pics=pics;
}
保存内容(图:图片){
这个.fileservice.savefile(pic);
这个.updatePics();
}
异步更新{
this.pics=等待this.fileservice.getSavedPics();
}
}
谢谢,但我在使用ChangeDetectorRef时出错,看起来它与ionic angular有一些问题?您好,谢谢您给我一些建议。我不能使用查看子视图的想法,因为这些选项卡位于不同的路径中,并且它们各自的路径具有不同的UI组件。下一个建议是更新Tab3page UI中的pics数据,而不是Tab2Page UI。我不得不选择使用RxJS“Subject”的另一种方式,这在angular文档中提到过。拍摄对象和观察对象都很吸引人,我仍在为之绞尽脑汁。我想知道为什么“ChangeDetectorRef”会出现运行时错误。我的第二个建议假设您正在使用@输入将pics
从Tab3Page
传递到Tab2Page
。这样,当您在Tab3Page
中更新pics
时,Tab2Page
中的@Input
也会得到更新。我明白了,我的缺点是变量命名相同。在我的用例中,这两个页面具有不同的“pics”数据状态。Tab2中的数据实际上是Tab3中数据的子集。Tab2仅包括用户从Tab3中的数据项中选择的项。