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

Blazor页面切换图表参数无刷新问题排查求助

Blazor页面切换榜单参数无刷新问题排查与修复

问题描述

使用Blazor搭建网站,页面包含两类单选按钮:

  • 6个用于选择列表类型(Overzichten => 预览)的单选按钮
  • 3个用于设置榜单参数(... van hitlijsten => 来自榜单)的单选按钮

切换列表类型时页面正常刷新并展示新列表,但切换榜单参数时页面无任何响应。

现有代码

父组件代码

<ul class="list-group lists" role="group">
    <li class="list-group-item subheader">Overzichten...</li>
    <li class="list-group-item lists">
        <input id="nummer1" name="overzichtgroep" type="radio" autocomplete="off" checked @onchange="@SetSelectedView" value="1" /> Alle nummer 1 hits
    </li>
    <li class="list-group-item lists">
        <input id="tipVanDeWeek" name="overzichtgroep" type="radio" autocomplete="off" @onchange="@SetSelectedView" value="2" /> Alle tips van de week
    </li>
    <!-- 省略其余4个预览类型单选按钮 -->
</ul>

<ul class="list-group lists" role="group">
    <li class="list-group-item subheader">... van hitlijsten</li>
    <li class="list-group-item lists">
        <input id="songs" name="hitlijstengroep" type="radio" autocomplete="off" checked @onchange="@SetSelectedView" value="7" /> Songs
    </li>
    <li class="list-group-item lists">
        <input id="albums" name="hitlijstengroep" type="radio" autocomplete="off" @onchange="@SetSelectedView" value="8" /> Albums
    </li>
    <li class="list-group-item lists">
        <input id="nlV" name="hitlijstengroep" type="radio" autocomplete="off" @onchange="@SetSelectedView" value="9" /> Songs NL/V
    </li>
</ul>

@switch (_previewId)
{
    case 1:
        <div class="row lists">
            <AllNumber1Hits ListId=@_listId ListName=@_listName @ref="_allNumber1Hits" />
        </div>
        break;
    case 2:
        <div class="row lists">
            <AllNumber1Tips ListId=@_listId ListName=@_listName @ref="_allNumber1Tips" />
        </div>
        break;
    <!-- 省略case3到case6的代码 -->
}

@code {
    private int _previewId { get; set; } = 1;
    private int _chartId { get; set; } = 7;
    private int _listId { get; set; } = 1;
    private string _listName { get; set; } = "Songs";
    // 子组件引用
    private AllNumber1Hits _allNumber1Hits;
    private AllNumber1Tips _allNumber1Tips;

    protected override void OnInitialized()
    {
        try
        {
            UpdateView(1);
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
    }

    private void UpdateView(int id)
    {
        if (id > 0 && id < 7)
            _previewId = id;
        else if (id > 6 && id < 10)
            _chartId = id;

        switch (_chartId)
        {
            case 7:
                _ListId = 1;
                _ListName = "Songs";
                break;
            case 8:
                _ListId = 2;
                _ListName = "Albums";
                break;
            case 9:
                _ListId = 3;
                _ListName = "Songs NL/V";
                break;
        }
    }

    private void DoRefresh()
    {
        if (_allNummer1Hits != null)
            _allNummer1Hits.Refresh();

        if (_allNummer1Tips != null)
            _allNummer1Tips.Refresh();
    }

    public void SetSelectedView(ChangeEventArgs args)
    {
        if (args != null && args.Value != null)
        {
            int id;
            int.TryParse(args.Value.ToString(), out id);

            UpdateView(id);
            DoRefresh();
        }
    }
}

子组件代码(以AllNumber1Hits为例)

@code
{
    private List<AllNumber1HitsModel> model { get; set; }
    [Parameter] public int ListId { get; set; }
    [Parameter] public string ListName { get; set; } = string.Empty;
    // 假设_statisticsService已通过注入获取
    [Inject] private IStatisticsService _statisticsService { get; set; }

    protected override async Task OnInitializedAsync()
    {
        try
        {
            model = await _statisticsService.GetAllNumber1Hits(ListId, ListName);
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
    }

    public void Refresh() 
    { 
        StateHasChanged(); 
    }
}

代码中的问题与修复方案

1. 字段大小写拼写错误

父组件UpdateView方法中,给_ListId和_ListName赋值,但私有字段实际是_listId(小写l)和_listName(小写l),导致参数无法正确更新到子组件。

修复:将UpdateView中的_ListId改为_listId,_ListName改为_listName,保持字段名称一致:

switch (_chartId)
{
    case 7:
        _listId = 1;
        _listName = "Songs";
        break;
    case 8:
        _listId = 2;
        _listName = "Albums";
        break;
    case 9:
        _listId = 3;
        _listName = "Songs NL/V";
        break;
}

2. 单选按钮选中状态未绑定到状态变量

现有单选按钮的checked属性是硬编码的,未绑定到父组件的_previewId或_chartId,导致切换后选中状态不会同步,且初始状态可能异常。

修复:给每个单选按钮的checked属性绑定对应的状态判断:

  • 预览类型单选按钮示例:
<input id="nummer1" name="overzichtgroep" type="radio" autocomplete="off" checked="@(_previewId == 1)" @onchange="@SetSelectedView" value="1" />
  • 榜单参数单选按钮示例:
<input id="songs" name="hitlijstengroep" type="radio" autocomplete="off" checked="@(_chartId ==7)" @onchange="@SetSelectedView" value="7" />

3. 子组件未重新获取数据

子组件的Refresh方法仅调用StateHasChanged(),但没有重新调用数据接口获取新参数下的数据;同时子组件未监听参数变化,当父组件传递的ListId/ListName更新时,不会自动触发数据刷新。

修复:

  • 重写子组件的OnParametersSetAsync方法,监听参数变化并重新获取数据:
private int _previousListId;
private string _previousListName;

protected override async Task OnParametersSetAsync()
{
    // 仅当参数变化时重新获取数据,避免重复请求
    if (ListId != _previousListId || !string.Equals(ListName, _previousListName))
    {
        model = await _statisticsService.GetAllNumber1Hits(ListId, ListName);
        _previousListId = ListId;
        _previousListName = ListName;
    }
}
  • 同时更新Refresh方法,确保手动调用时也能重新获取数据:
public async Task Refresh() 
{ 
    model = await _statisticsService.GetAllNumber1Hits(ListId, ListName);
    StateHasChanged(); 
}

4. 子组件引用名称拼写不一致

父组件DoRefresh方法中使用_allNummer1Hits,但switch中定义的子组件引用是@ref="_allNumber1Hits"(Number vs Nummer),导致无法正确调用子组件的Refresh方法。

修复:统一引用名称,比如都改为_allNumber1Hits:

private void DoRefresh()
{
    if (_allNumber1Hits != null)
        _allNumber1Hits.Refresh();

    if (_allNumber1Tips != null)
        _allNumber1Tips.Refresh();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 18:10:29