如何正确处理JavaScript移除Blazor渲染元素的问题?
Blazor中JS修改DOM引发的组件同步问题及解决方案
问题背景
在Blazor框架中,通过JavaScript直接修改DOM并非最佳实践,但当前场景下找不到替代方案:我使用Blazor的for循环遍历数组渲染了一组Material Web的<MdInputChip>自定义组件,用户点击芯片的X按钮可移除芯片。但点击X时,Web Component的内部代码会自行将元素从DOM中移除,这部分逻辑无法修改。
可复现代码
<div @key="@DateTime.UtcNow.ToString()"> @for (int i = 0; i < values.Count; i++) { var z = i; var item = values[z]; <p @key="@(DateTime.UtcNow.ToString() + z)" @onchange="(() => Remove(z))"> @(item) <button onclick="this.parentElement.dispatchEvent(new Event('change')); this.parentElement.remove();"> Remove </button> </p> } </div> @code { List<string> values = new() { "A", "B", "C" }; void Remove(int index) { values.RemoveAt(index); Console.WriteLine(string.Join(",", values)); } }
核心问题
点击移除中间元素(比如B)时,多数情况下末尾元素(C)也会被错误移除。尝试通过@key属性解决:
- 给
<p>元素添加@key:数组后续修改时会触发多种异常 - 给外层
<div>添加@key并移除<p>的@key:仅降低问题出现频率,仍偶发异常
由于场景对性能要求不高,重新渲染整个区域完全可行,希望找到可靠的解决办法,包括让Blazor直接销毁区域后重新渲染所有内容的方案。
针对该场景的可行方案
幸运的是,当前场景中可通过preventDefault()取消Web Component的自动移除事件,具体实现如下:
export function beforeStart() { document.addEventListener("remove", e => { if (e.target?.tagName === "MD-INPUT-CHIP") { e.preventDefault(); } }); }
内容的提问来源于stack exchange,提问作者Luke Vo
相关产品推荐
相关产品推荐

