技术:我如何解决MatExpansionPanel的奇怪行为

I have worked with Angular Material for several years and I love how easy it is to integrate their components into my apps. Among some of the most popular components like MatTab and MatTable, I often use MatExpansionPanel to render data that regulates a parent-child relationship. The problem with MatExpansionPanel is that it will automatically close when the data is getting updated. For example, assume we have a list of parent folders which also contain several sub folders that need to be loaded at runtime. The issue occurs right after sub folder data is loaded. Since the data structure has changed MatExpansionPanel suddenly collapses and the user needs to expand the panel again to view the contents. The issue is demonstrated below:

我已经与Angular Material合作了几年,我喜欢将其组件集成到我的应用中多么容易。 在一些最受欢迎的组件(例如MatTab和MatTable)中,我经常使用MatExpansionPanel来呈现可调节父子关系的数据。 MatExpansionPanel的问题在于,它将在数据更新时自动关闭。 例如,假设我们有一个父文件夹列表,其中还包含几个需要在运行时加载的子文件夹。 子文件夹数据加载后立即发生此问题。 由于数据结构已发生变化,MatExpansionPanel突然崩溃,用户需要再次扩展面板以查看内容。 该问题如下所示:

Image for post
Expansion Panel automatically closes when data get updated
数据更新后,扩展面板会自动关闭

我的第一次尝试 (My First Attempt)

Initially I thought this can be easily fixed by adding some custom logic to reopen the panel after the data is getting loaded. By doing this the parent folder can finally expand after sub folders are rendered but I am not fully satisfied with the current behavior. As the result, the expansion panel starts collapsing for a few milliseconds then begins to open again which, in fact, is not very graceful to see.

最初,我认为可以通过添加一些自定义逻辑来轻松解决此问题,该逻辑可以在加载数据后重新打开面板。 通过这样做,父文件夹最终可以在呈现子文件夹之后扩展,但是我对当前行为不完全满意。 结果,扩展面板开始折叠几毫秒,然后开始再次打开,实际上看起来不是很舒服。

Image for post
Ungraceful Success
失败的成功

After some time struggling to find the root cause, I realized that the problem is not caused by MatExpansionPanel itself. It’s definitely a side effect of the way my data structure gets updated.

经过一段时间的努力寻找根本原因后,我意识到问题不是由MatExpansionPanel本身引起的。 这绝对是我的数据结构更新方式的副作用。

In my implementation I use *ngFor structural directives to render each expansion panel. When the data structure is updated, *ngFor destroys existing MatExpansionPanels and re-renders the components again which causes all the states of the expansion panel to be lost completely. I then started digging into Angular doc to understand how *ngFor works and found out something interesting that might help me fix this problem.

在我的实现中,我使用* ngFor结构化指令来呈现每个扩展面板。 更新数据结构后,* ngFor会破坏现有的MatExpansionPanels并再次重新渲染组件,这将导致扩展面板的所有状态完全丢失。 然后,我开始研究Angular文档,以了解* ngFor的工作原理,并发现一些有趣的东西可能会帮助我解决此问题。

* ngFor引擎盖下 (*ngFor Under The Hood)

*ngFor is an Angular structural directive used to render the contents of an array of items. In each iteration, it takes the embedded template wrapped inside the directive and adds it to the DOM. When the array of items gets updated, *ngFor completely destroys the entire elements and starts inserting them back to the DOM. Let’s circle back to my MatExpansionPanel problem. The fact that *ngFor has to rebuild everything from scratch when only the children data are changing makes it become a very expensive operation and potentially hurt the performance of the app.

* ngFor是一个Angular结构指令,用于呈现项目数组的内容。 在每次迭代中,它都会使用包装在指令中的嵌入式模板,并将其添加到DOM中。 当项数组更新时,* ngFor会完全破坏整个元素,并开始将它们重新插入DOM。 让我们回到我的MatExpansionPanel问题。 当仅更改子数据时,* ngFor必须从头开始重建所有内容,这一事实使其变得非常昂贵,并可能损害应用程序的性能。

Image for post
*ngFor without trackBy
* ng对于没有trackBy

To mitigate this problem, *ngFor also supports an option to track down the changes and only perform DOM manipulation if necessary. The option is called trackBy. It is a function that takes two arguments: index and item. By providing this option in *ngFor, Angular will track the changes based on the return value of this function.

为了缓解此问题,* ngFor还支持一个选项来跟踪更改,并仅在必要时执行DOM操作。 该选项称为trackBy 。 它是一个带有两个参数的函数:index和item。 通过在* ngFor中提供此选项,Angular将基于此函数的返回值跟踪更改。

Image for post
*ngFor with trackBy
* ngFor与trackBy
Image for post
Expansion Panel stops collapsing
扩展面板停止折叠

最终思想 (Final Thought)

By applying trackBy option in *ngFor, I can be able to prevent MatExpansionPanel from closing when data structure gets updated. See demo here.

通过在* ngFor中应用trackBy选项,我可以防止MatExpansionPanel在数据结构更新时关闭。 在此处查看演示。

Being able to understand how structural directives work in Angular helps resolve a lot of issues related to DOM rendering. If you want to learn about *ngFor, feel free to visit Angular doc for more info.

能够理解结构化指令在Angular中的工作方式有助于解决许多与DOM渲染相关的问题。 如果您想了解* ngFor,请随时访问Angular 文档以获取更多信息。

您看到我的其他帖子了吗? (Did you see my other posts?)

翻译自: https://medium.com/swlh/how-i-fix-strange-behavior-of-matexpansionpanel-863b2c956b1a

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值