You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

循环调用Blazor模板函数包裹HTML元素时td未嵌套tr渲染异常问题

问题现象

开发带表格功能的Blazor组件时,抽离复用Razor模板片段出现渲染异常:生成的td元素未嵌套在tr元素内部,与<tr>处于同一DOM层级。其中tfoot部分渲染正常,tbody部分存在上述问题,无需通过返回MarkupString拼接原始HTML的方式即可解决。

复现代码如下:

<table>
<tbody>
    @foreach (var row in data)
    {
        @:<tr>
        RenderRow(row);
        @:</tr>
    }
</tbody>
<tfoot>
    <tr>
        @if (footerRow != null)
        {
            RenderRow(footerRow);
        }
    </tr>
</tfoot>
</table>

@{
    void RenderRow(Row row)
    {
        <td>@row.RowNum</td>
        RenderRowHalf(row.Left);
        RenderRowHalf(row.Right);
    }

    void RenderRowHalf(RowHalf half)
    {
        <td>@half.Foo</td>
        <td>@(Util.ColorNumber(half.Bar))</td>
    }
}
问题原因

Blazor的Razor引擎不是通过字符串拼接生成HTML,而是通过构建渲染树(RenderTree)映射DOM结构,要求HTML标签必须以完整的成对结构出现在Razor标记中,才能被正确识别为元素节点、建立父子层级关系:

  • tbody循环中使用@:语法单独输出<tr>开标签和</tr>闭标签时,引擎会将这两段内容识别为独立的平级内容块,不会将两者中间调用RenderRow生成的td节点归为tr的子节点,最终渲染出平级结构。
  • tfoot部分的<tr>标签是完整成对写在Razor标记中的,引擎可以正确识别这是一个父元素节点,内部逻辑输出的td会自动挂载为其子节点,因此渲染正常。
正确实现方案

方案1:最小改动修正标签写法

不要拆分tr的开/闭标签用@:单独输出,直接将完整的tr标签写在循环块内,把渲染方法调用放在标签内部,和tfoot的写法保持一致即可:

<tbody>
    @foreach (var row in data)
    {
        <tr>
            @{ RenderRow(row); }
        </tr>
    }
</tbody>

调用返回void的渲染方法时,放在@{}代码块中,或在方法名前加@调用均可正常渲染。

方案2:使用RenderFragment实现复用(官方推荐)

对于可复用的模板片段,更符合Blazor设计规范的写法是定义参数化RenderFragment委托,相比void渲染方法,渲染层级更可控,不会出现上下文错乱问题:

<table>
<tbody>
    @foreach (var row in data)
    {
        <tr>
            @RenderRow(row)
        </tr>
    }
</tbody>
<tfoot>
    <tr>
        @if (footerRow != null)
        {
            @RenderRow(footerRow)
        }
    </tr>
</tfoot>
</table>

@{
    RenderFragment<Row> RenderRow = row => __builder =>
    {
        <td>@row.RowNum</td>
        @RenderRowHalf(row.Left)
        @RenderRowHalf(row.Right)
    };

    RenderFragment<RowHalf> RenderRowHalf = half => __builder =>
    {
        <td>@half.Foo</td>
        <td>@(Util.ColorNumber(half.Bar))</td>
    };
}

注意:Blazor Razor语法和传统ASP.NET MVC的字符串拼接式Razor逻辑有本质区别,永远不要将一个HTML元素的开标签、闭标签拆分到不同的输出块中,否则必然出现渲染层级错乱。


内容的提问来源于stack exchange,提问作者Austin Wagner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 02:15:33