Skip to content

Commit c279a6c

Browse files
committed
feat: optimize setExpand and extract event target
1 parent 56fe90f commit c279a6c

File tree

4 files changed

+100
-97
lines changed

4 files changed

+100
-97
lines changed

src/constants/events.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { IEventNames } from "../store/tree-store"
1+
import { IEventNames } from "../store/tree-event-target"
2+
23

34
export const TREE_NODE_EVENTS = [
45
'expand',

src/store/tree-event-target.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { TreeNodeKeyType } from '../types'
2+
import TreeNode from './tree-node'
3+
4+
interface IListenersMap {
5+
[eventName: string]: Function[]
6+
}
7+
8+
type NodeGeneralListenerType = (node: TreeNode) => void
9+
10+
export type ListenerType<T extends keyof IEventNames> = IEventNames[T]
11+
12+
export interface IEventNames {
13+
'set-data': () => void
14+
'visible-data-change': () => void
15+
'render-data-change': () => void
16+
expand: NodeGeneralListenerType
17+
select: NodeGeneralListenerType
18+
unselect: NodeGeneralListenerType
19+
'selected-change': (
20+
node: TreeNode | null,
21+
key: TreeNodeKeyType | null
22+
) => void
23+
check: NodeGeneralListenerType
24+
uncheck: NodeGeneralListenerType
25+
'checked-change': (nodes: TreeNode[], keys: TreeNodeKeyType[]) => void
26+
}
27+
28+
export default class TreeEventTarget {
29+
/** 事件 listeners */
30+
private listenersMap: IListenersMap = {}
31+
32+
on<T extends keyof IEventNames>(
33+
eventName: T,
34+
listener: ListenerType<T> | Array<ListenerType<T>>
35+
): void {
36+
if (!this.listenersMap[eventName]) {
37+
this.listenersMap[eventName] = []
38+
}
39+
let listeners: Array<ListenerType<T>> = []
40+
if (!Array.isArray(listener)) {
41+
listeners = [listener]
42+
} else {
43+
listeners = listener
44+
}
45+
listeners.forEach(listener => {
46+
if (this.listenersMap[eventName].indexOf(listener) === -1) {
47+
this.listenersMap[eventName].push(listener)
48+
}
49+
})
50+
}
51+
52+
off<T extends keyof IEventNames>(
53+
eventName: T,
54+
listener?: ListenerType<T>
55+
): void {
56+
if (!this.listenersMap[eventName]) return
57+
if (!listener) {
58+
this.listenersMap[eventName] = []
59+
} else {
60+
const index = this.listenersMap[eventName].indexOf(listener)
61+
if (index > -1) {
62+
this.listenersMap[eventName].splice(index, 1)
63+
}
64+
}
65+
}
66+
67+
emit<T extends keyof IEventNames>(
68+
eventName: T,
69+
...args: Parameters<IEventNames[T]>
70+
): void {
71+
if (!this.listenersMap[eventName]) return
72+
const length: number = this.listenersMap[eventName].length
73+
for (let i: number = 0; i < length; i++) {
74+
this.listenersMap[eventName][i](...args)
75+
}
76+
}
77+
78+
disposeListeners(): void {
79+
for (const eventName in this.listenersMap) {
80+
this.listenersMap[eventName] = []
81+
}
82+
}
83+
}

src/store/tree-store.ts

Lines changed: 14 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import TreeNode, { ITreeNodeOptions } from './tree-node'
22
import { ignoreEnum } from '../constants'
33
import { TreeNodeKeyType, IgnoreType } from '../types'
4+
import TreeEventTarget from './tree-event-target'
45

56
//#region Interfaces
67

@@ -20,39 +21,11 @@ interface IMapData {
2021
[key: number]: TreeNode
2122
}
2223

23-
interface IListenersMap {
24-
[eventName: string]: Function[]
25-
}
26-
27-
export interface IEventNames {
28-
'set-data': () => void
29-
'visible-data-change': () => void
30-
'render-data-change': () => void
31-
expand: NodeGeneralListenerType
32-
select: NodeGeneralListenerType
33-
unselect: NodeGeneralListenerType
34-
'selected-change': (
35-
node: TreeNode | null,
36-
key: TreeNodeKeyType | null
37-
) => void
38-
check: NodeGeneralListenerType
39-
uncheck: NodeGeneralListenerType
40-
'checked-change': (nodes: TreeNode[], keys: TreeNodeKeyType[]) => void
41-
}
42-
4324
//#endregion Interfaces
4425

45-
//#region Types
46-
47-
type NodeGeneralListenerType = (node: TreeNode) => void
48-
49-
export type ListenerType<T extends keyof IEventNames> = IEventNames[T]
50-
5126
export type FilterFunctionType = (keyword: string, node: TreeNode) => boolean
5227

53-
//#endregion Types
54-
55-
export default class TreeStore {
28+
export default class TreeStore extends TreeEventTarget {
5629
//#region Properties
5730

5831
/** 树数据 */
@@ -73,12 +46,11 @@ export default class TreeStore {
7346
/** 当前单选选中节点 key */
7447
private currentSelectedKey: TreeNodeKeyType | null = null
7548

76-
/** 事件 listeners */
77-
private listenersMap: IListenersMap = {}
78-
7949
//#endregion Properties
8050

81-
constructor(private readonly options: ITreeStoreOptions) {}
51+
constructor(private readonly options: ITreeStoreOptions) {
52+
super()
53+
}
8254

8355
/**
8456
* Use this function to insert nodes into flatData to avoid 'maximun call stack size exceeded' error
@@ -481,17 +453,18 @@ export default class TreeStore {
481453
// Set children visibility
482454
let queue = node.children.concat()
483455
while (queue.length) {
484-
if (queue[0].expand && queue[0].children.length) {
485-
queue = queue.concat(queue[0].children)
456+
const nodeFromQueue = queue.pop()
457+
if (!nodeFromQueue) continue
458+
if (nodeFromQueue.expand && nodeFromQueue.children.length) {
459+
queue = nodeFromQueue.children.concat(queue)
486460
}
487-
if (queue[0]._filterVisible === false) {
488-
queue[0].visible = false
461+
if (nodeFromQueue._filterVisible === false) {
462+
nodeFromQueue.visible = false
489463
} else {
490-
queue[0].visible =
491-
queue[0]._parent === null ||
492-
(queue[0]._parent.expand && queue[0]._parent.visible)
464+
nodeFromQueue.visible =
465+
nodeFromQueue._parent === null ||
466+
(nodeFromQueue._parent.expand && nodeFromQueue._parent.visible)
493467
}
494-
queue.shift()
495468
}
496469

497470
if (triggerEvent) {
@@ -1173,58 +1146,4 @@ export default class TreeStore {
11731146
}
11741147

11751148
//#endregion Utils
1176-
1177-
//#region Mini EventTarget
1178-
on<T extends keyof IEventNames>(
1179-
eventName: T,
1180-
listener: ListenerType<T> | Array<ListenerType<T>>
1181-
): void {
1182-
if (!this.listenersMap[eventName]) {
1183-
this.listenersMap[eventName] = []
1184-
}
1185-
let listeners: Array<ListenerType<T>> = []
1186-
if (!Array.isArray(listener)) {
1187-
listeners = [listener]
1188-
} else {
1189-
listeners = listener
1190-
}
1191-
listeners.forEach(listener => {
1192-
if (this.listenersMap[eventName].indexOf(listener) === -1) {
1193-
this.listenersMap[eventName].push(listener)
1194-
}
1195-
})
1196-
}
1197-
1198-
off<T extends keyof IEventNames>(
1199-
eventName: T,
1200-
listener?: ListenerType<T>
1201-
): void {
1202-
if (!this.listenersMap[eventName]) return
1203-
if (!listener) {
1204-
this.listenersMap[eventName] = []
1205-
} else {
1206-
const index = this.listenersMap[eventName].indexOf(listener)
1207-
if (index > -1) {
1208-
this.listenersMap[eventName].splice(index, 1)
1209-
}
1210-
}
1211-
}
1212-
1213-
emit<T extends keyof IEventNames>(
1214-
eventName: T,
1215-
...args: Parameters<IEventNames[T]>
1216-
): void {
1217-
if (!this.listenersMap[eventName]) return
1218-
const length: number = this.listenersMap[eventName].length
1219-
for (let i: number = 0; i < length; i++) {
1220-
this.listenersMap[eventName][i](...args)
1221-
}
1222-
}
1223-
1224-
disposeListeners(): void {
1225-
for (const eventName in this.listenersMap) {
1226-
this.listenersMap[eventName] = []
1227-
}
1228-
}
1229-
//#endregion Mini EventTarget
12301149
}

src/types/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ export type AnyPropsArrayType = Array<{ [key: string]: any }>
2929
export interface INonReactiveData {
3030
store: TreeStore
3131
blockNodes: TreeNode[]
32-
}
32+
}

0 commit comments

Comments
 (0)