angular - ExpressionChangedAfterItHasBeenCheckedError 与共享服务
问题描述
我们有一个加载了子组件的根布局组件。布局组件绑定到共享布局服务中的属性。子组件在共享布局服务中设置属性。每当我们从子组件更改属性时,我们会在非 prod 模式下收到以下错误: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked
这真的很烦人。如果不执行 cdr.detectChanges(),就没有其他方法可以使这个工作吗?
这是一个应该可以工作的简单场景……</p>
app.component.html
------------------
<layout>
</layout>
layout.component.html
---------------------
<div *ngFor="let menuItem of layoutService.menuItems">
{{menuItem.content}}
</div>
layout.component.ts
-------------------
@Injectable()
export class LayoutComponent{
constructor(public layoutService: LayoutService){}
...
}
layout.service.ts
-----------------
export class LayoutService {
menuItems: MenuItem[];
...
}
child-component-in-router-outlet.component.ts
---------------------------------------------
export class ChildComponentInRouterOutletComponent {
constructor(private layoutService: LayoutService){}
ngOnInit(): void{
this.layoutService.menuItems = [ ... ];
}
}
如果在此示例中我将 de menuItems 属性转换为 BehaviorSubject 它也不起作用。
解决方案
我通过在 NavigationEnd 上执行 detectChanges 来修复它,如下所示:
this.router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
this.cdr.detectChanges();
}
});
有了这个,你只在组件被加载到路由器出口并且在共享服务上设置了属性之后才调用一次detectChanges。
推荐阅读
- ios - 使用 @EnvironmentObject 无休止地重新渲染 Swift UI Tabview
- ruby-on-rails - 每个字段上的 GraphQL Ruby Resolver
- lua - 如何在 Neovim 中使用 mod 键(Ctrl、Alt、Shift 等)编写 Lua 命令
- sql - 如何使用 CASE WHEN 从我们的分类和竞争分类中获取匹配的 SKU 产品
- laravel - Laravel 文件系统(url)公开显示无图像
- python - raise ValueError("name_scope 的名称必须是字符串。"
- javascript - 使用本地存储保存游戏进度
- android - 使用来自 Json Android 的唯一值填充 Spinner
- html - 如何在 Angular 中复制、编辑和或重用严格来说只是 html 和 css 的组件?
- javascript - 如何根据给定的参数过滤出对象数组?