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

Blazor博客编辑组件提交空标题触发removeChild空引用错误致应用冻结

问题分析

提交空标题的博客时出现的TypeError: Cannot read properties of null (reading 'removeChild')错误,本质是Blazor渲染过程中JS互操作异常,通常是组件状态未正确同步或调用时机不当导致。结合代码来看,核心问题有两点:

  • 表单验证与编辑器内容获取的顺序逻辑错误,导致验证失败后编辑器DOM状态异常
  • 未对编辑器组件引用做空值检查,增加了未初始化调用的风险
解决方案

1. 调整操作顺序,先更新模型再验证

当前代码先执行表单验证,再获取编辑器内容更新模型,这会导致验证基于旧的模型数据,同时验证触发的重新渲染可能干扰编辑器的JS操作。应先同步编辑器内容到模型,再执行完整的表单验证。

2. 增加组件引用的空值检查

确保调用编辑器方法前,组件引用已正确初始化,避免空引用引发的后续错误。

3. 优化异常处理逻辑

避免捕获异常后直接返回,应给出明确的错误提示,同时保证组件状态正常恢复。

修改后的代码
@using BlazorBlog.Application.Features.Blogs.Commands.Edit

@inherits MudComponentBase

@inject IValidationService Validator
@inject IMediator Mediator

<MudDialog style="min-height: 650px;">
    <DialogContent>
        <MudForm Model="@Model" @ref="@_form" Validation="@(Validator.ValidateValue(Model))">
            <MudGrid>
                <MudItem xs="12">
                    <MudTextField Label="Blog Title" @bind-Value="Model.Title" For="@(() => Model.Title)"
                                  Required RequiredError="@string.Format(ConstantString.RequiredText, "Blog Title")">
                    </MudTextField>
                </MudItem>
                <MudItem xs="12">
                    <BlazoredTextEditor @ref="@RichEditor">
                        <ToolbarContent>
                            <span class="ql-formats">
                                <select class="ql-font">
                                    <option selected=""></option>
                                    <option value="serif"></option>
                                    <option value="monospace"></option>
                                </select>
                                <select class="ql-size">
                                    <option value="small"></option>
                                    <option selected=""></option>
                                    <option value="large"></option>
                                    <option value="huge"></option>
                                </select>
                            </span>
                            <span class="ql-formats">
                                <button class="ql-bold"></button>
                                <button class="ql-italic"></button>
                                <button class="ql-underline"></button>
                                <button class="ql-strike"></button>
                            </span>
                            <span class="ql-formats">
                                <select class="ql-color"></select>
                                <select class="ql-background"></select>
                            </span>
                            <span class="ql-formats">
                                <button class="ql-list" value="ordered"></button>
                                <button class="ql-list" value="bullet"></button>
                                <button class="ql-indent" value="-1"></button>
                                <button class="ql-indent" value="+1"></button>
                                <select class="ql-align">
                                    <option selected=""></option>
                                    <option value="center"></option>
                                    <option value="right"></option>
                                    <option value="justify"></option>
                                </select>
                            </span>
                            <span class="ql-formats">
                                <button class="ql-link"></button>
                            </span>
                        </ToolbarContent>
                        <EditorContent>
                            @((MarkupString)Model.Description)
                        </EditorContent>
                    </BlazoredTextEditor>
                </MudItem>
            </MudGrid>
        </MudForm>
    </DialogContent>
    <DialogActions>
        <MudButton Variant="Variant.Outlined" OnClick="Cancel">@ConstantString.Cancel</MudButton>
        <MudLoadingButton Variant="Variant.Outlined" Loading="@_saving" OnClick="Submit">@ConstantString.SaveChanges</MudLoadingButton>
    </DialogActions>
</MudDialog>

@code {
    [CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = default!;
    [EditorRequired][Parameter] public EditBlogCommand Model { get; set; } = default!;
    [Parameter] public Action? Refresh { get; set; }
    private MudForm? _form;
    private bool _saving;
    private BlazoredTextEditor? RichEditor; // 增加nullable标记

    private async Task Submit()
    {
        try
        {
            _saving = true;

            // 1. 先检查编辑器引用是否存在
            if (RichEditor == null)
            {
                Snackbar.Add("编辑器未初始化,请稍后重试", Severity.Error);
                return;
            }

            // 2. 先获取编辑器内容更新模型
            try
            {
                Model.Description = await RichEditor.GetHTML();
            }
            catch (Exception ex)
            {
                Snackbar.Add($"获取编辑器内容失败: {ex.Message}", Severity.Error);
                return;
            }

            // 3. 再执行表单验证
            await _form!.Validate().ConfigureAwait(false);
            if (!_form.IsValid) { return; }

            // 4. 提交命令
            var result = await Mediator.Send(Model);

            if (result.Succeeded)
            {
                MudDialog.Close(DialogResult.Ok(true));
                Snackbar.Add(ConstantString.SaveSuccess, Severity.Info);
                Refresh?.Invoke();
            }
            else
            {
                Snackbar.Add(result.ErrorMessage, Severity.Error);
            }
        }
        finally
        {
            _saving = false;
        }
    }

    private void Cancel()
    {
        MudDialog.Cancel();
    }
}
额外建议
  • 检查Blazored Text Editor的版本,确保使用最新稳定版,部分旧版本存在类似的DOM操作异常
  • 若仍出现渲染问题,可尝试在编辑器组件上添加@key="Model.Id"(或唯一标识),帮助Blazor正确跟踪组件状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 15:42:35