原文鏈接:https://blazor-university.com/forms/editcontext-fieldidentifiers-and-fieldstate/
EditContext、FieldIdentifiers 和 FieldState
請注意,對于那些希望了解 Blazor 如何“在后臺”工作的人來說,這是一個高級主題。無需了解此信息即可正常使用 Blazor - 但我覺得了解內部信息可能是有益的。
讓我們從描述 Blazor 如何維護表單數據的元狀態的 UML 圖開始。
EditContext
每當 EditForm.Model
更改(表單中正在修改的對象)時,都會執行 EditForm.OnParametersSet
并創建一個新的 EditContext
實例。EditForm
組件將此 EditContext
聲明為級聯值[1],以便表單中的任何組件都可以訪問它。
EditContext
是當前正在編輯的對象的表單元數據持有者。在表單中編輯對象(例如 Person
)時,Blazor 需要了解有關該對象的其他信息,以便提供更豐富的用戶體驗。Blazor 持有的其他信息告訴我們:
如果模型的特定屬性已被手動更改。
哪些模型屬性有驗證錯誤,這些錯誤是什么。
顯然,正在編輯的模型類應該只代表我們特定的業務需求,因此讓我們的模型類實現這些額外的用戶界面狀態信息將是一個關注點沖突——因此 Blazor 將這些額外信息本身存儲在 EditContext
中。這就是 EditForm
在其 Model
更改時創建一個新的 EditContext
的原因,因為如果 Model
更改,則 EditContext
中保存的信息不再相關。
FieldIdentifier
FieldIdentifier
的目的是為對象的特定屬性提供標識。它與 System.Reflection.PropertyInfo
不同,因為它標識特定對象實例的屬性,而反射標識類的屬性。
給定一個具有名為 PostalCode
的屬性的 Address
類,我們可以預期以下相等規則:
值 | 是否相等? |
---|---|
// 反射:不同實例上的相同屬性 | |
address1.GetProperty(“郵政編碼”); address2.GetProperty(“郵政編碼”); | 是 |
// FieldIdentifier:同一個實例的同一個屬性 | |
new FieldIdentifier(address1, “PostalCode”); new FieldIdentifier(address1, “PostalCode”); | 是 |
// FieldIdentifier:不同實例上的相同屬性 | |
new FieldIdentifier(address1, “PostalCode”); | |
new FieldIdentifier(address2, “PostalCode”); | 否 |
當 UI 狀態(例如驗證錯誤)需要與輸入值相關聯時,我們需要某種方式來識別該狀態與哪些輸入數據相關。在以前的 Web 技術中,通常使用字符串來標識單個輸入,以下是一些示例:
EmailAddress
HomeAddress.PostalCode
WorkAddress.PostalCode
一旦用戶界面變得復雜,這些路徑可能會非常復雜。
Contacts[0].Name
Contacts[0].ContactDetails[0].TelephoneNumber
Contacts[0].ContactDetails[0].EmailAddress
Contacts[9].ContactDetails[3].TelephoneNumber
Blazor 簡化了此過程,因為它的設計方式允許它始終在同一進程中處理對象和屬性標識。這使我們能夠通過存儲兩條簡單的信息來識別任何對象的任何屬性。
1.直接引用對象本身。2.該對象的屬性名稱。
標識現在很簡單,并且(與字符串路徑不同)永遠不必更改以考慮數據的更改,例如從數組中刪除項目。例如,在字符串路徑方法中,如果要刪除列表中的第一個聯系人,則需要將 Contacts[9].ContactDetails[3].TelephoneNumber
更改為 Contacts[8].ContactDetails[3].TelephoneNumber
。Blazor 的 ObjectReference/PropertyName
方法避免了這種復雜性。
即使我們編寫自己的自定義驗證器與服務器對話以確定有效性(例如唯一值的可用性,例如 EmailAddress
),我們的 Blazor 驗證器也會獲得一個 FieldIdentifier
的實例,然后可以關聯來自服務器調用的結果直接使用正確對象實例的正確屬性。
FieldState
FieldState 類包含有關任何對象屬性的附加信息。EditContext
類具有 Dictionary<FieldIdentifier, FieldState>
類型的私有屬性 - 這使 Blazor 可以將其附加狀態存儲在扁平列表中以便快速訪問。
給定以下模型
protected?override?OnInitialized()
{var?country1?=?new?Country{Code?=?"GB",Name?=?"Great?Britain"};var?address1?=?new?Address{Line1?=?"The?Mansion",Line2?=?"Bletchley?Park",Line3?=?"Sherwood?Drive",Town?=?"Bletchley",Area?=?"Milton?Keynes",PostalCode?=?"MK3?6EB",Country?=?country1};var?person1?=?new?Person{Name?=?"My?name",Age?=?12,HomeAddress?=?address1,TelephoneNumber?=?"+44?(0)?1908?64004"};
}
我們希望看到如下的字段標識符:
注意: 條目僅在需要時添加到字典中。