在 Blazor 中将值从子组件传递到父页面的良好做法?

Posted

技术标签:

【中文标题】在 Blazor 中将值从子组件传递到父页面的良好做法?【英文标题】:Good practice to pass values from child component to parent page in Blazor? 【发布时间】:2021-09-11 11:53:07 【问题描述】:

我不确定在 Blazor 中使用我的方法将对象从子组件传递到其使用父页面时是否犯了错误。 我有一个带有 ID、名称的 poco 类。从 poco 类 obj 列表中选择 div 的组件。 用户选择一个条目,该条目应显示在父页面上。 我没有经验看到我的解决方案有任何问题。 1)我做对了吗? 2)如果一切正常, OnInitializedAsync() 没有等待(父),我应该使用 OnInitialized() 代替吗? 3) Dispose 的使用是否正确? 4)如果我在一个应用程序中为不同的组件等使用相同的方法可能 20 次,这个解决方案可以吗?这个规模可以吗? 谢谢,不好

父页面:

@page "/"
@inject MitarbeiterEventService MitarbeiterEventService

@implements IDisposable

<h1>ParentPage</h1>
<MitarbeiterSel></MitarbeiterSel>
<br />

@if (SelMitarbeiterFromChild != null)

    <p>Selected Obj. from Child: @SelMitarbeiterFromChild.Name </p>


@code
    public MitarbeiterLite SelMitarbeiterFromChild;

    protected override async Task OnInitializedAsync()
    
        MitarbeiterEventService.EventMitarbeiterChangedInComp += HandelOnMitarbeiterChangedInComp;
    

    public async void HandelOnMitarbeiterChangedInComp(object sender, MitarbeiterLite selMitarbeiter)
    
        SelMitarbeiterFromChild = selMitarbeiter;

        await InvokeAsync(() =>
        
            StateHasChanged();

        );
    

    public void Dispose()
    
        MitarbeiterEventService.EventMitarbeiterChangedInComp -= HandelOnMitarbeiterChangedInComp;
    

来自服务的代码(在实际应用中我使用 MVVM,因此事件代码将在 ViewModel 中):

    public class MitarbeiterEventService
    
        public event EventHandler<MitarbeiterLite> EventMitarbeiterChangedInComp;
        public void FireEvent(MitarbeiterLite selMitarbeiterFromComp)
        
            EventMitarbeiterChangedInComp?.Invoke(this, selMitarbeiterFromComp);
        
    

最后是它自己的组件:

@inject MitarbeiterEventService  MitarbeiterEventService

<h3>MitarbeiterSelection</h3>

<select class="form-control col-6" @onchange="@(x => OnMitarbeiterSelectedChanged(x.Value.ToString()))">
    <option value="" disabled selected hidden>--Mitarbeiter--</option>
    @foreach (var mita in MitarbeiterLitesLst)
    
        <option value=@mita.Id>@mita.Name </option>
    
</select>

@code 
    //Ini List 
    public List<MitarbeiterLite> MitarbeiterLitesLst = new List<MitarbeiterLite>

        new MitarbeiterLite("Henry"),
        new MitarbeiterLite("John"),
        new MitarbeiterLite("Sue"),
        new MitarbeiterLite("Mary"),
        new MitarbeiterLite("Jimmy")
    ;

    public void OnMitarbeiterSelectedChanged(string guidAsString)
    
        MitarbeiterEventService.FireEvent(MitarbeiterLitesLst.FirstOrDefault(x => x.Id.ToString() == guidAsString));
    

【问题讨论】:

你的方法没有错。 Service vs EventCallback - 开发者的选择。我总是使用包含数据访问代码以及与该数据相关的事件的服务。 【参考方案1】:

要与父级通信,请使用 EventCallback。当事件的使用者不是父母或孩子,而是应用程序中与您选择项目的组件没有直接关系的其他组件时,事件服务会更有用。

在你的场景中,我会选择:

组件

<h3>MitarbeiterSelection</h3>

<select class="form-control col-6" 
        @onchange="@(x => OnMitarbeiterSelectedChanged(x.Value.ToString()))">
    <option value="" disabled selected hidden>--Mitarbeiter--</option>
    @foreach (var mita in MitarbeiterLitesLst)
    
        <option value=@mita.Id>@mita.Name </option>
    
</select>

@code 
    [Parameter] public EventCallback<MitarbeiterLite> OnItemSelected  get; set;  

    //Ini List 
    public List<MitarbeiterLite> MitarbeiterLitesLst = new List<MitarbeiterLite>
    
        new MitarbeiterLite("Henry"),
        new MitarbeiterLite("John"),
        new MitarbeiterLite("Sue"),
        new MitarbeiterLite("Mary"),
        new MitarbeiterLite("Jimmy")
    ;

    public void OnMitarbeiterSelectedChanged(string guidAsString)
    
        MitarbeiterLite selected = 
            MitarbeiterLitesLst
            .FirstOrDefault(x => x.Id.ToString() == guidAsString);

        OnItemSelected.InvokeAsync(selected);
    

父页面

@page "/"
<h1>ParentPage</h1>
<MitarbeiterSel OnItemSelected=@HandleOnMitarbeiterChangedInComp
                />
<br />

@if (SelMitarbeiterFromChild != null)

    <p>Selected Obj. from Child: @SelMitarbeiterFromChild.Name </p>


@code
    public MitarbeiterLite SelMitarbeiterFromChild;

    public async Task HandelOnMitarbeiterChangedInComp(
        MitarbeiterLite selMitarbeiter)
    
        SelMitarbeiterFromChild = selMitarbeiter;
    

【讨论】:

谢谢它正在工作。您能否详细说明两种解决方案之间的区别。如果可能的话,Pro/Con 多一点。我从您的帖子中了解到,如果组件/页面不是父/子,我应该使用事件解决方案。就像我需要来自没有 GUI 的类中的组件的输入。如果我想在同一页面上将信息从孩子传递给父母,我应该使用参数 EventCallBack 解决方案!正确的?你有关于原因的信息吗?再次感谢 嗯,我很难完全实施这个解决方案。当我尝试在我的 MVVM 模式中使用它时,我的问题就开始了。如果我在组件的直接代码块中有 [Parameter] EventCallback 和 OnSelChange 方法,它就可以工作。但我不希望视图中的代码。我在视图中注入 ViewModel。如果我在 ViewModel-Class 中有 [Parameter] 等内容,那么 Blazor 会在 Build-> Error 上告诉我组件没有具有指定名称的参数??? 我知道很多人都在 Blazor 中谈论过 MVVM,但我真的不明白它的意义所在。 Blazor 在其在 EditForm 中对模型的 OWN 使用以及在依赖注入的使用中实现了足够好的关注点分离。我是说。 . .如果需要,您可以为所有业务逻辑使用单独的类库。

以上是关于在 Blazor 中将值从子组件传递到父页面的良好做法?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Reactjs 中将数据从子组件传递到父组件? [复制]

在 React Native 中将状态从子组件传递到父组件

如何在Angular中将表单数据从子组件传输到父组件

如何为 v-select 组件从子级传递值到父级

如何在反应中将数组从子组件发送到父组件?

使用 Vue.js 将信息从子组件传递到父组件