You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular Material侧边栏点击遮罩区域关闭功能实现问题

问题:Angular Material侧边栏点击遮罩无法关闭,结合NgRx实现布局

我是Angular Material、NgRx及现代Angular的新手,正在实现一个基础头部布局:包含带标题和菜单图标的Toolbar,以及承载链接的Sidenav。需求是:

  • 点击菜单图标打开侧边栏
  • 点击侧边栏外的遮罩区域(backdrop)关闭侧边栏

我参考NgRx示例应用尝试实现,但通过(click)和(backdropClick)事件在Sidenav容器上触发事件时,功能未成功实现。相关代码如下:


app.component.ts

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';

import * as fromRoot from '@client-app/reducers';
import { LayoutActions } from '@client-app/core/actions';

@Component({
  selector: 'app-root',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <app-layout (closeMenu)="closeSidenav()">
      <app-toolbar (openMenu)="openSidenav()">Memories</app-toolbar>
      <app-sidenav [open]="(showSidenav$ | async)!">

      </app-sidenav>
      <router-outlet></router-outlet>
    </app-layout>
  `,
})
export class AppComponent {
  showSidenav$: Observable<boolean>;

  constructor(private store: Store) {
    this.showSidenav$ = this.store.select(fromRoot.selectShowSidenav);
  }
  closeSidenav() {
    this.store.dispatch(LayoutActions.closeSidenav());
  }
  openSidenav() {
    this.store.dispatch(LayoutActions.openSidenav());
  }
}

layout.component.ts

import { Component, EventEmitter, Output } from '@angular/core';

@Component({
  selector: 'app-layout',
  template: `
    <mat-sidenav-container fullscreen>
      <ng-content></ng-content>
    </mat-sidenav-container>
  `,
})
export class LayoutComponent {
  @Output() closeMenu = new EventEmitter<void>;
}

sidenav.component.ts

import { Component, EventEmitter, Input, Output } from '@angular/core';

@Component({
  selector: 'app-sidenav',
  template: `
    <mat-sidenav
      position="end"
      [opened]="open"
    >
      <mat-nav-list>
        <a mat-list-item href="login">Login</a>
        <a mat-list-item href="signup">Signup</a>
      </mat-nav-list>
    </mat-sidenav>
  `,
  styles: [
    `
      mat-sidenav {
        width: 200px;
      }
    `,
  ],
})
export class SidenavComponent {
  @Input() open = false;
}

toolbar.component.ts

import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-toolbar',
  template: `
    <mat-toolbar color="primary">
      <ng-content></ng-content>
      <button mat-icon-button (click)="openMenu.emit()" aria-label="menu">
        <mat-icon>menu</mat-icon>
      </button>
    </mat-toolbar>
  `,
  styles: [
    `
      mat-toolbar {
        display: flex;
        justify-content: space-between;
      }
    `,
  ],
})
export class ToolbarComponent {
  @Output() openMenu = new EventEmitter<void>;
}

解决方案

问题核心是未正确监听遮罩点击事件,且mat-sidenav默认模式不生成遮罩。以下是具体修改步骤:

1. 给LayoutComponent添加遮罩点击监听

在mat-sidenav-container上绑定(backdropClick)事件,触发closeMenu输出:

// layout.component.ts
@Component({
  selector: 'app-layout',
  template: `
    <mat-sidenav-container fullscreen (backdropClick)="closeMenu.emit()">
      <ng-content></ng-content>
    </mat-sidenav-container>
  `,
})
export class LayoutComponent {
  @Output() closeMenu = new EventEmitter<void>(); // 补充分号修正语法
}

2. 给SidenavComponent设置mode="over"

mat-sidenav默认mode="side"(侧边固定显示),不会生成遮罩。设置为mode="over"才能在侧边栏弹出时显示遮罩:

// sidenav.component.ts
@Component({
  selector: 'app-sidenav',
  template: `
    <mat-sidenav
      position="end"
      [opened]="open"
      mode="over" <!-- 添加此行 -->
    >
      <mat-nav-list>
        <a mat-list-item href="login">Login</a>
        <a mat-list-item href="signup">Signup</a>
      </mat-nav-list>
    </mat-sidenav>
  `,
  styles: [
    `
      mat-sidenav {
        width: 200px;
      }
    `,
  ],
})
export class SidenavComponent {
  @Input() open = false;
}

3. 修正语法细节

给所有EventEmitter定义补充分号,保证语法合规:

// toolbar.component.ts
@Output() openMenu = new EventEmitter<void>();

修改完成后,点击菜单图标会触发NgRx的openSidenav动作打开侧边栏,点击遮罩区域会触发closeSidenav动作关闭侧边栏,完全符合需求。


内容的提问来源于stack exchange,提问作者orangecheese

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 03:32:47