簡體   English   中英

在 Blazor 中使用組件時從孩子到父母的通信

[英]Communicating from child to parent when using Components in Blazor

我有一個博客網站,評論在一個名為CommentListComponent中進行管理。

index.razor

...
Counting comments: @CommentCount
<CommentList PostId="@CurrentPost.Id" OnCommentCountChanged="OnCommentCountChangedHandler" />

@code {
    ...
    int CommentCount;
    public void OnCommentCountChangedHandler(int count)
    {
        CommentCount = count;
    }
}

現在是組件:

CommentList.razor

[Parameter] public int PostId { get; set; }
[Parameter] public EventCallback<int> OnCommentCountChanged { get; set; }
[Inject] ICommentService CommentService { get; set; }

List<Comment> AllComments { get; set; }    
bool flag;

protected override async Task OnParametersSetAsync()
{
    if (PostId && !flag)
    {
        flag = true;
        AllComments = await CommentService.GetComments(PostId);
        await CountComments();
    }
}
protected async Task CountComments()
{
    Console.WriteLine("CountComments called");
    if (AllComments == null) return;
    var count = AllComments.Count();
    await OnCommentCountChanged.InvokeAsync(count);
}

正如您在上面的代碼中看到的那樣,在我的組件中,我通過一個服務檢索了這篇文章的所有評論,然后我調用了一個方法來通知父級計數。

檢索到評論列表后,我需要將計數傳達給父母。 我發現重新計算此計數( CountingComments )的唯一地方是OnParametersSetAsync

你會注意到我使用了一個標志。 沒有這個標志,就會有一個永無止境的循環:

  • OnParametersSetAsync調用CountingComments
  • CountingComments調用OnCommentCountChanged
  • 此“調用”產生對OnParametersSetAsync的調用
  • ETC...

有了標志,就可以避免循環,但我想知道這是否是最好的方法?

不幸的是,不可能區分每個參數的變化。 如果我們有 2 或 3 個參數,如果其中一個參數發生更改,則觸發OnParametersSetAsync方法,但我們不知道涉及哪個參數。 此外,對EventCallback Parameter OnCommentCountChanged的調用也會觸發此OnParametersSetAsync而沒有興趣(在我的情況下)。

OnParametersSetAsync 方法中的代碼在每次執行該方法時都會多余地檢索注釋。 相反,您應該在創建 CommentList 組件時使用 OnInitalized(Async) 方法對僅檢索一次數據。

現在有了這種設計,只有在當前帖子(博客的,請注意)中添加了新評論時,您才需要通過再次調用 CommentService.GetComments 方法來刷新AllComments列表。 如何調用、何時調用等都取決於您的設計。

讓我在這里描述一個簡單可行的設計。 假設在您的博客文章底部是一個評論部分,您可以在其中輸入評論,然后單擊“保存我的評論”按鈕。 您可以定義一個服務或 Razor 組件來將添加的評論發布到相關的數據庫表中。 此服務或組件還應具有調用事件的代碼,以通知您的 CommentList 發生這種情況(添加了新評論)。 作為響應,您的代碼應調用 CommentService.GetComments 方法從數據庫中檢索一組新的評論。

不幸的是,無法區分每個參數的變化

為什么不?

這就是你應該如何定義你的[Parameter] public int PostId { get; set; } [Parameter] public int PostId { get; set; }

[Parameter] public int PostId { get; set; }

private int _internalPostId;
private int InternalPostId 
{ 
   get => _internalPostId; 
   set 
   {
     if(_internalPostId != value)
     {
        _internalPostId = value;

        // Can only be true if a new post is displayed or selected 
        // in the Index component, which requires you to retrieve the 
        // comments for the new post id passed. Put here code that 
        // call the method that perform the database access to
        // retrieve the comments. That should be the same code that 
        // you should have in OnInitalized(Async) pair of methods. So 
        // you can create a single method that should be called from 
        // OnInitalized(Async), and from here.
        // Understand that OnInitalized(Async) is called only once, 
        // when the component is created... When the PostId parameter 
        // changes, the Component is not created again, but re-used.
        // Note: If you define an asynchronous method that contain the 
        // code to retrieve the comments, you can still call it from 
        // here by applying the so-called fire-and-forget operation, 
        // as for instance:  _ = MyService.GetSomething();
     }
   } 
}

請注意,我引入了一個名為InternalPostId的新私有屬性。 使用它是因為子組件不應該改變參數屬性......它們應該被視為自動屬性。 希望你不會感到困惑。

您還需要重寫 OnParametersSet 方法,以便從 PostId 參數屬性更新內部屬性 InternalPostId。

 protected override void OnParametersSet()
    {
       if (InternalPostId != PostId)
       {
           InternalPostId = PostId;
       }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM