Angular Material Snackbar构建后报错:无法读取openSnackBar属性
Angular Material Snackbar: 本地运行正常,构建后报错"Cannot read properties of undefined (reading 'openSnackBar')"
问题场景
本地开发环境中调用commonService.openSnackBar()功能正常,但项目生产构建后抛出错误:
Cannot read properties of undefined (reading 'openSnackBar')
调用方服务中的代码:
private async handle() { this.commonService.openSnackBar('test snackbar'); // ...其他业务逻辑 }
commonService中openSnackBar的实现:
public openSnackBar(message: string, icon?: string) { return this.zone.run(() => { this._snackBar.open(message, icon, { horizontalPosition: this.horizontalPosition, verticalPosition: this.verticalPosition, duration: 3000 }); }); }
已尝试通过NgZone包裹逻辑,但问题未解决。
可能的原因及解决方法
1. 服务注入或提供范围错误
- 确保调用方服务的构造函数中正确声明
commonService的依赖注入:constructor(private commonService: CommonService) {} - 检查
CommonService的@Injectable装饰器是否设置了正确的提供范围,避免生产构建时被树摇优化移除:@Injectable({ providedIn: 'root' }) export class CommonService { // ...服务代码 }
2. 异步上下文丢失this指向
handle是异步方法,若被作为回调函数传递,可能导致this指向丢失,进而this.commonService为undefined:
- 调用
handle时用箭头函数绑定上下文:// 错误示例:直接传递方法可能丢失this someAsyncTask(this.handle); // 正确示例:箭头函数绑定上下文 someAsyncTask(() => this.handle()); - 或在构造函数中提前绑定
handle的this:constructor(private commonService: CommonService) { this.handle = this.handle.bind(this); }
3. 生产构建优化导致服务未被识别
Angular生产构建的树摇优化可能误判CommonService未被使用而移除:
- 在调用
openSnackBar前添加非空断言(仅确认服务已注入时使用):this.commonService!.openSnackBar('test snackbar'); - 给
CommonService添加一个初始化方法,在根组件中调用一次,让构建工具识别到服务被使用:
然后在根组件的@Injectable({ providedIn: 'root' }) export class CommonService { constructor(private zone: NgZone, private _snackBar: MatSnackBar) {} init() { // 空逻辑或初始化配置 } openSnackBar(message: string, icon?: string) { // ...原逻辑 } }ngOnInit中调用:ngOnInit() { this.commonService.init(); }
4. NgZone与Snackbar实例的上下文问题
确认_snackBar的注入和NgZone的使用时机:
- 确保
CommonService的构造函数中正确注入MatSnackBar和NgZone:constructor(private zone: NgZone, private _snackBar: MatSnackBar) {} - 尝试将整个
openSnackBar逻辑完整包裹在zone.run中:public openSnackBar(message: string, icon?: string) { return this.zone.run(() => { const config = { horizontalPosition: this.horizontalPosition, verticalPosition: this.verticalPosition, duration: 3000 }; return this._snackBar.open(message, icon, config); }); }
内容的提问来源于stack exchange,提问作者Uland Nimblehoof
相关产品推荐
相关产品推荐

