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

Blazor WASM .NET6:如何访问MainLayout头部组件并感知值变化

解决方案

1. 实现状态共享服务

创建单例服务统一管理头部组件的实例、状态和值变更通知:

public class HeaderComponentStateService
{
    private readonly Dictionary<Type, IHeaderComponent> _componentInstances = new();
    public event Action<Type, object>? ComponentValueChanged;

    // 注册头部组件实例
    public void RegisterComponent(Type componentType, IHeaderComponent component)
    {
        if (!_componentInstances.ContainsKey(componentType))
        {
            _componentInstances.Add(componentType, component);
            // 组件注册后立即推送初始值
            ComponentValueChanged?.Invoke(componentType, component.CurrentValue);
        }
    }

    // 根据组件类型获取实例
    public IHeaderComponent? GetComponent(Type componentType)
    {
        _componentInstances.TryGetValue(componentType, out var component);
        return component;
    }

    // 触发值变更全局通知
    public void TriggerValueChanged(Type componentType, object value)
    {
        ComponentValueChanged?.Invoke(componentType, value);
    }
}

// 定义头部组件统一接口,规范值操作
public interface IHeaderComponent
{
    object CurrentValue { get; }
    event Action<object>? ValueChanged;
}

在Program.cs注册为单例服务:

builder.Services.AddSingleton<HeaderComponentStateService>();

2. 改造头部组件实现统一接口

让所有头部组件实现IHeaderComponent,自身处理状态变更并同步到服务:

以MyComponent1为例:

<input type="text" @bind="_inputValue" @bind:after="NotifyValueChanged" />

@code {
    [Inject] private HeaderComponentStateService StateService { get; set; } = default!;

    private string _inputValue = "默认初始值";

    public object CurrentValue => _inputValue;
    public event Action<object>? ValueChanged;

    protected override void OnInitialized()
    {
        base.OnInitialized();
        StateService.RegisterComponent(typeof(MyComponent1), this);
    }

    private void NotifyValueChanged()
    {
        ValueChanged?.Invoke(_inputValue);
        StateService.TriggerValueChanged(typeof(MyComponent1), _inputValue);
    }
}

3. 简化MainLayout渲染逻辑

移除手动传递回调的逻辑,让组件通过依赖注入和状态服务交互:

<div class="top-row px-4">
    @foreach (var componentType in BaseParameters)
    {
        <DynamicComponent Type="@componentType" />
    }
</div>
<div id="mainContent" class="content px-4" style="padding:0;">
    @Body
</div>

@code {
    [Inject] public HeaderComponentStateService StateService { get; set; } = default!;

    public List<Type> BaseParameters { get; set; } = new List<Type> { typeof(MyComponent1), typeof(MyComponent2) };
}

4. 实际页面中访问组件与监听变更

在业务页面(如abc.razor)中,通过状态服务获取组件实例、初始值,并订阅变更:

<h3>MyComponent1 当前值:@_currentValue</h3>

@code {
    [Inject] private HeaderComponentStateService StateService { get; set; } = default!;

    private string _currentValue = string.Empty;

    protected override void OnInitialized()
    {
        base.OnInitialized();
        
        // 获取初始值
        var myComponent = StateService.GetComponent(typeof(MyComponent1)) as MyComponent1;
        if (myComponent != null)
        {
            _currentValue = (string)myComponent.CurrentValue;
        }

        // 订阅全局值变更事件
        StateService.ComponentValueChanged += OnComponentValueChanged;
    }

    private void OnComponentValueChanged(Type componentType, object value)
    {
        if (componentType == typeof(MyComponent1))
        {
            _currentValue = (string)value;
            StateHasChanged();
        }
    }

    public void Dispose()
    {
        // 取消订阅避免内存泄漏
        StateService.ComponentValueChanged -= OnComponentValueChanged;
    }
}

方案优势

  • 解耦设计:页面与头部组件通过状态服务间接交互,避免代码混乱
  • 初始值自动同步:组件注册时自动推送初始值,无需额外处理
  • 灵活访问:随时可通过组件类型从状态服务获取实例,调用组件方法或读取状态
  • 扩展性强:新增头部组件只需实现IHeaderComponent接口,无需修改布局或页面逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 09:20:14