Skip to content

Commit 333dd4d

Browse files
authored
refactor(TreeView): improve TreeView script (#4728)
* refactor: 精简代码移除不使用的参数 * refactor: 精简 scroll 代码提高性能 * refactor: 更新 GetParentsState 方法 * refactor: 重构 toggleLoading 方法 * refactor: 精简 setChildrenState 方法 * refactor: 精简 dispose 方法 * refactor: 移除 Data 方法 * test: 更新单元测试
1 parent 227fa5e commit 333dd4d

File tree

3 files changed

+69
-104
lines changed

3 files changed

+69
-104
lines changed

src/BootstrapBlazor/Components/TreeView/TreeView.razor.cs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -391,15 +391,15 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
391391
if (_keyboardArrowUpDownTrigger)
392392
{
393393
_keyboardArrowUpDownTrigger = false;
394-
await InvokeVoidAsync("scroll", Id, ScrollIntoViewOptions ?? new() { Behavior = ScrollIntoViewBehavior.Smooth, Block = ScrollIntoViewBlock.Center, Inline = ScrollIntoViewInline.Nearest });
394+
await InvokeVoidAsync("scroll", Id, ScrollIntoViewOptions);
395395
}
396396
}
397397

398398
/// <summary>
399399
/// <inheritdoc/>
400400
/// </summary>
401401
/// <returns></returns>
402-
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, new { Invoke = Interop, Method = nameof(TriggerKeyDown), IsVirtualize, AutoCheckParent, AutoCheckChildren });
402+
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, new { Invoke = Interop, Method = nameof(TriggerKeyDown) });
403403

404404
private bool _keyboardArrowUpDownTrigger;
405405

@@ -431,17 +431,11 @@ public async ValueTask TriggerKeyDown(string key)
431431
/// 客户端查询指定行选择框状态方法 由 JavaScript 调用
432432
/// </summary>
433433
/// <param name="items"></param>
434-
/// <param name="index"></param>
435-
/// <param name="state"></param>
436434
/// <returns></returns>
437435
[JSInvokable]
438-
public ValueTask<List<CheckboxState>> GetParentsState(List<int> items, int index, CheckboxState? state)
436+
public ValueTask<List<CheckboxState>> GetParentsState(List<int> items)
439437
{
440438
var rows = Rows;
441-
if (state.HasValue)
442-
{
443-
rows[index].CheckedState = state.Value;
444-
}
445439
var result = items.Select(i =>
446440
{
447441
var item = rows[i];
@@ -719,16 +713,16 @@ private async Task OnCheckStateChanged(TreeViewItem<TItem> item, CheckboxState s
719713
// 向下级联操作
720714
if (item.CheckedState != CheckboxState.Indeterminate)
721715
{
722-
_ = InvokeVoidAsync("setChildrenState", Id, Rows.IndexOf(item), item.CheckedState);
723716
item.SetChildrenCheck(TreeNodeStateCache);
717+
_ = InvokeVoidAsync("setChildrenState", Id, Rows.IndexOf(item), item.CheckedState);
724718
}
725719
}
726720

727721
if (AutoCheckParent)
728722
{
729723
// 向上级联操作
730724
item.SetParentCheck(TreeNodeStateCache);
731-
_ = InvokeVoidAsync("setParentState", Id, Rows.IndexOf(item));
725+
_ = InvokeVoidAsync("setParentState", Id, Interop, nameof(GetParentsState), Rows.IndexOf(item));
732726
}
733727

734728
if (OnTreeItemChecked != null)
Lines changed: 61 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
1-
import Data from "../../modules/data.js"
2-
import EventHandler from "../../modules/event-handler.js"
1+
import EventHandler from "../../modules/event-handler.js"
32

43
export function init(id, options) {
5-
const { invoke, method, isVirtualize } = options
64
const el = document.getElementById(id)
75
if (el === null) {
86
return
97
}
108

11-
const tree = { el, invoke, isVirtualize };
12-
Data.set(id, tree)
13-
9+
const { invoke, method } = options
1410
EventHandler.on(el, 'keydown', '.tree-root', e => {
1511
if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
1612
const v = el.getAttribute('data-bb-keyboard');
@@ -33,103 +29,89 @@ export function init(id, options) {
3329
}
3430

3531
export function scroll(id, options) {
36-
const tree = Data.get(id)
37-
if (tree) {
38-
const { el } = tree;
39-
const item = el.querySelector(".active .tree-node");
40-
if (item) {
41-
item.scrollIntoView(options);
42-
}
32+
const el = document.getElementById(id);
33+
const item = el.querySelector(".active .tree-node");
34+
if (item) {
35+
item.scrollIntoView(options ?? { behavior: 'smooth', block: 'start', inline: 'nearest' });
4336
}
4437
}
4538

4639
export function toggleLoading(id, index, state) {
47-
const tree = Data.get(id)
48-
if (tree) {
49-
const { el } = tree;
50-
const node = el.querySelector(`[data-bb-tree-view-index="${index}"]`);
51-
if (node) {
52-
if (state) {
53-
node.classList.add('loading');
54-
}
55-
else {
56-
node.classList.remove('loading');
57-
}
40+
const el = document.getElementById(id);
41+
const node = el.querySelector(`[data-bb-tree-view-index="${index}"]`);
42+
if (node) {
43+
if (state) {
44+
node.classList.add('loading');
45+
}
46+
else {
47+
node.classList.remove('loading');
5848
}
5949
}
6050
}
6151

6252
export function setChildrenState(id, index, state) {
63-
const tree = Data.get(id)
64-
if (tree) {
65-
const { el } = tree;
66-
const node = el.querySelector(`[data-bb-tree-view-index="${index}"]`);
67-
const level = parseInt(node.style.getPropertyValue('--bb-tree-view-level'));
68-
if (node) {
69-
let next = node.nextElementSibling;
70-
while (next) {
71-
const currentLevel = parseInt(next.style.getPropertyValue('--bb-tree-view-level'));
72-
if (currentLevel <= level) {
73-
break;
74-
}
75-
const checkbox = next.querySelector('.form-check-input');
76-
if (checkbox) {
77-
checkbox.indeterminate = false;
78-
checkbox.checked = state === 1;
79-
EventHandler.trigger(checkbox, "statechange.bb.checkbox", { state });
80-
}
81-
next = next.nextElementSibling;
53+
const el = document.getElementById(id);
54+
const node = el.querySelector(`[data-bb-tree-view-index="${index}"]`);
55+
const level = parseInt(node.style.getPropertyValue('--bb-tree-view-level'));
56+
if (node) {
57+
let next = node.nextElementSibling;
58+
while (next) {
59+
const currentLevel = parseInt(next.style.getPropertyValue('--bb-tree-view-level'));
60+
if (currentLevel <= level) {
61+
break;
62+
}
63+
const checkbox = next.querySelector('.form-check-input');
64+
if (checkbox) {
65+
checkbox.indeterminate = false;
66+
checkbox.checked = state === 1;
67+
EventHandler.trigger(checkbox, "statechange.bb.checkbox", { state });
8268
}
69+
next = next.nextElementSibling;
8370
}
8471
}
8572
}
8673

87-
export async function setParentState(id, index, state) {
88-
const tree = Data.get(id)
89-
if (tree) {
90-
const { el, invoke } = tree;
91-
const node = el.querySelector(`[data-bb-tree-view-index="${index}"]`);
92-
let level = parseInt(node.style.getPropertyValue('--bb-tree-view-level'));
93-
if (node) {
94-
const parents = [];
95-
let prev = node.previousElementSibling;
96-
while (prev) {
97-
const currentLevel = parseInt(prev.style.getPropertyValue('--bb-tree-view-level'));
98-
if (currentLevel < level) {
99-
level = currentLevel;
100-
parents.push(prev);
101-
}
102-
prev = prev.previousElementSibling;
74+
export async function setParentState(id, invoke, method, index) {
75+
const el = document.getElementById(id);
76+
const node = el.querySelector(`[data-bb-tree-view-index="${index}"]`);
77+
let level = parseInt(node.style.getPropertyValue('--bb-tree-view-level'));
78+
if (node) {
79+
const parents = [];
80+
let prev = node.previousElementSibling;
81+
while (prev) {
82+
const currentLevel = parseInt(prev.style.getPropertyValue('--bb-tree-view-level'));
83+
if (currentLevel < level) {
84+
level = currentLevel;
85+
parents.push(prev);
10386
}
87+
prev = prev.previousElementSibling;
88+
}
10489

105-
if (parents.length > 0) {
106-
const results = await invoke.invokeMethodAsync('GetParentsState', parents.map(p => parseInt(p.getAttribute('data-bb-tree-view-index'))), index, state);
107-
for (let index = 0; index < parents.length; index++) {
108-
const checkbox = parents[index].querySelector('.form-check-input');
109-
const result = results[index];
110-
checkbox.indeterminate = false;
111-
if (result === 0) {
112-
checkbox.checked = false;
113-
}
114-
else if (result === 1) {
115-
checkbox.checked = true;
116-
}
117-
else {
118-
checkbox.indeterminate = true;
119-
}
120-
EventHandler.trigger(checkbox, "statechange.bb.checkbox", { state: result });
90+
if (parents.length > 0) {
91+
const results = await invoke.invokeMethodAsync(method, parents.map(p => parseInt(p.getAttribute('data-bb-tree-view-index'))));
92+
for (let index = 0; index < parents.length; index++) {
93+
const checkbox = parents[index].querySelector('.form-check-input');
94+
const result = results[index];
95+
checkbox.indeterminate = false;
96+
if (result === 0) {
97+
checkbox.checked = false;
98+
}
99+
else if (result === 1) {
100+
checkbox.checked = true;
101+
}
102+
else {
103+
checkbox.indeterminate = true;
121104
}
105+
EventHandler.trigger(checkbox, "statechange.bb.checkbox", { state: result });
122106
}
123107
}
124108
}
125109
}
126110

127111
export function dispose(id) {
128-
const tree = Data.get(id)
129-
Data.remove(id);
112+
const el = document.getElementById(id);
130113

131-
if (tree) {
132-
const { el } = tree;
114+
if (el) {
133115
EventHandler.off(el, 'keyup', '.tree-root');
134116
}
135117
}

test/UnitTest/Components/TreeViewTest.cs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,6 @@ public async Task GetParentsState_Ok()
507507
Assert.Equal(CheckboxState.Checked, checkboxes[1].Instance.State);
508508

509509
await cut.InvokeAsync(() => cut.Find(".fa-caret-right.visible").Click());
510-
511510
cut.WaitForState(() => cut.Instance.Items[0].Items.Count > 0);
512511
// 101 unchecked
513512
// -> 101-101 unchecked
@@ -516,21 +515,11 @@ public async Task GetParentsState_Ok()
516515

517516
checkboxes = cut.FindComponents<Checkbox<TreeViewItem<TreeFoo>>>();
518517
var parents = new List<int>() { 0 };
519-
List<CheckboxState> results = await cut.Instance.GetParentsState(parents, 1, CheckboxState.Checked);
520-
Assert.NotNull(results);
521-
Assert.Equal(CheckboxState.Checked, checkboxes[1].Instance.Value.CheckedState);
522-
Assert.Equal(CheckboxState.Checked, checkboxes[0].Instance.Value.CheckedState);
523-
524-
Assert.Single(results);
525-
Assert.Equal(CheckboxState.Checked, results[0]);
526-
527-
// 更改第二个子节点状态
528-
checkboxes = cut.FindComponents<Checkbox<TreeViewItem<TreeFoo>>>();
529-
results = await cut.Instance.GetParentsState(parents, 2, CheckboxState.UnChecked);
518+
List<CheckboxState> results = await cut.Instance.GetParentsState(parents);
530519
Assert.NotNull(results);
531520
Assert.Equal(CheckboxState.Indeterminate, checkboxes[0].Instance.Value.CheckedState);
532-
Assert.Equal(CheckboxState.Checked, checkboxes[1].Instance.Value.CheckedState);
533-
Assert.Equal(CheckboxState.UnChecked, checkboxes[2].Instance.Value.CheckedState);
521+
Assert.Equal(CheckboxState.UnChecked, checkboxes[1].Instance.Value.CheckedState);
522+
Assert.Equal(CheckboxState.Checked, checkboxes[2].Instance.Value.CheckedState);
534523

535524
Assert.Single(results);
536525
Assert.Equal(CheckboxState.Indeterminate, results[0]);

0 commit comments

Comments
 (0)