我正在通過閱讀微軟的Blazor檔案來學習Blazor,但在理解這個關于覆寫引數問題的例子時遇到了問題。以下是示例代碼:
子組件:
< div @onclick="Toggle" class="card bg-light mb-3" style="width: 30rem">
<div class="card-body">
<h2 class="card-title">Toggle (<code> Expanded< /code> = @Expanded)</h2>
@if (Expanded)
{
<p class="card-text"> @ChildContent</p>
}
</div>
</div>
@code {
[Parameter]。
public bool Expanded { get; set; }
[Parameter]。
public RenderFragment ChildContent { get; set; }
private void Toggle()
{
Expanded = !Expanded;
}
}
父級:
@page "/expander-example"/span>
<Expander Expanded="true">
擴展器1內容
</Expander>
<Expander Expanded="true" />
<按鈕 @onclick="StateHasChanged">。
呼叫StateHasChanged
</button>
令我困惑的是:
為什么第二個
Expander沒有被重新渲染,而且引數系結也不起作用?檔案在這里試圖展示的問題到底是什么?當父級組件重置其狀態時,我希望這一變化能夠反映在子級組件上,這正是第一個所謂有問題的擴展器所做的。
為什么會有這樣的問題?
uj5u.com熱心網友回復:
該問題在這一段中被描述。
一個子組件收到新的引數值,當父組件重新提交時可能會覆寫現有的值。在開發帶有一個或多個資料系結引數的組件時,不小心覆寫了子組件中的引數值,而開發者直接向子組件中的引數寫入時,往往會發生這種情況
如果你想讓子組件中的引數值被覆寫,那么你就需要在子組件中加入一個新的引數。
如果你不想讓子組件依賴父組件的屬性,就不要把這個屬性作為引數傳給子組件。為了使例子明確,它們會觸發StateHasChanged方法來啟動父頁面上的變化檢測。這反過來又會觸發子頁面的重新渲染,如果你想保持子頁面的開放,這可能不是一個理想的行為。這就是為什么他們建議在子頁面中使用私有變數來將其狀態與父頁面隔離。
這不是最大的問題:)
MSDN沒有告訴你的是,在使用Blazor時,你遲早會意識到它的變化檢測策略與廣泛使用的SPA框架(如Angular或React)相比有很大的不同。這些框架只檢測組件中定義的內部狀態(類變數)的變化。相反,Blazor喜歡重新渲染整個頁面及其所有子頁面,即使在一些任意的情況下,例如當你點擊頁面上的某個隨機位置。
換句話說,即使你不明確呼叫StateHasChanged,你也可能看到同樣的問題。
uj5u.com熱心網友回復:
- 為什么第二個Expander沒有被重新渲染,而且引數系結也沒有發揮作用?
因為有一個簡單值型別和參考型別(ChildContent)的引數為空。渲染引擎認為 "這里沒有任何變化",因此跳過了它。
那個布爾引數被 "從內部 "改變了,這正是 "重寫引數 "的問題所在。
。第一個<Expander>有一個非空的ChildContent,然后引擎沒有再深究,它假定那是一個可變的物件,并重新提交組件。
注意,這意味著在傳遞復雜的物件而不是價值型別時有一個隱藏的成本。<PersonCard PersonId="person.Id" />將不會像<PersonCard Person="person" />
uj5u.com熱心網友回復:
檔案在這里試圖展示的問題到底是什么?當 父級組件重置其狀態時,我希望這一變化能反映在子級組件上。 反映到子組件上,這正是第一個 膨脹器所做的事情。
其目的是警告不要使用公共引數來維護你只想從組件內部控制的組件的內部狀態。
想象一下這樣的場景:您有一個可編輯的標題,其細節處于折疊狀態。模型類Title也有一些其他屬性(為簡潔起見略過)。
請考慮以下幾點:
<TitleEditor Title="@title"/span> @OnTitleChanged="RefreshTitle"/span>/>
<Details Content="@content" CollapseState="@areDetailsCollapsed"/>
@代碼
{
TitleClass title = new ();
ContentClass content = new ();
bool areDetailsCollapsed = true;
void RefreshTitle(string title)
{
title.Text = title;
StateHasChanged()。
}
}
用戶更新標題。這就呼叫了 "RefreshTitle",其目的是只更新標題。然而,由于涉及到參考型別引數,Details也被重繪 。這將導致Details的內部collapse狀態被重置。這是一個完全意想不到的副作用。
此外,StateHasChanged()會級聯重繪 樹上的每個子組件。因此,任何父節點中的任何StateHasChanged()都將導致一個組件失去其狀態。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/334304.html
標籤:
下一篇:如何在同級視圖之間傳遞環境物件?
