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

Blazor 7下拉组件选中项传递异常:父组件仅获前一次选中值

问题分析与解决方案

问题根源

  1. 渲染顺序导致旧值传递:你在组件的渲染模板中(@if (mySelector.SelectedId > 0)块)给selectedOption赋值,但Blazor中@bind:after触发的SelectionChanged事件会先于模板渲染更新执行,此时selectedOption还是上一次的旧值,所以父组件收到的总是滞后一步的结果。
  2. 异步回调方式错误:SelectionChanged使用async void定义,这在Blazor中可能引发UI更新不同步问题,规范写法应使用async Task处理异步事件回调。

修复后的子组件代码

<h3>DropDownNames</h3>

<select @bind="@mySelector.SelectedId" @bind:after="SelectionChanged">
    @foreach (var opt in mySelector.Options)
    {
        <option value="@opt.Id" class="@opt.Style">@opt.Name @(new String('*', @opt.Stars))</option>
    }
</select>

@code {
    [Parameter]
    public EventCallback<Option> GetSelectedOption { get; set; }

    private Selector mySelector = new Selector(myOptions);

    // 下拉选项数据源
    private static List<Option> myOptions = new List<Option>() {
        new Option(1, "Fred", "style3", 2),
        new Option(2, "Joe", "style1", 4),
        new Option(3, "Jana", "style2", 4),
        new Option(4, "Mary", "style1", 3),
        new Option(5, "Howard", "style3", 1) };

    // 改为async Task,符合Blazor异步回调规范
    async Task SelectionChanged()
    {
        // 直接在回调中获取最新选中项,不再依赖渲染块赋值
        var selectedOption = mySelector.SelectedId > 0 
            ? mySelector.Options.Find(e => e.Id == mySelector.SelectedId) 
            : new Option();
        
        await GetSelectedOption.InvokeAsync(selectedOption);
    }

    public class Selector
    {
        public Selector(List<Option> options) => Options = options;

        public int SelectedId { get; set; } = 0;
        public List<Option> Options { get; set; }
    }

    public class Option
    {
        public Option(int id = 0, string? name = "", string? style = "", int stars = 0)
        {
            Id = id;
            Name = name;
            Style = style;
            Stars = stars;
        }

        public int Id { get; set; }
        public string? Name { get; set; }
        public string? Style { get; set; }
        public int Stars { get; set; }
    }
}

修复后的父页面代码

@page "/"

<PageTitle>Index</PageTitle>

<DropDownNames GetSelectedOption="getSelectedOption"></DropDownNames>

<br />

<p>You selected: @selectedOption.Id</p>
<p>@selectedOption.Name has @selectedOption.Stars.ToString() stars</p>

@code {
    DropDownNames.Option selectedOption = new DropDownNames.Option();
    
    public void getSelectedOption(DropDownNames.Option option)
    {
        selectedOption = option;
        // 显式通知UI更新,确保状态变更及时生效
        StateHasChanged();
    }
}

关键修改说明

  • 移除渲染模板中对selectedOption的赋值逻辑,改为在SelectionChanged回调内直接获取最新选中项,确保传递给父组件的是当前最新值。
  • 将async void改为async Task,遵循Blazor异步事件处理的最佳实践,避免UI更新异常。
  • 父组件中添加StateHasChanged()显式触发UI刷新,确保选中状态变更能及时在页面上展示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 16:25:23