super-toolkit 1.0.4 → 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.
package/src/data.ts CHANGED
@@ -1,57 +1,182 @@
1
1
  /** 深拷贝 */
2
- export function deepClone<T>(val: T):T {
2
+ export function deepClone<T>(val: T): T {
3
+ if (val === null || typeof val !== 'object') {
4
+ return val;
5
+ }
6
+
7
+ // 处理 Date 类型
8
+ if (val instanceof Date) {
9
+ return new Date(val.getTime()) as T;
10
+ }
11
+
12
+ // 处理 RegExp 类型
13
+ if (val instanceof RegExp) {
14
+ return new RegExp(val.source, val.flags) as T;
15
+ }
16
+
17
+ // 处理 Array 类型
3
18
  if (Array.isArray(val)) {
4
- let arr = [];
5
- for (let i = 0; i < val.length; i++) {
6
- arr[i] = deepClone(val[i])
19
+ var result: any[] = [];
20
+ for (var i = 0; i < val.length; i++) {
21
+ result.push(deepClone(val[i]));
7
22
  }
8
- return arr as T
23
+ return result as T;
9
24
  }
10
- if (typeof val === 'object' && val !== null) {
11
- let obj: Record<string, unknown> = {};
12
- for (let key in val) {
13
- obj[key] = deepClone<unknown>(val[key])
25
+
26
+ // 处理普通对象
27
+ if (typeof val === 'object') {
28
+ var obj: Record<string, any> = {};
29
+ for (var key in val) {
30
+ if (Object.prototype.hasOwnProperty.call(val, key)) {
31
+ obj[key] = deepClone(val[key]);
32
+ }
14
33
  }
15
- return obj as T
34
+ return obj as T;
16
35
  }
17
- return val
36
+
37
+ return val;
18
38
  }
39
+
19
40
  /** 判断是否为空字符串、null、undefined、空对象、空数组 */
20
- export function isEmpty(value: string | number | null | undefined | Array<any> | Record<string, any>) {
41
+ export function isEmpty(value: any): boolean {
21
42
  if (value === '' || value === null || value === undefined) {
22
43
  return true;
23
44
  } else if (typeof value === 'object') {
24
45
  if (Array.isArray(value)) {
25
46
  return value.length === 0;
26
47
  } else {
27
- return Object.keys(value).length === 0;
48
+ // 兼容 IE8 的对象键获取
49
+ var hasKeys = false;
50
+ for (var key in value) {
51
+ if (Object.prototype.hasOwnProperty.call(value, key)) {
52
+ hasKeys = true;
53
+ break;
54
+ }
55
+ }
56
+ return !hasKeys;
28
57
  }
29
58
  }
30
59
  return false;
31
60
  }
61
+
32
62
  /** 数据分组筛选 */
33
- export function group <T extends Array<Record<string,any>> = any[]>(array:T, keys:string[]) {
34
- const data:{
35
- group:string
36
- data:T
37
- }[] = []
38
- array.forEach(item => {
39
- const groups = data.map(t => t.group)
40
- const values = keys.map(t => item[t])
41
- if(values.includes(undefined)) throw Error('传入的keys有误')
42
- if (groups.includes(values.join(','))) {
43
- data.forEach(ct => {
44
- if (ct.group == item.age) {
45
- ct.data.push(item)
46
- }
47
- })
63
+ export function group<T extends Array<Record<string, any>>>(array: T, keys: string[]): { group: string; data: T }[] {
64
+ // 使用对象替代 Map
65
+ var dataMap: Record<string, T> = {};
66
+
67
+ for (var i = 0; i < array.length; i++) {
68
+ var item = array[i];
69
+ var values = [];
70
+ for (var j = 0; j < keys.length; j++) {
71
+ values.push(item[keys[j]]);
72
+ }
73
+
74
+ // 检查是否包含 undefined
75
+ var hasUndefined = false;
76
+ for (var k = 0; k < values.length; k++) {
77
+ if (values[k] === undefined) {
78
+ hasUndefined = true;
79
+ break;
80
+ }
48
81
  }
49
- else {
50
- data.push({
51
- group: values.join(','),
52
- data: [item] as T
53
- })
82
+ if (hasUndefined) {
83
+ throw new Error('传入的keys有误');
84
+ }
85
+
86
+ var groupKey = values.join(',');
87
+ if (dataMap[groupKey]) {
88
+ dataMap[groupKey].push(item);
89
+ } else {
90
+ dataMap[groupKey] = [item] as T;
54
91
  }
55
- })
56
- return data
92
+ }
93
+
94
+ // 转换为数组
95
+ var result = [];
96
+ for (var key in dataMap) {
97
+ if (Object.prototype.hasOwnProperty.call(dataMap, key)) {
98
+ result.push({ group: key, data: dataMap[key] });
99
+ }
100
+ }
101
+ return result;
102
+ }
103
+
104
+ /** 返回参数的数据类型 */
105
+ export function getDataType(data: any): string {
106
+ return Object.prototype.toString.call(data).slice(8, -1);
107
+ }
108
+
109
+ /** 判断两个参数的数据是否一样 */
110
+ export function isSame(sourceData: any, compareData: any): boolean {
111
+ if (arguments.length < 2) {
112
+ throw new Error('Incorrect number of parameters');
113
+ }
114
+
115
+ var sourceType = getDataType(sourceData);
116
+ if (sourceType !== getDataType(compareData)) {
117
+ return false;
118
+ }
119
+
120
+ // 处理基本类型
121
+ if (sourceType !== 'Array' && sourceType !== 'Object') {
122
+ if (sourceType === 'Number' && isNaN(sourceData)) {
123
+ return isNaN(compareData);
124
+ }
125
+ if (sourceType === 'Date' || sourceType === 'RegExp') {
126
+ return sourceData.toString() === compareData.toString();
127
+ }
128
+ return sourceData === compareData;
129
+ }
130
+
131
+ // 处理数组
132
+ if (sourceType === 'Array') {
133
+ if (sourceData.length !== compareData.length) {
134
+ return false;
135
+ }
136
+ for (var i = 0; i < sourceData.length; i++) {
137
+ if (!isSame(sourceData[i], compareData[i])) {
138
+ return false;
139
+ }
140
+ }
141
+ return true;
142
+ }
143
+
144
+ // 处理对象
145
+ if (sourceType === 'Object') {
146
+ // 兼容 IE8 的对象键获取
147
+ var sourceKeys = [];
148
+ for (var key in sourceData) {
149
+ if (Object.prototype.hasOwnProperty.call(sourceData, key)) {
150
+ sourceKeys.push(key);
151
+ }
152
+ }
153
+
154
+ var compareKeys = [];
155
+ for (var key in compareData) {
156
+ if (Object.prototype.hasOwnProperty.call(compareData, key)) {
157
+ compareKeys.push(key);
158
+ }
159
+ }
160
+
161
+ if (sourceKeys.length !== compareKeys.length) {
162
+ return false;
163
+ }
164
+
165
+ for (var i = 0; i < sourceKeys.length; i++) {
166
+ var key = sourceKeys[i];
167
+ var hasKey = false;
168
+ for (var j = 0; j < compareKeys.length; j++) {
169
+ if (compareKeys[j] === key) {
170
+ hasKey = true;
171
+ break;
172
+ }
173
+ }
174
+ if (!hasKey || !isSame(sourceData[key], compareData[key])) {
175
+ return false;
176
+ }
177
+ }
178
+ return true;
179
+ }
180
+
181
+ return true;
57
182
  }
package/src/element.ts CHANGED
@@ -1,7 +1,88 @@
1
+ /** 字符串 trim 方法兼容 IE8 */
2
+ function trim(str: string): string {
3
+ return str.replace(/^\s+|\s+$/g, '');
4
+ }
5
+
1
6
  /** 获取指定元素中的所有内容 */
2
- export function getElementContent(msg: string, el: string) {
3
- let elReg = new RegExp("<" + el + "[\\s\\S]*<\\/" + el + ">");
4
- console.log(elReg);
5
- let newEl = elReg.exec(msg);
6
- return newEl?.length ? newEl[0] : null
7
+ export function getElementContent(msg: string, el: string): string | null {
8
+ // 参数验证
9
+ if (typeof msg !== 'string' || typeof el !== 'string') {
10
+ return null;
11
+ }
12
+
13
+ // 验证元素名称是否合法
14
+ if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(el)) {
15
+ return null;
16
+ }
17
+
18
+ try {
19
+ // 构建正则表达式,使用非贪婪匹配,处理属性和自闭合标签
20
+ var elReg = new RegExp('<' + el + '[^>]*>([\\s\\S]*?)<\\/' + el + '>', 'i');
21
+ var match = elReg.exec(msg);
22
+
23
+ // 返回匹配到的内容,如果没有匹配到则返回 null
24
+ return match ? match[0] : null;
25
+ } catch (error) {
26
+ // 处理可能的错误
27
+ return null;
28
+ }
29
+ }
30
+
31
+ /** 获取指定元素中的文本内容 */
32
+ export function getElementText(msg: string, el: string): string | null {
33
+ // 参数验证
34
+ if (typeof msg !== 'string' || typeof el !== 'string') {
35
+ return null;
36
+ }
37
+
38
+ // 验证元素名称是否合法
39
+ if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(el)) {
40
+ return null;
41
+ }
42
+
43
+ try {
44
+ // 构建正则表达式,使用非贪婪匹配
45
+ var elReg = new RegExp('<' + el + '[^>]*>([\\s\\S]*?)<\\/' + el + '>', 'i');
46
+ var match = elReg.exec(msg);
47
+
48
+ if (match) {
49
+ // 移除可能的标签,只保留文本内容
50
+ return trim(match[1].replace(/<[^>]+>/g, ''));
51
+ }
52
+
53
+ return null;
54
+ } catch (error) {
55
+ // 处理可能的错误
56
+ return null;
57
+ }
58
+ }
59
+
60
+ /** 获取所有指定元素 */
61
+ export function getAllElements(msg: string, el: string): string[] {
62
+ // 参数验证
63
+ if (typeof msg !== 'string' || typeof el !== 'string') {
64
+ return [];
65
+ }
66
+
67
+ // 验证元素名称是否合法
68
+ if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(el)) {
69
+ return [];
70
+ }
71
+
72
+ try {
73
+ // 构建正则表达式,使用非贪婪匹配
74
+ var elReg = new RegExp('<' + el + '[^>]*>([\\s\\S]*?)<\\/' + el + '>', 'gi');
75
+ var matches: string[] = [];
76
+ var match;
77
+
78
+ // 收集所有匹配结果
79
+ while ((match = elReg.exec(msg)) !== null) {
80
+ matches.push(match[0]);
81
+ }
82
+
83
+ return matches;
84
+ } catch (error) {
85
+ // 处理可能的错误
86
+ return [];
87
+ }
7
88
  }
package/src/event.ts CHANGED
@@ -1,32 +1,106 @@
1
- /**防抖方法,其中形参fn为要执行的方法,wait则代表时间间隔,v2使用方法:methods:debounce(()=>{},500),v3使用方法:const methods=debounce(()=>{},500)*/
2
- export function onDebounce(fn: Function, wait: number) {
3
- var timer: any = null;
4
- return function (this: Window) {
5
- var _that = this;
6
- clearTimeout(timer as undefined)
7
- timer = timer as typeof setTimeout;
8
- timer = setTimeout(function () {
9
- fn.apply(_that, arguments) //更改this指向,使this指向它的调用层
10
- }, wait)
11
- }
12
- }
13
-
14
- /**节流方法,其中形参fn为要执行的方法,wait则代表时间间隔,v2使用方法:methods:throttle(()=>{},500),v3使用方法:const methods=throttle(()=>{},500)*/
15
- export function onThrottle(fn: Function, wait: number) {
16
- var timeout: any, startTime = new Date() as any;
17
- return function (this: Window) {
18
- var _that = this;
19
- var curTime = new Date() as any;
20
- clearTimeout(timeout);
21
- // 如果达到了规定的触发时间间隔,触发 handler
22
- if (curTime - startTime >= wait) {
23
- fn.apply(_that, arguments);//更改this指向,使this指向它的调用层
24
- startTime = curTime;
25
- // 没达到触发间隔,重新设定定时器
1
+ /**
2
+ * 防抖方法
3
+ * @param fn 要执行的函数
4
+ * @param wait 时间间隔(毫秒)
5
+ * @param immediate 是否立即执行
6
+ * @returns 防抖处理后的函数
7
+ * @example
8
+ * // v2使用方法:methods:debounce(()=>{},500)
9
+ * // v3使用方法:const methods=debounce(()=>{},500)
10
+ */
11
+ export function debounce(fn: Function, wait: number, immediate: boolean = false) {
12
+ let timer: any = null;
13
+
14
+ const debounced = function(this: any) {
15
+ const context = this;
16
+ const args = arguments;
17
+
18
+ if (timer) {
19
+ clearTimeout(timer);
20
+ }
21
+
22
+ if (immediate) {
23
+ const callNow = !timer;
24
+ timer = setTimeout(() => {
25
+ timer = null;
26
+ }, wait);
27
+
28
+ if (callNow) {
29
+ fn.apply(context, args);
30
+ }
26
31
  } else {
27
- timeout = setTimeout(function () {
28
- fn.apply(_that, arguments);//更改this指向,使this指向它的调用层
32
+ timer = setTimeout(() => {
33
+ fn.apply(context, args);
29
34
  }, wait);
30
35
  }
31
36
  };
37
+
38
+ // 添加取消方法
39
+ debounced.cancel = function() {
40
+ if (timer) {
41
+ clearTimeout(timer);
42
+ timer = null;
43
+ }
44
+ };
45
+
46
+ return debounced;
47
+ }
48
+
49
+ /**
50
+ * 节流方法
51
+ * @param fn 要执行的函数
52
+ * @param wait 时间间隔(毫秒)
53
+ * @param options 配置选项
54
+ * @returns 节流处理后的函数
55
+ * @example
56
+ * // v2使用方法:methods:throttle(()=>{},500)
57
+ * // v3使用方法:const methods=throttle(()=>{},500)
58
+ */
59
+ export function throttle(fn: Function, wait: number, options: any = {}) {
60
+ let timeout: any = null;
61
+ let lastTime = 0;
62
+ const leading = options.leading !== false;
63
+ const trailing = options.trailing !== false;
64
+
65
+ const throttled = function(this: any) {
66
+ const context = this;
67
+ const args = arguments;
68
+ const now = Date.now();
69
+
70
+ // 首次执行时,如果不允许立即执行,则设置 lastTime 为当前时间
71
+ if (!lastTime && !leading) {
72
+ lastTime = now;
73
+ }
74
+
75
+ // 计算剩余时间
76
+ const remaining = wait - (now - lastTime);
77
+
78
+ if (remaining <= 0 || remaining > wait) {
79
+ // 达到时间间隔,执行函数
80
+ if (timeout) {
81
+ clearTimeout(timeout);
82
+ timeout = null;
83
+ }
84
+ lastTime = now;
85
+ fn.apply(context, args);
86
+ } else if (!timeout && trailing) {
87
+ // 未达到时间间隔,设置定时器
88
+ timeout = setTimeout(() => {
89
+ lastTime = leading ? Date.now() : 0;
90
+ timeout = null;
91
+ fn.apply(context, args);
92
+ }, remaining);
93
+ }
94
+ };
95
+
96
+ // 添加取消方法
97
+ throttled.cancel = function() {
98
+ if (timeout) {
99
+ clearTimeout(timeout);
100
+ timeout = null;
101
+ }
102
+ lastTime = 0;
103
+ };
104
+
105
+ return throttled;
32
106
  }