blazor webassembly 为什么我在页面和子组件之间无限循环?
blazor webassembly Why I am getting infinite looping between Page and subComponent?
我的应用程序在 VS2022 C# Blazor WASM 中使用 .Net 6 托管。我有一个带有子组件的 Blazor 页面,该页面具有允许 PAGE 查看 select-框的功能 Active/Inactive(两个选项)和一个用于客户名称列表(缩写)的 select 框。
PAGE 如下所示:
TOP 矩形是子组件,其“行为”类似于 returns(通过 CALLBACK)selected“CustomerID”(显示为 'ARCTB' ).子组件通过 CALLBACK 参数对带有 'selected' CustomerID 的父表单的“select-选择”(@onchange=) 作出反应,因此父页面可以为该 selected 客户。
在确定客户列表和第一个 CustomerID 的初始子组件 OnParametersSetAsync() 上,使用 CustomerID 的 List[0] 元素对 PAGE 进行回调。在 PAGE 的这一点上,对 PAGE 和子组件都进行了重新呈现。这会导致子组件的 OnParametersSetAsync() 再次触发,并再次触发 CALLBACK 以进行无限循环。
第二个矩形是 PAGE-html 的一部分,允许用户 select 活动或非活动车辆,将客户车辆列表过滤为 _listOfAllVehicles( v => v.IS_ACTIVE == true-or-false)
。
出现无限循环的问题是因为对PAGE的CALLBACK强制重新渲染,然后子组件从OnParametersSetAsync()方法执行另一个CALLBACK。这是我求解答的死循环问题
作为最新 Blazor 的新手,我不确定 ShouldRender() 是否可以用于 PAGE 或子组件或两者?也许使用子组件“标志”来表示“OkToCallback”以限制重复的 CALLBACK 调用。
欢迎您提出意见、问题和答案。
应@Marius的要求,子组件代码如下。我已经包含了停止无限循环的“_IsLoading”测试。
谢谢@Marius 的回答。 :-)
protected override async Task OnParametersSetAsync() {
// Retain the Parameters.
_LoggedInCustomerName = pLoggedInCustomerName;
_LoggedInUserRoleName = pLoggedInRole;
_IsUserNotFCI = (_LoggedInUserRoleName != "FCI");
_IsActiveCustomers = (_ddlActive_Value == 1);
await Task.Delay(10);
_ddlCustomer_Value = RefreshCustomerList(_ddlActive_Value);
if (_ddlCustomer_Value > 0) {
// Set to first-option (index) (refer to wwwroot\index.html -- see OnAfterRender()
if (_IsLoading) {
// Update the selected customer.
ChangeEventArgs evntArgs = new ChangeEventArgs();
evntArgs.Value = _ddlCustomer_Value.ToString();
await SelectedCustomerChanged(evntArgs);
_IsLoading = false;
}
}
base.OnParametersSet();
}
private int RefreshCustomerList(int pCustomersActiveFlag) {
// Refresh the customer-list based on the 'ddlActiveFilter' ACTIVE-STATUS and USER-ROLE.
// Return the zero-th element's UID_CUSTOMER of the list of customers.
bool isActiveFlag = (pCustomersActiveFlag==1);
int retValue = 0;
if (_ListAllCustomers != null) {
// When LOGGEDIN-USER is NOT FCI, reduce the list to ONLY the loggedin-user customer.
if (_IsUserNotFCI) {
// This returns a list of a single <Customer> record.
_ListFilteredCustomers = _ListAllCustomers.Where(c => (c.TXT_CUSTOMER_NAME == _LoggedInCustomerName)).ToList();
} else {
// This returns a list of all ACTIVE or INACTIVE customers based on 'pCustomersActiveFlag' => 'isActiveFlag'.
_ListFilteredCustomers = _ListAllCustomers.Where(c => (c.BOOL_IS_CUST_ACTIVE == isActiveFlag)).OrderBy(r => r.TXT_CUSTOMER_ABBREV).ToList();
}
// Set the 'ddlCustomer_Value' to the UID of the first-customer in the list.
retValue = _ListFilteredCustomers[0].UID_CUSTOMER;
}
return retValue;
}
private async Task SelectedCustomerChanged(ChangeEventArgs e) { // This is the event after selection is made.
int iArgValue = Convert.ToInt32(e.Value);
_ddlCustomer_Value = Convert.ToInt32(e.Value);
Customer customer = _ListFilteredCustomers!.Where(rec => rec.UID_CUSTOMER == _ddlCustomer_Value).FirstOrDefault();
if (customer != null) {
_SelectedCustUID = customer.UID_CUSTOMER;
_SelectedCustName = customer.TXT_CUSTOMER_NAME;
}
// Callback to Parent.
await OnCustomerSelection.InvokeAsync(_ddlCustomer_Value);
}
OnParametersSetAsync
and OnParametersSet
将在参数更改时触发,即使值与之前相同。您可以编写一些代码来避免这种情况。
示例:Is previous parameter value the same as current ? skip load : load
private string _cachedValue;
[Parameter]
public string parameterValue { get; set; }
protected override async Task OnParametersSetAsync()
{
if (parameterValue != _cachedValue)
{
_cachedValue = parameterValue;
LoadComponent();
}
}
private void LoadComponent() {
//...
}
以上只是执行此操作的一种方法的示例。使用适合您的代码的逻辑。
我的应用程序在 VS2022 C# Blazor WASM 中使用 .Net 6 托管。我有一个带有子组件的 Blazor 页面,该页面具有允许 PAGE 查看 select-框的功能 Active/Inactive(两个选项)和一个用于客户名称列表(缩写)的 select 框。
PAGE 如下所示:
TOP 矩形是子组件,其“行为”类似于 returns(通过 CALLBACK)selected“CustomerID”(显示为 'ARCTB' ).子组件通过 CALLBACK 参数对带有 'selected' CustomerID 的父表单的“select-选择”(@onchange=) 作出反应,因此父页面可以为该 selected 客户。
在确定客户列表和第一个 CustomerID 的初始子组件 OnParametersSetAsync() 上,使用 CustomerID 的 List[0] 元素对 PAGE 进行回调。在 PAGE 的这一点上,对 PAGE 和子组件都进行了重新呈现。这会导致子组件的 OnParametersSetAsync() 再次触发,并再次触发 CALLBACK 以进行无限循环。
第二个矩形是 PAGE-html 的一部分,允许用户 select 活动或非活动车辆,将客户车辆列表过滤为 _listOfAllVehicles( v => v.IS_ACTIVE == true-or-false)
。
出现无限循环的问题是因为对PAGE的CALLBACK强制重新渲染,然后子组件从OnParametersSetAsync()方法执行另一个CALLBACK。这是我求解答的死循环问题
作为最新 Blazor 的新手,我不确定 ShouldRender() 是否可以用于 PAGE 或子组件或两者?也许使用子组件“标志”来表示“OkToCallback”以限制重复的 CALLBACK 调用。
欢迎您提出意见、问题和答案。
应@Marius的要求,子组件代码如下。我已经包含了停止无限循环的“_IsLoading”测试。
谢谢@Marius 的回答。 :-)
protected override async Task OnParametersSetAsync() {
// Retain the Parameters.
_LoggedInCustomerName = pLoggedInCustomerName;
_LoggedInUserRoleName = pLoggedInRole;
_IsUserNotFCI = (_LoggedInUserRoleName != "FCI");
_IsActiveCustomers = (_ddlActive_Value == 1);
await Task.Delay(10);
_ddlCustomer_Value = RefreshCustomerList(_ddlActive_Value);
if (_ddlCustomer_Value > 0) {
// Set to first-option (index) (refer to wwwroot\index.html -- see OnAfterRender()
if (_IsLoading) {
// Update the selected customer.
ChangeEventArgs evntArgs = new ChangeEventArgs();
evntArgs.Value = _ddlCustomer_Value.ToString();
await SelectedCustomerChanged(evntArgs);
_IsLoading = false;
}
}
base.OnParametersSet();
}
private int RefreshCustomerList(int pCustomersActiveFlag) {
// Refresh the customer-list based on the 'ddlActiveFilter' ACTIVE-STATUS and USER-ROLE.
// Return the zero-th element's UID_CUSTOMER of the list of customers.
bool isActiveFlag = (pCustomersActiveFlag==1);
int retValue = 0;
if (_ListAllCustomers != null) {
// When LOGGEDIN-USER is NOT FCI, reduce the list to ONLY the loggedin-user customer.
if (_IsUserNotFCI) {
// This returns a list of a single <Customer> record.
_ListFilteredCustomers = _ListAllCustomers.Where(c => (c.TXT_CUSTOMER_NAME == _LoggedInCustomerName)).ToList();
} else {
// This returns a list of all ACTIVE or INACTIVE customers based on 'pCustomersActiveFlag' => 'isActiveFlag'.
_ListFilteredCustomers = _ListAllCustomers.Where(c => (c.BOOL_IS_CUST_ACTIVE == isActiveFlag)).OrderBy(r => r.TXT_CUSTOMER_ABBREV).ToList();
}
// Set the 'ddlCustomer_Value' to the UID of the first-customer in the list.
retValue = _ListFilteredCustomers[0].UID_CUSTOMER;
}
return retValue;
}
private async Task SelectedCustomerChanged(ChangeEventArgs e) { // This is the event after selection is made.
int iArgValue = Convert.ToInt32(e.Value);
_ddlCustomer_Value = Convert.ToInt32(e.Value);
Customer customer = _ListFilteredCustomers!.Where(rec => rec.UID_CUSTOMER == _ddlCustomer_Value).FirstOrDefault();
if (customer != null) {
_SelectedCustUID = customer.UID_CUSTOMER;
_SelectedCustName = customer.TXT_CUSTOMER_NAME;
}
// Callback to Parent.
await OnCustomerSelection.InvokeAsync(_ddlCustomer_Value);
}
OnParametersSetAsync
and OnParametersSet
将在参数更改时触发,即使值与之前相同。您可以编写一些代码来避免这种情况。
示例:Is previous parameter value the same as current ? skip load : load
private string _cachedValue;
[Parameter]
public string parameterValue { get; set; }
protected override async Task OnParametersSetAsync()
{
if (parameterValue != _cachedValue)
{
_cachedValue = parameterValue;
LoadComponent();
}
}
private void LoadComponent() {
//...
}
以上只是执行此操作的一种方法的示例。使用适合您的代码的逻辑。