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

Angular中Service调用BreakpointObserver在app-component不生效问题

问题根因

@ViewChild 是 Angular 专为组件、指令提供的视图查询装饰器,只能在持有视图实例的组件/指令类中使用,才能查询到当前模板内的DOM或组件实例。Service是全局共享的逻辑层类,本身不关联任何组件视图,所以写在Service里的@ViewChild(MatSidenav)永远拿不到实际的侧边栏实例,调用方法时访问this.sidenav会直接报错,功能自然失效。

修复方案

调整逻辑,把sidenav实例的查询放在组件侧,再传递给Service的方法使用即可:

1. 修改app.component.ts

在组件内查询sidenav实例,调用Service方法时传入:

import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { MyDataServiceService } from './my-data-service.service';
import { MatSidenav } from '@angular/material/sidenav';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.scss']
})
export class AppComponent implements AfterViewInit {
    title = 'azad-app';
    name = '';
    // 组件侧查询侧边栏实例
    @ViewChild(MatSidenav) sidenav!: MatSidenav;
    
    constructor(private user: MyDataServiceService) { }
    
    ngAfterViewInit() {
        // 调用Service方法时传入sidenav实例
        this.user.menuDisplay(this.sidenav);
    }
}

2. 修改my-data-service.service.ts

删除Service内的@ViewChild代码,调整menuDisplay方法接收sidenav参数:

import { Injectable } from '@angular/core';
import { MatSidenav } from '@angular/material/sidenav';
import { BreakpointObserver } from '@angular/cdk/layout';
import { Subscription } from 'rxjs';

@Injectable({
    providedIn: 'root'
})
export class MyDataServiceService {
    private breakpointSub?: Subscription;

    constructor(private observer: BreakpointObserver) { }

    menuDisplay(sidenav: MatSidenav) {
        // 先销毁之前的订阅避免内存泄漏
        this.breakpointSub?.unsubscribe();
        this.breakpointSub = this.observer.observe(['(max-width:800px)']).subscribe((res) => {
            if (res.matches) {
                sidenav.mode = 'over';
                sidenav.close();
            } else {
                sidenav.mode = "side";
                sidenav.open();
            }
        });
    }

    // 可选:组件销毁时调用该方法清理订阅
    destroy() {
        this.breakpointSub?.unsubscribe();
    }
}

额外优化建议

你当前的Service命名MyDataServiceService重复了Service后缀,可以调整为更语义化的名称比如SidenavService,方便后续维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 15:18:01