@mi-avalon/libs 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,56 @@
1
1
  export declare const noop: () => void;
2
- export declare const getClassName: (key1: string, key2: string) => string;
3
- export declare const getFieldsByPath: (data: any, path: string) => any;
4
- export declare const removeNull: (obj: any) => any;
5
- export declare const debounce: (func: any, wait: number) => (...args: any[]) => void;
6
- export declare const throttle: (func: any, wait: number) => (...args: any[]) => void;
2
+ /**
3
+ * 生成类名 - 优化版本,支持空值处理和多修饰符
4
+ */
5
+ export declare const getClassName: (key1: string, key2?: string) => string;
6
+ /**
7
+ * 根据路径安全获取嵌套对象数据
8
+ * @param data 源对象
9
+ * @param path 路径字符串,支持点号分隔
10
+ * @param defaultValue 默认值,当路径不存在时返回
11
+ * @returns 获取到的值或默认值
12
+ */
13
+ export declare const getFieldsByPath: <T = any>(data: any, path: string, defaultValue?: T) => T;
14
+ /**
15
+ * 清理对象中的空值(null 和 undefined)
16
+ * @param obj 要清理的对象
17
+ * @param includeEmptyString 是否包含空字符串,默认false
18
+ * @param includeZero 是否包含0,默认false
19
+ * @returns 清理后的对象
20
+ */
21
+ export declare const removeNull: <T extends Record<string, any>>(obj: T, includeEmptyString?: boolean, includeZero?: boolean) => Partial<T>;
22
+ /**
23
+ * 防抖函数 - 增强版本,支持取消和立即执行
24
+ * @param func 要防抖的函数
25
+ * @param wait 等待时间(毫秒)
26
+ * @param options 选项配置
27
+ * @returns 防抖后的函数
28
+ */
29
+ export declare const debounce: <T extends (...args: any[]) => any>(func: T, wait: number, options?: {
30
+ leading?: boolean;
31
+ trailing?: boolean;
32
+ maxWait?: number;
33
+ }) => ((...args: Parameters<T>) => void) & {
34
+ cancel: () => void;
35
+ flush: () => void;
36
+ };
37
+ /**
38
+ * 节流函数 - 增强版本,支持选项配置
39
+ * @param func 要节流的函数
40
+ * @param wait 等待时间(毫秒)
41
+ * @param options 选项配置
42
+ * @returns 节流后的函数
43
+ */
44
+ export declare const throttle: <T extends (...args: any[]) => any>(func: T, wait: number, options?: {
45
+ leading?: boolean;
46
+ trailing?: boolean;
47
+ }) => ((...args: Parameters<T>) => void) & {
48
+ cancel: () => void;
49
+ flush: () => void;
50
+ };
51
+ /**
52
+ * 深度克隆对象
53
+ * @param obj 要克隆的对象
54
+ * @returns 克隆后的对象
55
+ */
56
+ export declare const deepClone: <T>(obj: T) => T;
@@ -1,69 +1,268 @@
1
1
  export const noop = () => { };
2
- // 生成类名
2
+ /**
3
+ * 生成类名 - 优化版本,支持空值处理和多修饰符
4
+ */
3
5
  export const getClassName = (key1, key2) => {
4
- const cn = key1;
5
- let str = key1;
6
- if (key2.includes(' ')) {
7
- str = '';
8
- const nArr = key2?.split(' ');
9
- for (const i of nArr) {
10
- str += ` ${cn}-${i}`;
11
- }
12
- }
13
- else if (key2) {
14
- str = `${key1}-${key2}`;
6
+ if (!key1)
7
+ return '';
8
+ const cn = key1.trim();
9
+ if (!key2)
10
+ return cn;
11
+ const modifiers = key2.trim();
12
+ if (!modifiers)
13
+ return cn;
14
+ // 处理多个修饰符
15
+ if (modifiers.includes(' ')) {
16
+ const modifierArray = modifiers.split(/\s+/).filter(Boolean);
17
+ return `${cn} ${modifierArray.map(mod => `${cn}-${mod}`).join(' ')}`;
15
18
  }
16
- return str;
19
+ return `${cn}-${modifiers}`;
17
20
  };
18
- // 根据路径获取数据
19
- export const getFieldsByPath = (data, path) => {
20
- const arr = path?.split('.');
21
- let res = data;
22
- for (const i of arr) {
23
- res = res[i];
21
+ /**
22
+ * 根据路径安全获取嵌套对象数据
23
+ * @param data 源对象
24
+ * @param path 路径字符串,支持点号分隔
25
+ * @param defaultValue 默认值,当路径不存在时返回
26
+ * @returns 获取到的值或默认值
27
+ */
28
+ export const getFieldsByPath = (data, path, defaultValue) => {
29
+ if (!data || !path)
30
+ return defaultValue;
31
+ try {
32
+ const keys = path.split('.');
33
+ let result = data;
34
+ for (const key of keys) {
35
+ if (result === null || result === undefined || !(key in result)) {
36
+ return defaultValue;
37
+ }
38
+ result = result[key];
39
+ }
40
+ return result !== undefined ? result : defaultValue;
41
+ }
42
+ catch {
43
+ return defaultValue;
24
44
  }
25
- return res;
26
45
  };
27
- // 删除空值
28
- export const removeNull = (obj) => {
46
+ /**
47
+ * 清理对象中的空值(null undefined)
48
+ * @param obj 要清理的对象
49
+ * @param includeEmptyString 是否包含空字符串,默认false
50
+ * @param includeZero 是否包含0,默认false
51
+ * @returns 清理后的对象
52
+ */
53
+ export const removeNull = (obj, includeEmptyString = false, includeZero = false) => {
54
+ if (!obj || typeof obj !== 'object')
55
+ return obj;
56
+ const cleaned = {};
29
57
  for (const key in obj) {
30
- if (obj[key] === null) {
31
- delete obj[key];
58
+ if (obj.hasOwnProperty(key)) {
59
+ const value = obj[key];
60
+ // 检查是否应该跳过该值
61
+ const shouldSkip = value === null ||
62
+ value === undefined ||
63
+ (includeEmptyString && value === '') ||
64
+ (includeZero && value === 0);
65
+ if (!shouldSkip) {
66
+ cleaned[key] = value;
67
+ }
32
68
  }
33
69
  }
34
- return obj;
70
+ return cleaned;
35
71
  };
36
- // 防抖函数
37
- export const debounce = (func, wait) => {
72
+ /**
73
+ * 防抖函数 - 增强版本,支持取消和立即执行
74
+ * @param func 要防抖的函数
75
+ * @param wait 等待时间(毫秒)
76
+ * @param options 选项配置
77
+ * @returns 防抖后的函数
78
+ */
79
+ export const debounce = (func, wait, options = {}) => {
38
80
  let timeout = null;
39
- return (...args) => {
81
+ let lastArgs = null;
82
+ let lastCallTime = 0;
83
+ let lastInvokeTime = 0;
84
+ let maxTimeout = null;
85
+ const { leading = false, trailing = true, maxWait } = options;
86
+ const invokeFunc = (time) => {
87
+ const args = lastArgs;
88
+ lastArgs = null;
89
+ lastInvokeTime = time;
90
+ if (args) {
91
+ func(...args);
92
+ }
93
+ };
94
+ const shouldInvoke = (time) => {
95
+ const timeSinceLastCall = time - lastCallTime;
96
+ const timeSinceLastInvoke = time - lastInvokeTime;
97
+ return lastCallTime === 0 ||
98
+ timeSinceLastCall >= wait ||
99
+ timeSinceLastInvoke < 0 ||
100
+ (maxWait && timeSinceLastInvoke >= maxWait);
101
+ };
102
+ const startTimer = (pendingFunc, waitMs) => {
103
+ return setTimeout(pendingFunc, waitMs);
104
+ };
105
+ const cancelTimer = (timer) => {
106
+ if (timer) {
107
+ clearTimeout(timer);
108
+ }
109
+ };
110
+ const debounced = (...args) => {
111
+ const now = Date.now();
112
+ const shouldInvokeNow = shouldInvoke(now);
113
+ lastArgs = args;
114
+ lastCallTime = now;
115
+ if (shouldInvokeNow) {
116
+ if (timeout) {
117
+ cancelTimer(timeout);
118
+ timeout = null;
119
+ }
120
+ if (leading && lastInvokeTime === 0) {
121
+ lastInvokeTime = now;
122
+ func(...args);
123
+ return;
124
+ }
125
+ if (maxWait) {
126
+ cancelTimer(maxTimeout);
127
+ maxTimeout = startTimer(() => {
128
+ if (trailing && lastArgs) {
129
+ invokeFunc(Date.now());
130
+ }
131
+ maxTimeout = null;
132
+ }, maxWait);
133
+ }
134
+ }
135
+ if (!timeout && trailing) {
136
+ timeout = startTimer(() => {
137
+ timeout = null;
138
+ if (trailing && lastArgs) {
139
+ invokeFunc(Date.now());
140
+ }
141
+ }, wait);
142
+ }
143
+ };
144
+ debounced.cancel = () => {
40
145
  if (timeout) {
41
- clearTimeout(timeout);
146
+ cancelTimer(timeout);
147
+ timeout = null;
42
148
  }
43
- timeout = setTimeout(() => {
44
- func(...args);
45
- }, wait);
149
+ if (maxTimeout) {
150
+ cancelTimer(maxTimeout);
151
+ maxTimeout = null;
152
+ }
153
+ lastArgs = null;
154
+ lastCallTime = 0;
155
+ lastInvokeTime = 0;
46
156
  };
157
+ debounced.flush = () => {
158
+ if (timeout) {
159
+ cancelTimer(timeout);
160
+ timeout = null;
161
+ }
162
+ if (lastArgs) {
163
+ invokeFunc(Date.now());
164
+ }
165
+ };
166
+ return debounced;
47
167
  };
48
- // 节流函数
49
- export const throttle = (func, wait) => {
168
+ /**
169
+ * 节流函数 - 增强版本,支持选项配置
170
+ * @param func 要节流的函数
171
+ * @param wait 等待时间(毫秒)
172
+ * @param options 选项配置
173
+ * @returns 节流后的函数
174
+ */
175
+ export const throttle = (func, wait, options = {}) => {
50
176
  let timeout = null;
51
- let lastTime = 0;
52
- return (...args) => {
53
- const nowTime = Date.now();
54
- if (!timeout) {
177
+ let lastArgs = null;
178
+ let lastCallTime = 0;
179
+ let lastInvokeTime = 0;
180
+ const { leading = true, trailing = true } = options;
181
+ const invokeFunc = (time) => {
182
+ const args = lastArgs;
183
+ lastArgs = null;
184
+ lastInvokeTime = time;
185
+ if (args) {
55
186
  func(...args);
56
- lastTime = nowTime;
57
- timeout = setTimeout(() => {
187
+ }
188
+ };
189
+ const shouldInvoke = (time) => {
190
+ const timeSinceLastCall = time - lastCallTime;
191
+ const timeSinceLastInvoke = time - lastInvokeTime;
192
+ return lastCallTime === 0 ||
193
+ timeSinceLastCall >= wait ||
194
+ timeSinceLastInvoke < 0;
195
+ };
196
+ const startTimer = (pendingFunc, waitMs) => {
197
+ return setTimeout(pendingFunc, waitMs);
198
+ };
199
+ const throttled = (...args) => {
200
+ const now = Date.now();
201
+ const shouldInvokeNow = shouldInvoke(now);
202
+ lastArgs = args;
203
+ lastCallTime = now;
204
+ if (shouldInvokeNow) {
205
+ if (timeout) {
206
+ clearTimeout(timeout);
207
+ timeout = null;
208
+ }
209
+ if (leading && lastInvokeTime === 0) {
210
+ invokeFunc(now);
211
+ return;
212
+ }
213
+ }
214
+ if (!timeout && trailing) {
215
+ timeout = startTimer(() => {
58
216
  timeout = null;
217
+ if (trailing && lastArgs) {
218
+ invokeFunc(Date.now());
219
+ }
59
220
  }, wait);
60
221
  }
61
- else {
62
- const diffTime = nowTime - lastTime;
63
- if (diffTime >= wait) {
64
- func(...args);
65
- lastTime = nowTime;
66
- }
222
+ };
223
+ throttled.cancel = () => {
224
+ if (timeout) {
225
+ clearTimeout(timeout);
226
+ timeout = null;
67
227
  }
228
+ lastArgs = null;
229
+ lastCallTime = 0;
230
+ lastInvokeTime = 0;
68
231
  };
232
+ throttled.flush = () => {
233
+ if (timeout) {
234
+ clearTimeout(timeout);
235
+ timeout = null;
236
+ }
237
+ if (lastArgs) {
238
+ invokeFunc(Date.now());
239
+ }
240
+ };
241
+ return throttled;
242
+ };
243
+ /**
244
+ * 深度克隆对象
245
+ * @param obj 要克隆的对象
246
+ * @returns 克隆后的对象
247
+ */
248
+ export const deepClone = (obj) => {
249
+ if (obj === null || typeof obj !== 'object') {
250
+ return obj;
251
+ }
252
+ if (obj instanceof Date) {
253
+ return new Date(obj.getTime());
254
+ }
255
+ if (obj instanceof Array) {
256
+ return obj.map(item => deepClone(item));
257
+ }
258
+ if (typeof obj === 'object') {
259
+ const clonedObj = {};
260
+ for (const key in obj) {
261
+ if (obj.hasOwnProperty(key)) {
262
+ clonedObj[key] = deepClone(obj[key]);
263
+ }
264
+ }
265
+ return clonedObj;
266
+ }
267
+ return obj;
69
268
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mi-avalon/libs",
3
3
  "private": false,
4
- "version": "1.0.3",
4
+ "version": "1.0.5",
5
5
  "type": "module",
6
6
  "main": "./dist/index.umd.js",
7
7
  "module": "./dist/index.es.js",
@@ -37,4 +37,4 @@
37
37
  "@ant-design/icons": ">=6.0.0"
38
38
  },
39
39
  "dependencies": {}
40
- }
40
+ }