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

Blazor组件中泛型列表集合的变更检测方案问询

Blazor中检测泛型列表集合内容变更的方案

因为List<T>是引用类型,仅修改集合内容(比如Clear())不会改变引用地址,所以子组件的OnParametersSet里通过引用对比无法触发预期逻辑。以下是几种可行的解决方式:

方案一:使用不可变集合模式(推荐)

每次修改集合时,创建新的集合实例而非修改原集合内容。这样父组件传递的引用会更新,子组件能通过OnParametersSet检测到变化。

修改父组件Index的ChangeDates方法:

private void ChangeDates()
{
    // 替换原集合为新实例,而非清空原集合
    dates = new List<DateClass>();
    // 如果是添加/修改元素,也用新集合:dates = dates.Where(...).ToList(); 或 dates = new List<DateClass>(dates) { newItem };
}

子组件ViewerComp的逻辑可保留原引用对比,此时就能触发自定义操作:

protected override void OnParametersSet()
{
    if (dates != Dates)
    {
        dates = Dates;
        // 执行你的自定义操作
        Console.WriteLine("集合已更新");
    }
}

方案二:手动对比集合内容

如果必须保留原集合引用,可以在OnParametersSet中对比集合的内容差异,而非仅对比引用。

子组件ViewerComp修改如下:

@code {
    [Parameter]
    public List<DateClass> Dates { get; set; }

    private List<DateClass> _previousDates;

    protected override void OnInitialized()
    {
        _previousDates = Dates?.Select(d => new DateClass { StartDate = d.StartDate, EndDate = d.EndDate }).ToList();
    }

    protected override void OnParametersSet()
    {
        // 对比集合内容是否变化
        bool hasChanged = false;
        if ((Dates == null && _previousDates != null) || (Dates != null && _previousDates == null))
        {
            hasChanged = true;
        }
        else if (Dates != null && _previousDates != null)
        {
            if (Dates.Count != _previousDates.Count)
            {
                hasChanged = true;
            }
            else
            {
                // 逐个元素对比(DateClass是值类型字段可直接对比;若为引用类型需重写Equals或自定义对比逻辑)
                hasChanged = !Dates.SequenceEqual(_previousDates);
            }
        }

        if (hasChanged)
        {
            // 执行自定义操作
            Console.WriteLine("集合内容已变更");
            // 更新缓存的旧集合
            _previousDates = Dates?.Select(d => new DateClass { StartDate = d.StartDate, EndDate = d.EndDate }).ToList();
        }
    }
}

为了让SequenceEqual正确对比,可为DateClass重写Equals和GetHashCode方法:

public class DateClass
{
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }

    public override bool Equals(object obj)
    {
        return obj is DateClass other &&
               StartDate == other.StartDate &&
               EndDate == other.EndDate;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(StartDate, EndDate);
    }
}

方案三:使用ObservableCollection

利用ObservableCollection<T>的CollectionChanged事件,实时监听集合内容的变化。

首先修改父组件的集合类型:

@code{
    private ObservableCollection<DateClass> dates = new ObservableCollection<DateClass>()
    {
        new DateClass(){StartDate = new DateTime(2021,12,01), EndDate = new DateTime(2021,12,21)}
    };

    private void ChangeDates()
    {
        dates.Clear();
    }
}

子组件ViewerComp中订阅事件:

@implements IDisposable

<div>
    @foreach (DateClass date in Dates)
    {
        <div> @(date.EndDate - date.StartDate).Days</div>
    }
</div>

@code {
    [Parameter]
    public ObservableCollection<DateClass> Dates { get; set; }

    protected override void OnInitialized()
    {
        if (Dates != null)
        {
            Dates.CollectionChanged += OnDatesCollectionChanged;
        }
    }

    private void OnDatesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        // 执行自定义操作,比如更新本地缓存、触发UI刷新等
        Console.WriteLine("集合内容变更:" + e.Action);
        // 若需更新UI,调用StateHasChanged()
        StateHasChanged();
    }

    // 组件销毁时取消订阅,避免内存泄漏
    public void Dispose()
    {
        if (Dates != null)
        {
            Dates.CollectionChanged -= OnDatesCollectionChanged;
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 18:05:17