super-toolkit 1.0.2 → 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/.babelrc +8 -1
- package/README.md +50 -9
- package/index.d.ts +39 -28
- package/index.ts +68 -31
- package/lib/super-toolkit.min.js +47 -1
- package/package.json +6 -3
- package/src/array.ts +81 -56
- package/src/data.ts +175 -18
- package/src/element.ts +86 -5
- package/src/event.ts +101 -27
- package/src/file.ts +188 -96
- package/src/localStorage.ts +175 -17
- package/src/random.ts +161 -0
- package/src/reg.ts +164 -40
- package/src/time.ts +170 -85
- package/tsconfig.json +15 -8
- package/webpack.config.js +76 -4
- package/test.html +0 -20
package/src/data.ts
CHANGED
|
@@ -1,25 +1,182 @@
|
|
|
1
|
-
export const getRandomSixNum = (size: number) => {
|
|
2
|
-
let RandomSixStr = ''
|
|
3
|
-
for (let i = 0; i < size; i++) {
|
|
4
|
-
RandomSixStr += String(Math.floor(Math.random() * 10))
|
|
5
|
-
}
|
|
6
|
-
return RandomSixStr
|
|
7
|
-
}
|
|
8
1
|
/** 深拷贝 */
|
|
9
|
-
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 类型
|
|
10
18
|
if (Array.isArray(val)) {
|
|
11
|
-
|
|
12
|
-
for (
|
|
13
|
-
|
|
19
|
+
var result: any[] = [];
|
|
20
|
+
for (var i = 0; i < val.length; i++) {
|
|
21
|
+
result.push(deepClone(val[i]));
|
|
22
|
+
}
|
|
23
|
+
return result as T;
|
|
24
|
+
}
|
|
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
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return obj as T;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return val;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** 判断是否为空字符串、null、undefined、空对象、空数组 */
|
|
41
|
+
export function isEmpty(value: any): boolean {
|
|
42
|
+
if (value === '' || value === null || value === undefined) {
|
|
43
|
+
return true;
|
|
44
|
+
} else if (typeof value === 'object') {
|
|
45
|
+
if (Array.isArray(value)) {
|
|
46
|
+
return value.length === 0;
|
|
47
|
+
} else {
|
|
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;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** 数据分组筛选 */
|
|
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
|
+
}
|
|
81
|
+
}
|
|
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;
|
|
14
91
|
}
|
|
15
|
-
return arr as T
|
|
16
92
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
+
}
|
|
21
177
|
}
|
|
22
|
-
return
|
|
178
|
+
return true;
|
|
23
179
|
}
|
|
24
|
-
|
|
180
|
+
|
|
181
|
+
return true;
|
|
25
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
28
|
-
fn.apply(
|
|
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
|
}
|