在不相关的组件上调用 OnSetParameterAsync
OnSetParameterAsync being called on unrelated component
我目前正在开发一个使用 Blazor WebAssembly 作为我的前端框架的项目,但是,我在状态管理方面遇到了一些问题,我认为。这个问题出现在一个大型复杂的解决方案中,所以我重新创建并简化了它,这样我就可以在这里简明扼要地描述它,而不会显得臃肿。
我有一个包含两个组件的页面:一个朋友列表和一个关注者列表,每个组件都有一个按钮,用于切换按升序或降序对列表进行排序。
如果我重写,并在 FollowerList 组件内部的 OnParametersSetAsync 上放置一个断点,然后单击 [=] 的排序按钮81=]FriendList 组件它达到了我在 FollowerList 组件上设置的断点。
我的印象是 OnParametersSet/Async 只会在 属性 馈送到该组件的组件发生变化或 它的状态已经改变。
在我下面的代码中,您可以看到我有两个单独的列表,一个被馈送到一个组件,一个被馈送到另一个组件,所以我不确定如何在未触及的组件上触发此方法...
因此我的问题是:为什么它会在不相关的组件上遇到断点?这是故意的行为吗?
页面浏览量
Index page, with the two lists
Index.razor
@page "/"
<button value="Sort Friends" @onclick=SortFriends>Sort Friends</button>
<FriendList Friends=SortedFriends />
<button value="Sort Followers" @onclick=SortFollowers>Sort Followers</button>
<FollowerList Followers=SortedFollowers />
Index.cs(后面的代码)
using StateManagementTest.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace StateManagementTest.Pages
{
public partial class Index
{
public List<Friend> MyFriends { get; set; }
public List<Friend> SortedFriends { get; set; }
public List<Follower> MyFollowers { get; set; }
public List<Follower> SortedFollowers { get; set; }
private bool IsFriendsDescending { get; set; }
private bool IsFollowersDescending { get; set; }
protected override async Task OnInitializedAsync()
{
MyFriends = new List<Friend>()
{
new Friend(){ FirstName = "Jack", LastName = "Sparrow" },
new Friend(){ FirstName = "Davey", LastName = "Jones"},
new Friend(){ FirstName = "Iron", LastName = "Man"}
};
MyFollowers = new List<Follower>()
{
new Follower(){ Username = "user1234" },
new Follower(){ Username = "abc123" },
new Follower(){ Username = "david123"}
};
SortedFriends = MyFriends;
SortedFollowers = MyFollowers;
}
private void SortFriends()
{
if (!IsFriendsDescending)
{
SortedFriends = MyFriends.OrderByDescending(f => f.FirstName).ToList();
IsFriendsDescending = true;
return;
}
SortedFriends = MyFriends.OrderBy(f => f.FirstName).ToList();
IsFriendsDescending = false;
}
private void SortFollowers()
{
if (!IsFollowersDescending)
{
SortedFollowers = MyFollowers.OrderByDescending(f => f.Username).ToList();
IsFollowersDescending = true;
return;
}
SortedFollowers = MyFollowers.OrderBy(f => f.Username).ToList();
IsFollowersDescending = false;
}
}
}
FriendList.razor
<h1>Friends</h1>
@foreach (var friend in Friends)
{
<div>@friend.FirstName @friend.LastName</div>
}
FriendList.cs(后面的代码)
using Microsoft.AspNetCore.Components;
using StateManagementTest.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace StateManagementTest.Components
{
public partial class FriendList
{
[Parameter]
public List<Friend> Friends { get; set; }
}
}
FollowerList.razor
<h1>Followers</h1>
@foreach (var follower in Followers)
{
<div>@follower.Username</div>
}
FollowerList.cs(后面的代码)
using Microsoft.AspNetCore.Components;
using StateManagementTest.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace StateManagementTest.Components
{
public partial class FollowerList
{
[Parameter]
public List<Follower> Followers { get; set; }
protected override Task OnParametersSetAsync()
{
return base.OnParametersSetAsync();
}
}
}
经过更多研究以及我的同事也深入研究了这个问题,我们找到了导致此行为的原因。
我又开始查看组件生命周期link here并突出显示了这段文字:
OnParametersSetAsync or OnParametersSet are called:
- After the component is initialized in OnInitialized or OnInitializedAsync.
- When the parent component re-renders and supplies:
- Only known primitive immutable types of which at least one parameter has changed.
- Any complex-typed parameters. The framework can't know whether the values of a complex-typed parameter have mutated internally, so it treats the parameter set as changed.
所以这将我的问题更改为:是什么导致父组件 re-render?本能地,我开始研究按钮在 Blazor 中的行为方式,并快速阅读 microsoft docs for event handling in Blazor,在每个 UI 事件上调用 StateHasChanged
,无论是 onclick
、onchange
等等等等。因此,当我单击按钮时,它也在调用 StateHasChanged
,这导致组件 re-render 并重新分配后续子项的参数,前提是它们是复杂类型。
我目前正在开发一个使用 Blazor WebAssembly 作为我的前端框架的项目,但是,我在状态管理方面遇到了一些问题,我认为。这个问题出现在一个大型复杂的解决方案中,所以我重新创建并简化了它,这样我就可以在这里简明扼要地描述它,而不会显得臃肿。
我有一个包含两个组件的页面:一个朋友列表和一个关注者列表,每个组件都有一个按钮,用于切换按升序或降序对列表进行排序。
如果我重写,并在 FollowerList 组件内部的 OnParametersSetAsync 上放置一个断点,然后单击 [=] 的排序按钮81=]FriendList 组件它达到了我在 FollowerList 组件上设置的断点。
我的印象是 OnParametersSet/Async 只会在 属性 馈送到该组件的组件发生变化或 它的状态已经改变。 在我下面的代码中,您可以看到我有两个单独的列表,一个被馈送到一个组件,一个被馈送到另一个组件,所以我不确定如何在未触及的组件上触发此方法...
因此我的问题是:为什么它会在不相关的组件上遇到断点?这是故意的行为吗?
页面浏览量
Index page, with the two lists
Index.razor
@page "/"
<button value="Sort Friends" @onclick=SortFriends>Sort Friends</button>
<FriendList Friends=SortedFriends />
<button value="Sort Followers" @onclick=SortFollowers>Sort Followers</button>
<FollowerList Followers=SortedFollowers />
Index.cs(后面的代码)
using StateManagementTest.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace StateManagementTest.Pages
{
public partial class Index
{
public List<Friend> MyFriends { get; set; }
public List<Friend> SortedFriends { get; set; }
public List<Follower> MyFollowers { get; set; }
public List<Follower> SortedFollowers { get; set; }
private bool IsFriendsDescending { get; set; }
private bool IsFollowersDescending { get; set; }
protected override async Task OnInitializedAsync()
{
MyFriends = new List<Friend>()
{
new Friend(){ FirstName = "Jack", LastName = "Sparrow" },
new Friend(){ FirstName = "Davey", LastName = "Jones"},
new Friend(){ FirstName = "Iron", LastName = "Man"}
};
MyFollowers = new List<Follower>()
{
new Follower(){ Username = "user1234" },
new Follower(){ Username = "abc123" },
new Follower(){ Username = "david123"}
};
SortedFriends = MyFriends;
SortedFollowers = MyFollowers;
}
private void SortFriends()
{
if (!IsFriendsDescending)
{
SortedFriends = MyFriends.OrderByDescending(f => f.FirstName).ToList();
IsFriendsDescending = true;
return;
}
SortedFriends = MyFriends.OrderBy(f => f.FirstName).ToList();
IsFriendsDescending = false;
}
private void SortFollowers()
{
if (!IsFollowersDescending)
{
SortedFollowers = MyFollowers.OrderByDescending(f => f.Username).ToList();
IsFollowersDescending = true;
return;
}
SortedFollowers = MyFollowers.OrderBy(f => f.Username).ToList();
IsFollowersDescending = false;
}
}
}
FriendList.razor
<h1>Friends</h1>
@foreach (var friend in Friends)
{
<div>@friend.FirstName @friend.LastName</div>
}
FriendList.cs(后面的代码)
using Microsoft.AspNetCore.Components;
using StateManagementTest.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace StateManagementTest.Components
{
public partial class FriendList
{
[Parameter]
public List<Friend> Friends { get; set; }
}
}
FollowerList.razor
<h1>Followers</h1>
@foreach (var follower in Followers)
{
<div>@follower.Username</div>
}
FollowerList.cs(后面的代码)
using Microsoft.AspNetCore.Components;
using StateManagementTest.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace StateManagementTest.Components
{
public partial class FollowerList
{
[Parameter]
public List<Follower> Followers { get; set; }
protected override Task OnParametersSetAsync()
{
return base.OnParametersSetAsync();
}
}
}
经过更多研究以及我的同事也深入研究了这个问题,我们找到了导致此行为的原因。
我又开始查看组件生命周期link here并突出显示了这段文字:
OnParametersSetAsync or OnParametersSet are called:
- After the component is initialized in OnInitialized or OnInitializedAsync.
- When the parent component re-renders and supplies:
- Only known primitive immutable types of which at least one parameter has changed.
- Any complex-typed parameters. The framework can't know whether the values of a complex-typed parameter have mutated internally, so it treats the parameter set as changed.
所以这将我的问题更改为:是什么导致父组件 re-render?本能地,我开始研究按钮在 Blazor 中的行为方式,并快速阅读 microsoft docs for event handling in Blazor,在每个 UI 事件上调用 StateHasChanged
,无论是 onclick
、onchange
等等等等。因此,当我单击按钮时,它也在调用 StateHasChanged
,这导致组件 re-render 并重新分配后续子项的参数,前提是它们是复杂类型。