【问题标题】:blazor how to pass the variable value in the component to the MainLayout componentblazor如何将组件中的变量值传递给MainLayout组件
【发布时间】:2021-01-24 16:25:26
【问题描述】:

我使用vs 2019自带的blazor服务器模板创建了一个项目,如何将Counter.razor组件中的currentCount属性值传递给MainLayout.razor组件?

并且在页面加载时,Mainlayout组件中传入的currentCount值与Counter组件中的currentCount值相同。而当currentCount值发生变化时,Mainlayout中的currentCount值也会发生变化。

MainLayout.razor:

@inherits LayoutComponentBase
<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <div class="main">
        <div class="top-row px-4 auth">
            <LoginDisplay />
        </div>
        <div class="content px-4">
            @Body
        </div>
    </div>
</div>

Counter.razor

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

【问题讨论】:

    标签: blazor


    【解决方案1】:

    我相信您正在寻找级联参数。级联值和参数是一种将值从组件传递给其所有后代的方法,而无需使用传统的组件参数。

    https://docs.microsoft.com/en-us/aspnet/core/blazor/components/cascading-values-and-parameters?view=aspnetcore-5.0

    级联值的来源示例将级联到包含的组件。

    <CascadingValue Value="@CurrentCount">
     @Body
    </CascadingValue>
    
    @code{
       int CurrentCount = 5;
    }
    

    内部组件应该如下装饰它的属性。

    [CascadingParameter] int CurrentCount { get; set; }
    

    【讨论】:

    • 级联参数与他要求的相反。他想将 UP 从页面传递给主人,而不是级联到页面。我认为唯一干净的解决方案是简单地将 NavLink 移出母版页并直接在每个页面上设置其属性。我也见过 AppState 方法,但它假定每个页面都有一个状态。
    【解决方案2】:

    一种方法是使用状态服务。

    为您的项目添加一个类 MainLayoutState.cs

    public class MainLayoutState
    {
        int currentCount;
        public int CurrentCount
        {
            get => currentCount;
            set
            {
                if (currentCount == value) return;
                currentCount = value;
                CurrentCountChanged?.Invoke(this, value);
            }
        }
        public event EventHandler<int> CurrentCountChanged;
    }
    

    更新Startup.cs,以便注入。

    services.AddScoped<MainLayoutState>();
    

    在布局和柜台剃须刀组件中使用它。

    MainLayout.razor

    @inherits LayoutComponentBase
    @implements IDisposable
    @inject MainLayoutState LayoutState
    <div class="page">
        <div class="sidebar">
            <NavMenu />
        </div>
    
        <div class="main">
            <div class="top-row px-4">
                <LoginDisplay /> @LayoutState.CurrentCount
            </div>
    
            <div class="content px-4">
                @Body
            </div>
        </div>
    </div>
    @code {
        protected override void OnInitialized()
            => LayoutState.CurrentCountChanged += CountChanged;
    
        void CountChanged(object sender, int e) => StateHasChanged();
    
        public void Dispose() => LayoutState.CurrentCountChanged -= CountChanged;
    }
    

    更改Counter.razor中的代码块

    @code {
    
        int CurrentCount { 
            get => LayoutState.CurrentCount; 
            set => LayoutState.CurrentCount = value; }
    
        [Inject]
        MainLayoutState LayoutState { get; set; }
    
        void IncrementCount()
        {
            CurrentCount++;
        }
    
    }
    

    【讨论】:

    • 这似乎正在影响全局状态,就好像您只有一个 MainLayout 实例一样。但是每个页面都可以有一个新的状态副本,用于它自己的主布局实例。
    • @ChrisBordeman 如果需要,请为状态实例使用工厂/字典键排列。我会创建一个工厂服务来管理它。
    猜你喜欢
    • 2021-10-27
    • 2021-04-05
    • 2023-03-20
    • 2017-05-19
    • 1970-01-01
    • 2017-05-30
    • 2021-01-18
    • 1970-01-01
    • 2021-11-16
    相关资源
    最近更新 更多