我创建了一个称为边栏的组件。假设该组件有2个输入,sideBarMode和sideBarSide。在app.component中,我像这样添加该组件<sidebar [sideBarMode]="'sliding'" [sideBarSide]="'right'"></sidebar>
。
[当我将以上内容用作一个标签时,它可以正常工作。但是,当我做类似的事情
<div>
<sidebar [sideBarMode]="'sliding'" [sideBarSide]="'right'"></sidebar>
</div>
<div>
<sidebar [sideBarMode]="'docked'" [sideBarSide]="'left'"></sidebar>
</div>
它们被渲染,但是具有相同的类,尽管如果我要控制台控制台记录正在传递的ngOnInit中的值,它们将正确显示。例如,一个div应该显示为类滑动,而另一个应为停靠。相反,它们都显示为停靠两者。
这是HTML模板。
<div class="container-fluid">
<div [ngClass]="barSliding ? 'sliding' : 'sidebar-docked'">
<div class="row k-sidebar {{theme}}"
[ngClass]="[sidebarLeft ? 'position-left' : 'position-right', barSliding ? 'sliding-content-bar' : 'sidebar-docked', isDesktopWidth.value ? 'largeView' : 'mobileView']"
[@slideAnimation]= 'animationState'
[@dockMobileSidebar]= 'animationStateMobile'
[ngStyle]="{'width.px': isDesktopWidth.value ? sideBarWidth : '' }"
>
<div class="col-md-12">
<ng-container *ngIf="sidebarTemplate">
<ng-container *ngTemplateOutlet="sidebarTemplate">
</ng-container>
</ng-container>
<ng-container *ngIf="!sidebarTemplate">
<p>This is a paragraph, no template has been passed</p>
</ng-container>
</div>
</div>
</div>
这是我检查模式的方式,无论它是否停靠在TS文件中,我都从ngOnInit调用此方法。
private checkSidebarMode(mode) {
console.log('checkSidebarMode ', mode);
if (mode === 'sliding') {
this.sidebarService.sideBarSliding.next(true);
console.log('checkSidebarMode ', this.sidebarService.sideBarSliding.getValue());
this.sideBarDock.next(false);
} else if (mode === 'docked' && this.sidebarService.innerWidth.getValue() <= 767) {
this.sideBarDock.next(false);
this.sidebarService.sideBarSliding.next(true);
} else if (mode === 'docked' && this.sidebarService.innerWidth.getValue() > 767) {
this.sideBarDock.next(true);
this.sidebarService.sideBarSliding.next(false);
this.sidebarService.animationState.next('docked');
console.log('checkSidebarMode ', this.sidebarService.sideBarSliding.getValue());
}
}
如您所见,如果它正在滑动,则将observable设置为true,然后在ngOninit中,将该值分配给barSliding,该值在HTML模板中用于确定类名。
停靠的是正确的,但是滑动的正在获取停靠的属性...为什么?
由于您的BehaviorSubject
位于sidebarService
中,因此该值很可能是providedIn: 'root'
,这使其成为单例。因此,对于组件的两个实例,您的BehaviorSubject
相同。
您有多种解决方案:
BehaviorSubject
,而不是在服务中使用共享的BehaviorSubject。 next()
输入更改后,我将通过在ngOnChanges
method中调用ngOnChanges
来更新它。mode
@Component({...})
export class MyComponent implements OnInit {
@Input() mode: 'sliding' | 'docked' = 'sliding';
private subject = new BehaviorSubject<string>(null);
ngOnChanges() {
// here you should check that 'mode' changed before calling next()
this.subject.next(this.mode);
}
}
实例。如果它是简单的BehaviorSubject
,但未附加逻辑,则也许比第一个解决方案没有真正的好处。 BehaviorSubject
但是仅当您从服务返回的// service
@Injectable()
export class MyService {
public getNewBehaviorSubject() {
return new BehaviorSubject<String>(null);
}
}
// component
@Component({...})
export class MyComponent implements OnInit {
@Input() mode: 'sliding' | 'docked' = 'sliding';
private subject = this.myService.getNewBehaviorSubject();
ngOnChanges() {
// here you should check that 'mode' changed before calling next()
this.subject.next(this.mode);
}
}
必须使用服务中的其他信息(其他数据,静态变量,例如屏幕大小等)时,这才有意义。
BehaviorSubject
请记住,默认情况下,Angular的服务被设计为单例。这是最常见的用例。