如何减少模板上的异步管道订阅数
How to reduce the number async pipe subscriptions on template
我有这个组件StackBliz
模板:
<mat-sidenav-container class="sidenav-container">
<mat-sidenav #drawer class="sidenav" fixedInViewport
[attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'"
[mode]="(isHandset$ | async) ? 'over' : 'side'"
[opened]="(isHandset$ | async) === false">
<mat-toolbar>Menu</mat-toolbar>
<mat-nav-list>
<a mat-list-item href="#">Link 1</a>
<a mat-list-item href="#">Link 2</a>
<a mat-list-item href="#">Link 3</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<mat-toolbar color="primary">
<button
type="button"
aria-label="Toggle sidenav"
mat-icon-button
(click)="drawer.toggle()"
*ngIf="isHandset$ | async">
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
<span>dashboard-app</span>
</mat-toolbar>
</mat-sidenav-content>
</mat-sidenav-container>
Class:
export class NavigationComponent {
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
.pipe(
map(result => result.matches),
shareReplay()
);
constructor(private breakpointObserver: BreakpointObserver) {}
}
我想减少页面上的订阅数量。
我尝试将内容包装到 ng-container
中,但这没有用。
首先,我在 [opened]="isHandset === false"
中的模板中遇到错误,其次,ng-container
破坏了视图,所以即使我按原样离开,[opened]="(isHandset$ | async) === false"
也没有任何问题显示
<mat-sidenav-container class="sidenav-container">
<ng-container *ngIf="isHandset$ | async as isHadset">
<mat-sidenav #drawer class="sidenav" fixedInViewport
[attr.role]="isHadset ? 'dialog' : 'navigation'"
[mode]="isHadset ? 'over' : 'side'"
[opened]="isHadset === false"> //got an error here saying this condition is always false because isHadset is always 'true'
...
*ngIf="isHadset"
...
</mat-sidenav-content>
<ng-container>
</mat-sidenav-container>
关于如何解决我上面描述的所有两个问题有什么想法吗?
使用带有 boolean
发射的 *ngIf
并不理想,因为如果值为 false
,它不会呈现元素。但是我看到最初你的发射是一个物体。由于对象是真实的,您可以忽略到布尔值的映射并直接将其与 *ngIf
.
一起使用
我还建议将整个容器包裹在 <ng-container>
中以保留 DOM。
尝试以下方法
控制器 (*.ts)
import { BreakpointObserver, Breakpoints, BreakpointState } from '@angular/cdk/layout';
...
export class NavigationComponent {
isHandset$: Observable<BreakpointState>;
constructor(private breakpointObserver: BreakpointObserver) {
this.isHandset$ = this.breakpointObserver.observe(Breakpoints.Handset);
}
}
模板(*.html)
<ng-container *ngIf="(isHandset$ | async) as result">
<mat-sidenav-container class="sidenav-container">
<mat-sidenav
#drawer
class="sidenav"
fixedInViewport
[attr.role]="(result.matches) ? 'dialog' : 'navigation'"
[mode]="(result.matches) ? 'over' : 'side'"
[opened]="!result.matches"
>
<mat-toolbar>Menu</mat-toolbar>
<mat-nav-list>
<a mat-list-item href="#">Link 1</a>
<a mat-list-item href="#">Link 2</a>
<a mat-list-item href="#">Link 3</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<mat-toolbar color="primary">
<button
type="button"
aria-label="Toggle sidenav"
mat-icon-button
(click)="drawer.toggle()"
*ngIf="result.matches"
>
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
<span>dashboard-app</span>
</mat-toolbar>
</mat-sidenav-content>
</mat-sidenav-container>
</ng-container>
我修改了你的Stackblitz
我有这个组件StackBliz
模板:
<mat-sidenav-container class="sidenav-container">
<mat-sidenav #drawer class="sidenav" fixedInViewport
[attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'"
[mode]="(isHandset$ | async) ? 'over' : 'side'"
[opened]="(isHandset$ | async) === false">
<mat-toolbar>Menu</mat-toolbar>
<mat-nav-list>
<a mat-list-item href="#">Link 1</a>
<a mat-list-item href="#">Link 2</a>
<a mat-list-item href="#">Link 3</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<mat-toolbar color="primary">
<button
type="button"
aria-label="Toggle sidenav"
mat-icon-button
(click)="drawer.toggle()"
*ngIf="isHandset$ | async">
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
<span>dashboard-app</span>
</mat-toolbar>
</mat-sidenav-content>
</mat-sidenav-container>
Class:
export class NavigationComponent {
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
.pipe(
map(result => result.matches),
shareReplay()
);
constructor(private breakpointObserver: BreakpointObserver) {}
}
我想减少页面上的订阅数量。
我尝试将内容包装到 ng-container
中,但这没有用。
首先,我在 [opened]="isHandset === false"
中的模板中遇到错误,其次,ng-container
破坏了视图,所以即使我按原样离开,[opened]="(isHandset$ | async) === false"
也没有任何问题显示
<mat-sidenav-container class="sidenav-container">
<ng-container *ngIf="isHandset$ | async as isHadset">
<mat-sidenav #drawer class="sidenav" fixedInViewport
[attr.role]="isHadset ? 'dialog' : 'navigation'"
[mode]="isHadset ? 'over' : 'side'"
[opened]="isHadset === false"> //got an error here saying this condition is always false because isHadset is always 'true'
...
*ngIf="isHadset"
...
</mat-sidenav-content>
<ng-container>
</mat-sidenav-container>
关于如何解决我上面描述的所有两个问题有什么想法吗?
使用带有 boolean
发射的 *ngIf
并不理想,因为如果值为 false
,它不会呈现元素。但是我看到最初你的发射是一个物体。由于对象是真实的,您可以忽略到布尔值的映射并直接将其与 *ngIf
.
我还建议将整个容器包裹在 <ng-container>
中以保留 DOM。
尝试以下方法
控制器 (*.ts)
import { BreakpointObserver, Breakpoints, BreakpointState } from '@angular/cdk/layout';
...
export class NavigationComponent {
isHandset$: Observable<BreakpointState>;
constructor(private breakpointObserver: BreakpointObserver) {
this.isHandset$ = this.breakpointObserver.observe(Breakpoints.Handset);
}
}
模板(*.html)
<ng-container *ngIf="(isHandset$ | async) as result">
<mat-sidenav-container class="sidenav-container">
<mat-sidenav
#drawer
class="sidenav"
fixedInViewport
[attr.role]="(result.matches) ? 'dialog' : 'navigation'"
[mode]="(result.matches) ? 'over' : 'side'"
[opened]="!result.matches"
>
<mat-toolbar>Menu</mat-toolbar>
<mat-nav-list>
<a mat-list-item href="#">Link 1</a>
<a mat-list-item href="#">Link 2</a>
<a mat-list-item href="#">Link 3</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<mat-toolbar color="primary">
<button
type="button"
aria-label="Toggle sidenav"
mat-icon-button
(click)="drawer.toggle()"
*ngIf="result.matches"
>
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
<span>dashboard-app</span>
</mat-toolbar>
</mat-sidenav-content>
</mat-sidenav-container>
</ng-container>
我修改了你的Stackblitz