Skip to content

Commit 7c5b136

Browse files
ArgoZhangkhyjb1995
andauthored
refactor(AutoComplete): redesign for improve performance (#4973)
* chore: bump version 9.2.0-beta01 Co-Authored-By: khyjb1995 <[email protected]> * chore: bump version 9.1.4 * refactor: 更新 type 为 text * refactor: 移除拼音处理逻辑 * doc: 增加注释文档 * refactor: 更新配置 * refactor: 重新设计下拉菜单显示逻辑 * refactor: 增加 Desc 标签 * refactor: 重构代码 * refactor: 支持回车按键 * refactor: 重构代码 * test: 更新单元测试 * doc: 更新示例 * refactor: 更改修饰符 * refactor: 更改样式字符串 * refactor: 更改变量名称 * refactor: 移动参数方法到基类中 * refactor: 移动部分参数到组件内 * refactor: 移动 TriggerBlure 到基类 * refactor: 移动 ShowDropdownListOnFocus 到实现类 * refactor: 移除 CurrentItemIndex 逻辑 * refactor: 代码重构 * refactor: 移动点击事件到组件内 * refactor: 移除无用代码 * refactor: 精简代码 * feat: 增加获得滚动行为参数逻辑 * refactor: 完善 blur 逻辑 * refactor: 增加菜单点击事件销毁逻辑 * refactor: 增加上下箭头出发下拉菜单逻辑 * refactor: 精简样式 * doc: 增加 IsPopover 示例 * refactor: 增加全局钩子 * doc: 格式化文档 * refactor: 移动 FilterItems 变量 * refactor: 增加 Esc 逻辑 * refactor: 根据 AutoComplete 重构 AutoFill 组件 * refactor: 移除不使用的方法 * refactor: 重构 AutoFill 组件 * doc: 更新示例文档 * doc: 更新文档说明按键支持 Esc * refactor: 增加关窗逻辑 * refactor: 开窗增加条件判断 * refactor: 更新 Search 组件 * refactor: 增加搜索按钮支持 * feat: 增加搜索按钮逻辑 * doc: 更新示例 * doc: 更新示例 * refactor: 更改泛型约束 * refactor: 代码统一 * test: 更新单元测试 * test: 增加防抖单元测试 * refactor: 移除不使用的属性 --------- Co-authored-by: khyjb1995 <[email protected]>
1 parent 3d6591e commit 7c5b136

24 files changed

+747
-1234
lines changed

src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
<PackageReference Include="BootstrapBlazor.Markdown" Version="9.0.0" />
4747
<PackageReference Include="BootstrapBlazor.MaterialDesign" Version="9.0.0" />
4848
<PackageReference Include="BootstrapBlazor.MaterialDesign.Extensions" Version="9.0.0" />
49-
<PackageReference Include="BootstrapBlazor.MeiliSearch" Version="9.1.3" />
49+
<PackageReference Include="BootstrapBlazor.MeiliSearch" Version="9.1.4" />
5050
<PackageReference Include="BootstrapBlazor.Mermaid" Version="9.0.3" />
5151
<PackageReference Include="BootstrapBlazor.MindMap" Version="9.0.0" />
5252
<PackageReference Include="BootstrapBlazor.MouseFollower" Version="9.0.1" />

src/BootstrapBlazor.Server/Components/Pages/Coms.razor

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
<div class="coms-search">
55
<div class="row">
66
<div class="col-12">
7-
<Search PlaceHolder="@Localizer["Search"]" IsOnInputTrigger="true" IsAutoFocus="true"
8-
Items="@ComponentItems" IsLikeMatch="true" IgnoreCase="true" OnSearch="@OnSearch"></Search>
7+
<Search @bind-Value="@SearchText" PlaceHolder="@Localizer["Search"]" IsOnInputTrigger="true" IsAutoFocus="true" OnSearch="@OnSearch"></Search>
98
</div>
109
</div>
1110
<div class="coms-search-filter">

src/BootstrapBlazor.Server/Components/Pages/Coms.razor.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,17 @@
66
namespace BootstrapBlazor.Server.Components.Pages;
77

88
/// <summary>
9-
///
9+
/// Coms 组件
1010
/// </summary>
1111
public sealed partial class Coms
1212
{
1313
private List<string> ComponentItems { get; } = [];
1414

1515
private string? SearchText { get; set; }
1616

17-
private Task OnSearch(string searchText)
17+
private Task<IEnumerable<string>> OnSearch(string searchText)
1818
{
1919
SearchText = searchText;
20-
21-
StateHasChanged();
22-
return Task.CompletedTask;
20+
return Task.FromResult<IEnumerable<string>>(ComponentItems.Where(i => i.Contains(searchText, StringComparison.OrdinalIgnoreCase)));
2321
}
2422
}

src/BootstrapBlazor.Server/Components/Samples/AutoCompletes.razor

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,35 @@
66
<h4>@Localizer["Description"]</h4>
77

88
<DemoBlock Title="@Localizer["Block1Title"]" Introduction="@Localizer["Block1Intro"]" Name="Normal">
9-
<p>@Localizer["NormalDescription"]</p>
10-
9+
<section ignore>@Localizer["NormalDescription"]</section>
1110
<div style="width: 200px;">
1211
<AutoComplete Items="@StaticItems" IsSelectAllTextOnFocus="true" />
1312
</div>
1413
</DemoBlock>
1514

1615
<DemoBlock Title="@Localizer["Block2Title"]" Introduction="@Localizer["Block2Intro"]" Name="LikeMatch">
17-
<p>@Localizer["LikeMatchDescription"]</p>
18-
16+
<section ignore>@Localizer["LikeMatchDescription"]</section>
1917
<div style="width: 200px;">
2018
<AutoComplete Items="@StaticItems" IsLikeMatch="true" IgnoreCase="false" />
2119
</div>
2220
</DemoBlock>
2321

2422
<DemoBlock Title="@Localizer["Block3Title"]" Introduction="@Localizer["Block3Intro"]" Name="NoDataTip">
25-
<p>@((MarkupString)Localizer["NoDataTipDescription"].Value)</p>
26-
23+
<section ignore>@((MarkupString)Localizer["NoDataTipDescription"].Value)</section>
2724
<div style="width: 200px;">
2825
<AutoComplete Items="@StaticItems" NoDataTip="@Localizer["NoDataTip"]" />
2926
</div>
3027
</DemoBlock>
3128

3229
<DemoBlock Title="@Localizer["Block4Title"]" Introduction="@Localizer["Block4Intro"]" Name="ValueChanged">
33-
<p>@Localizer["ValueChangedDescription"]</p>
34-
30+
<section ignore>@Localizer["ValueChangedDescription"]</section>
3531
<div style="width: 200px;">
3632
<AutoComplete Items="@Items" ValueChanged="@OnValueChanged" />
3733
</div>
3834
</DemoBlock>
3935

4036
<DemoBlock Title="@Localizer["Block5Title"]" Introduction="@Localizer["Block5Intro"]" Name="ShowLabel">
41-
<p>@((MarkupString)Localizer["ShowLabelDescription"].Value)</p>
42-
37+
<section ignore>@((MarkupString)Localizer["ShowLabelDescription"].Value)</section>
4338
<Divider Text="@Localizer["Divider1Text"]" Alignment="Alignment.Left" style="margin: 2rem 0;"></Divider>
4439
<ValidateForm Model="@Model">
4540
<AutoComplete Items="@StaticItems" @bind-Value="@Model.Name" ShowLabel="true" />
@@ -51,15 +46,17 @@
5146
</DemoBlock>
5247

5348
<DemoBlock Title="@Localizer["DebounceTitle"]" Introduction="@Localizer["DebounceIntro"]" Name="Debounce">
54-
<p>@Localizer["DebounceDescription"]</p>
49+
<section ignore>@Localizer["DebounceDescription"]</section>
5550
<div style="width: 200px;">
5651
<AutoComplete Items="@Items" ValueChanged="@OnValueChanged" Debounce="500" />
5752
</div>
5853
</DemoBlock>
5954

6055
<DemoBlock Title="@Localizer["OnSelectedItemChangedTitle"]" Introduction="@Localizer["OnSelectedItemChangedIntro"]" Name="OnSelectedItemChanged">
6156
<AutoComplete Items="@StaticItems" OnSelectedItemChanged="OnSelectedItemChanged" Debounce="500"></AutoComplete>
62-
<ConsoleLogger @ref="Logger" />
57+
<section ignore>
58+
<ConsoleLogger @ref="Logger" />
59+
</section>
6360
</DemoBlock>
6461

6562
<DemoBlock Title="@Localizer["ItemTemplateTitle"]" Introduction="@Localizer["ItemTemplateIntro"]" Name="ItemTemplate">
@@ -98,4 +95,10 @@
9895
<ConsoleLogger @ref="GroupLogger" />
9996
</DemoBlock>
10097

98+
<DemoBlock Title="@Localizer["PopoverTitle"]"
99+
Introduction="@Localizer["PopoverIntro"]"
100+
Name="Popover">
101+
<AutoComplete Items="@StaticItems" IsPopover="true"></AutoComplete>
102+
</DemoBlock>
103+
101104
<AttributeTable Items="@GetAttributes()" />

src/BootstrapBlazor.Server/Components/Samples/AutoCompletes.razor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
namespace BootstrapBlazor.Server.Components.Samples;
77

88
/// <summary>
9-
///
9+
/// AutoComplete 组件示例
1010
/// </summary>
1111
public sealed partial class AutoCompletes
1212
{

src/BootstrapBlazor.Server/Components/Samples/AutoFills.razor

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66
<h4>@Localizer["Description"]</h4>
77

88
<DemoBlock Title="@Localizer["NormalTitle"]" Introduction="@Localizer["NormalIntro"]" Name="Normal">
9-
<div class="mb-3">
9+
<section ignore>
1010
@((MarkupString)@Localizer["NormalDesc"].Value)
11-
</div>
12-
<AutoFill TValue="Foo" Value="Model" Items="Items" IsLikeMatch="true" OnSelectedItemChanged="OnSelectedItemChanged"
13-
OnGetDisplayText="OnGetDisplayText" class="mb-3" IsSelectAllTextOnFocus="true">
11+
</section>
12+
<AutoFill @bind-Value="Model1" Items="Items1" IsLikeMatch="true" OnGetDisplayText="OnGetDisplayText" class="mb-3" IsSelectAllTextOnFocus="true">
1413
<Template>
1514
<div class="d-flex">
1615
<div>
@@ -23,14 +22,16 @@
2322
</div>
2423
</Template>
2524
</AutoFill>
26-
<img src="@WebsiteOption.CurrentValue.GetAvatarUrl(Model.Id)" class="shadow" style="width: 140px; margin-bottom: 1rem; border-radius: 6px;" />
27-
<EditorForm Model="@Model" RowType="RowType.Inline" ItemsPerRow="2" />
25+
<section ignore>
26+
<img src="@WebsiteOption.CurrentValue.GetAvatarUrl(Model1.Id)" class="shadow" style="width: 140px; margin-bottom: 1rem; border-radius: 6px;" />
27+
<EditorForm Model="@Model1" RowType="RowType.Inline" ItemsPerRow="2" />
28+
</section>
2829
</DemoBlock>
2930

3031
<DemoBlock Title="@Localizer["CustomFilterTitle"]" Introduction="@Localizer["CustomFilterIntro"]" Name="CustomFilter">
31-
<div class="mb-3">@((MarkupString)Localizer["CustomFilterDesc"].Value)</div>
32-
<AutoFill TValue="Foo" Value="Model" Items="Items" OnCustomFilter="OnCustomFilter"
33-
OnSelectedItemChanged="OnSelectedItemChanged" OnGetDisplayText="OnGetDisplayText" class="mb-3">
32+
<section ignore>@((MarkupString)Localizer["CustomFilterDesc"].Value)</section>
33+
<AutoFill @bind-Value="Model2" Items="Items2" OnCustomFilter="OnCustomFilter"
34+
OnGetDisplayText="OnGetDisplayText" class="mb-3">
3435
<Template>
3536
<div class="d-flex">
3637
<div>
@@ -43,15 +44,16 @@
4344
</div>
4445
</Template>
4546
</AutoFill>
46-
<EditorForm Model="@Model" RowType="RowType.Inline" ItemsPerRow="2" />
47+
<section ignore>
48+
<EditorForm Model="@Model2" RowType="RowType.Inline" ItemsPerRow="2" />
49+
</section>
4750
</DemoBlock>
4851

4952
<DemoBlock Title="@Localizer["ShowDropdownListOnFocusTitle"]" Introduction="@Localizer["ShowDropdownListOnFocusIntro"]" Name="ShowDropdownListOnFocus">
50-
<div class="mb-3">
53+
<section ignore>
5154
@((MarkupString)@Localizer["ShowDropdownListOnFocusDesc"].Value)
52-
</div>
53-
<AutoFill TValue="Foo" Value="Model" Items="Items" ShowDropdownListOnFocus="false"
54-
OnGetDisplayText="OnGetDisplayText" class="mb-3">
55+
</section>
56+
<AutoFill @bind-Value="Model3" Items="Items3" ShowDropdownListOnFocus="false" OnGetDisplayText="OnGetDisplayText" class="mb-3">
5557
<Template>
5658
<div class="d-flex">
5759
<div>
@@ -64,7 +66,9 @@
6466
</div>
6567
</Template>
6668
</AutoFill>
67-
<EditorForm Model="@Model" RowType="RowType.Inline" ItemsPerRow="2" />
69+
<section ignore>
70+
<EditorForm Model="@Model3" RowType="RowType.Inline" ItemsPerRow="2" />
71+
</section>
6872
</DemoBlock>
6973

7074
<AttributeTable Items="@GetAttributes()" />

src/BootstrapBlazor.Server/Components/Samples/AutoFills.razor.cs

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,23 @@ namespace BootstrapBlazor.Server.Components.Samples;
1111
partial class AutoFills
1212
{
1313
[NotNull]
14-
private Foo Model { get; set; } = new();
14+
private Foo Model1 { get; set; } = new();
1515

16-
private Task OnSelectedItemChanged(Foo foo)
17-
{
18-
Model = Utility.Clone(foo);
19-
StateHasChanged();
20-
return Task.CompletedTask;
21-
}
16+
[NotNull]
17+
private Foo Model2 { get; set; } = new();
18+
[NotNull]
19+
private Foo Model3 { get; set; } = new();
2220

2321
private static string OnGetDisplayText(Foo foo) => foo.Name ?? "";
2422

2523
[NotNull]
26-
private IEnumerable<Foo>? Items { get; set; }
24+
private IEnumerable<Foo>? Items1 { get; set; }
25+
26+
[NotNull]
27+
private IEnumerable<Foo>? Items2 { get; set; }
28+
29+
[NotNull]
30+
private IEnumerable<Foo>? Items3 { get; set; }
2731

2832
[Inject]
2933
[NotNull]
@@ -34,13 +38,19 @@ protected override void OnInitialized()
3438
{
3539
base.OnInitialized();
3640

37-
Items = Foo.GenerateFoo(LocalizerFoo);
38-
Model = Items.First();
41+
Items1 = Foo.GenerateFoo(LocalizerFoo);
42+
Model1 = Items1.First();
43+
44+
Items2 = Foo.GenerateFoo(LocalizerFoo);
45+
Model2 = Items2.First();
46+
47+
Items3 = Foo.GenerateFoo(LocalizerFoo);
48+
Model3 = Items3.First();
3949
}
4050

4151
private Task<IEnumerable<Foo>> OnCustomFilter(string searchText)
4252
{
43-
var items = string.IsNullOrEmpty(searchText) ? Items : Items.Where(i => i.Count > 50 && i.Name!.Contains(searchText));
53+
var items = string.IsNullOrEmpty(searchText) ? Items2 : Items2.Where(i => i.Count > 50 && i.Name!.Contains(searchText));
4454
return Task.FromResult(items);
4555
}
4656

@@ -122,14 +132,14 @@ private AttributeItem[] GetAttributes() =>
122132
ValueList = " — ",
123133
DefaultValue = " — "
124134
},
125-
new()
126-
{
127-
Name = nameof(AutoFill<Foo>.ShowDropdownListOnFocus),
128-
Description = Localizer["Att10"],
129-
Type = "bool",
130-
ValueList = "true/false",
131-
DefaultValue = "true"
132-
},
135+
//new()
136+
//{
137+
// Name = nameof(AutoFill<Foo>.ShowDropdownListOnFocus),
138+
// Description = Localizer["Att10"],
139+
// Type = "bool",
140+
// ValueList = "true/false",
141+
// DefaultValue = "true"
142+
//},
133143
new()
134144
{
135145
Name = "Template",

src/BootstrapBlazor.Server/Components/Samples/Searches.razor

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,9 @@
88
<DemoBlock Title="@Localizer["SearchesNormalTitle"]"
99
Introduction="@Localizer["SearchesNormalIntro"]"
1010
Name="Normal">
11-
<p>@((MarkupString)Localizer["SearchesNormalDescription"].Value)</p>
12-
<Search IgnoreCase="true"
13-
IsLikeMatch="true"
14-
IsAutoFocus="true"
11+
<section ignore>@((MarkupString)Localizer["SearchesNormalDescription"].Value)</section>
12+
<Search IsAutoFocus="true"
1513
PlaceHolder="@Localizer["SearchesPlaceHolder"]"
16-
Items="@Items"
1714
OnSearch="@OnSearch"
1815
IsSelectAllTextOnFocus="true" />
1916
<ConsoleLogger @ref="Logger" />
@@ -22,23 +19,17 @@
2219
<DemoBlock Title="@Localizer["SearchesClearValueTitle"]"
2320
Introduction="@Localizer["SearchesClearValueIntro"]"
2421
Name="ClearValue">
25-
<Search IgnoreCase="true"
26-
IsLikeMatch="true"
27-
IsAutoClearAfterSearch="true"
22+
<Search IsAutoClearAfterSearch="true"
2823
PlaceHolder="@Localizer["SearchesPlaceHolder"]"
29-
Items="@Items"
3024
OnSearch="@OnClearSearch" />
3125
<ConsoleLogger @ref="ClearLogger" />
3226
</DemoBlock>
3327

3428
<DemoBlock Title="@Localizer["SearchesDisplayButtonTitle"]"
3529
Introduction="@Localizer["SearchesDisplayButtonIntro"]"
3630
Name="DisplayButton">
37-
<Search IgnoreCase="true"
38-
IsLikeMatch="true"
39-
PlaceHolder="@Localizer["SearchesPlaceHolder"]"
31+
<Search PlaceHolder="@Localizer["SearchesPlaceHolder"]"
4032
ShowClearButton="true"
41-
Items="@Items"
4233
OnSearch="@OnDisplaySearch"
4334
OnClear="@OnClear"></Search>
4435
<ConsoleLogger @ref="DisplayLogger" />
@@ -47,11 +38,8 @@
4738
<DemoBlock Title="@Localizer["SearchesKeyboardsTitle"]"
4839
Introduction="@Localizer["SearchesKeyboardsIntro"]"
4940
Name="keyboards">
50-
<Search IgnoreCase="true"
51-
IsLikeMatch="true"
52-
PlaceHolder="@Localizer["SearchesPlaceHolder"]"
53-
IsOnInputTrigger="true"
54-
Items="@Items"
41+
<Search PlaceHolder="@Localizer["SearchesPlaceHolder"]"
42+
IsOnInputTrigger="false"
5543
OnSearch="@OnKeyboardSearch" />
5644
<ConsoleLogger @ref="KeyboardLogger" />
5745
</DemoBlock>
@@ -60,7 +48,7 @@
6048
Introduction="@Localizer["SearchesValidateFormIntro"]"
6149
Name="ValidateForm">
6250
<ValidateForm Model="@Model">
63-
<Search Items="StaticItems" IsOnInputTrigger="true" @bind-Value="Model.Name" />
51+
<Search IsOnInputTrigger="true" @bind-Value="Model.Name" />
6452
</ValidateForm>
6553
</DemoBlock>
6654

0 commit comments

Comments
 (0)