我的项目有一个选择程序的页面。在我将 BrowserAnimationsModule 添加到我的项目中之前,它工作得很好。
页面有一个“切换到A程序”按钮。无论您点击此按钮多少次,它始终都能正常工作。
请参阅正确的程序选择器
但是在将BrowserAnimationsModule添加到该项目中后,第二次单击时它将设置为“空程序”。但数据模型已经设置为正确的程序,我打印在页面上。
请参阅损坏的程序选择器
该页面本身没有使用BrowserAnimationsModule。两个链接上的代码完全相同,只是损坏的链接在项目中具有 BrowserAnimationsModule。
我尝试了 Firefox 和 Edge,都有同样的问题。
我也尝试了 Angular 版本 12 和 15,都有同样的问题。
当前的实现是使用 FormControl。我也尝试了 [(ngModel)] 并遇到了同样的问题。
两个链接都有源码图,可以在源码上调试。 请使用浏览器控制台查看它们。
我看到有人提到了 BrowserAnimationsModule 上的 a bug。但似乎已经修复了。
您可以完全控制这个小项目在 stackblitz
您可以将changeDetection:ChangeDetectionStrategy.OnPush添加到ProgramSelectorByClientComponent来看看会发生什么。
这可能无法解决问题,但这是调试问题的良好开端。
this.cd.detectChanges()
(这里是stackblitz)。每次调用以下行时,您的代码都会销毁并重新创建
select
内的整个选项,这意味着保存在 FormControl
处的 selectedProgram
中设置的任何先前值都会丢失:
// line inside `loadPrograms()` method
this.allProgramList = res;
我看到您尝试通过每次重置选项时调用
followProgram()
方法来解决此问题,这可能没问题。但当涉及动画时,它可能会导致问题,这种错误(通过在某些点调用detectChanges()
解决的那种错误)通常与代码需要更新时 DOM 没有及时更新有关。
我的猜测是,通过添加模块,它可以通过稍微延迟
select
数组的创建来“增强”option
的行为。当您尝试设置新值时,没有给予足够的时间来完全创建它。所以,我能想到三种解决方案......
所有这些都经过了区域测试并且可以工作,请在 stackblitz 示例中查看它们:
this.cd.detectChanges()
这将强制您的选择在后续步骤中被访问时完全呈现:
// line inside `loadPrograms()` method
this.allProgramList = res;
this.cd.detectChanges()
setTimeout(() => {...}, 1)
这将为在单独的生命周期更改检测运行中处理延迟提供“时间”(这是一个深入的主题),
// line inside `loadPrograms()` method
setTimeout(() => {
this.followProgram();
},1)
这将使 Angular 不会破坏你的 dom,这样就不需要等待另一个生命周期来设置值:
// line inside `loadPrograms()` method
res.forEach((item) => {
if (!this.allProgramList.find((p) => p.pId === item.pId)) {
this.allProgramList.push(item);
}
});
我对这件事的最后评论是鼓励您将其报告为错误,仅添加额外的模块不应以这种方式改变行为。