与根 AppComponent 交互 - Angular
Interacting with root AppComponent - Angular
我正在尝试在组件 SettingsComponent
中实现功能,用户按下按钮,根 AppComponent
中的横幅将发生变化。
customBanner():void{
this.changeBanner = true;
}
当用户按下 SettingsComponent
中的按钮时调用上述函数。该应用程序的横幅位于根 AppComponent
:
<div *ngIf ="!changeBanner">
<h2 class="main-header"><img src = "../../../assets/images/banner.jpg" style="max-height:40px"></h2>
</div>
<div *ngIf ="changeBanner">
<h2>Custom Banner</h2>
</div>
<router-outlet></router-outlet>
changeBanner
是AppComponent
的变量。我试图在用户按下 SettingsComponent
中的按钮时获取它,AppComponent
中的变量 changeBanner
将被更改。
现在我正在尝试这个:
export class AppComponent implements AfterViewInit {
changeBanner = false;
@ViewChild(SettingsComponent)
private settings:SettingsComponent;
ngAfterViewInit(){
this.changeBanner = this.settings.changeBanner;
}
}
就在我按下 settings
页面上的任何内容之前,我收到错误消息
Cannot read property 'changeBanner' of undefined
谈论this.settings.changeBanner
。
如果我按下一个按钮,什么也不会发生。我不确定我是否以正确的方式进行此操作。
SettingsComponent 的实例需要是 AppComponent 的直接子级,即在 AppComponent 的视图中需要有一个 <my-settings></my-settings>
或类似的。否则这将无法工作。
除此之外,您应该使用模板绑定或中间服务将数据从一个组件移动到另一个组件。
基本上,主题是不同组件之间的通信。通常,当子组件想要与父组件通信时,您会通过 @Output
属性.
使用事件绑定
但在您的情况下,横幅 属性 似乎是许多组件之间的共享状态。在这种情况下,最好创建一个保存该状态的服务。所有应该更改横幅的组件都获得此 BannerService 的实例。 BannerService 有一个 Observable,它会在横幅更改时发出更改。 AppComponent 然后可以订阅该 Observable 并相应地更改横幅。
另一种管理共享状态的替代方案是 ngrx,它很棒但学习曲线相当陡峭。
去掉 AppComponent 中的 @ViewChild(SettingsComponent)。
在 AppComponent 中创建一个名为 bannerChanged(){ this.changeBanner = !this.changeBanner;}
的函数
在您的 html 应用程序组件中执行此操作:
<app-settings (bannerChanged)="bannerChanged($event)"></app-settings>
然后在您的 SettingsComponent 中有这个:
@Output() bannerChanged = new EventEmitter<void>();
...
changeBanner(){
this.bannerChanged.emit();
}
changeBanner 函数将在您按下按钮时被调用
如果你不想要那个,那么创建一个名为 'settings' 的 SettingsReducer 并订阅它的更改,当在 SettingsComponent 中按下按钮时调度更改:
//in app.module.ts
StoreModule.forRoot({settings: SettingsReducer})
//in SettingsReducer
export function SettignsReducer(state: SettingStore = SettingsState, { type, payload}){
switch (type) {
case ('SETTINGS_CHANGED'):
return (Object.assign({}, state, { settingValue: payload });
}
}
//in appComponent
constructor(private store: Store<SettingStore>){
this.store.select('settings').subscribe(value => this.changeBanner = value['settingValue'];);
}
//in SettingsComponent
buttonClicked(){
let value = !this.currentValue;
this.store.dispatch({type: 'SETTINGS_CHANGED', payload: value});
}
我正在尝试在组件 SettingsComponent
中实现功能,用户按下按钮,根 AppComponent
中的横幅将发生变化。
customBanner():void{
this.changeBanner = true;
}
当用户按下 SettingsComponent
中的按钮时调用上述函数。该应用程序的横幅位于根 AppComponent
:
<div *ngIf ="!changeBanner">
<h2 class="main-header"><img src = "../../../assets/images/banner.jpg" style="max-height:40px"></h2>
</div>
<div *ngIf ="changeBanner">
<h2>Custom Banner</h2>
</div>
<router-outlet></router-outlet>
changeBanner
是AppComponent
的变量。我试图在用户按下 SettingsComponent
中的按钮时获取它,AppComponent
中的变量 changeBanner
将被更改。
现在我正在尝试这个:
export class AppComponent implements AfterViewInit {
changeBanner = false;
@ViewChild(SettingsComponent)
private settings:SettingsComponent;
ngAfterViewInit(){
this.changeBanner = this.settings.changeBanner;
}
}
就在我按下 settings
页面上的任何内容之前,我收到错误消息
Cannot read property 'changeBanner' of undefined
谈论this.settings.changeBanner
。
如果我按下一个按钮,什么也不会发生。我不确定我是否以正确的方式进行此操作。
SettingsComponent 的实例需要是 AppComponent 的直接子级,即在 AppComponent 的视图中需要有一个 <my-settings></my-settings>
或类似的。否则这将无法工作。
除此之外,您应该使用模板绑定或中间服务将数据从一个组件移动到另一个组件。
基本上,主题是不同组件之间的通信。通常,当子组件想要与父组件通信时,您会通过 @Output
属性.
但在您的情况下,横幅 属性 似乎是许多组件之间的共享状态。在这种情况下,最好创建一个保存该状态的服务。所有应该更改横幅的组件都获得此 BannerService 的实例。 BannerService 有一个 Observable,它会在横幅更改时发出更改。 AppComponent 然后可以订阅该 Observable 并相应地更改横幅。
另一种管理共享状态的替代方案是 ngrx,它很棒但学习曲线相当陡峭。
去掉 AppComponent 中的 @ViewChild(SettingsComponent)。
在 AppComponent 中创建一个名为 bannerChanged(){ this.changeBanner = !this.changeBanner;}
在您的 html 应用程序组件中执行此操作:
<app-settings (bannerChanged)="bannerChanged($event)"></app-settings>
然后在您的 SettingsComponent 中有这个:
@Output() bannerChanged = new EventEmitter<void>();
...
changeBanner(){
this.bannerChanged.emit();
}
changeBanner 函数将在您按下按钮时被调用
如果你不想要那个,那么创建一个名为 'settings' 的 SettingsReducer 并订阅它的更改,当在 SettingsComponent 中按下按钮时调度更改:
//in app.module.ts
StoreModule.forRoot({settings: SettingsReducer})
//in SettingsReducer
export function SettignsReducer(state: SettingStore = SettingsState, { type, payload}){
switch (type) {
case ('SETTINGS_CHANGED'):
return (Object.assign({}, state, { settingValue: payload });
}
}
//in appComponent
constructor(private store: Store<SettingStore>){
this.store.select('settings').subscribe(value => this.changeBanner = value['settingValue'];);
}
//in SettingsComponent
buttonClicked(){
let value = !this.currentValue;
this.store.dispatch({type: 'SETTINGS_CHANGED', payload: value});
}