-
Notifications
You must be signed in to change notification settings - Fork 0
/
common.ts
310 lines (290 loc) · 8.8 KB
/
common.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
import { hasWindow } from "./brower";
import { strOrNumType, CASE_TYPE, baseType } from "./interface";
/**
* @description 开始位置
* @return {*}
*/
export enum StartPositionEnum {
START = 'START',
END = 'END'
}
/**
* @group 【public】
* @category 修正字符串或数字的长度
* @param {strOrNumType} params 传入的字符串或数字
* @param {number} len 修正后的长度
* @param {string} fillText 修正时填充用的字符
* @param {StartPositionEnum} startPosition 从什么位置开始填充
* @return {strOrNumType} 返回修正后的字符串或数字
*/
export const reviseLength = <T extends strOrNumType>(params: T, len: number, fillText: string = '0', startPosition: StartPositionEnum = StartPositionEnum.END): strOrNumType => {
// 获取传入字符串的长度
let newParams = params + ''
if (newParams.length >= len) {
newParams = newParams.slice(0, len)
} else{
newParams = startPosition === StartPositionEnum.END ? newParams.padEnd(len, fillText) : newParams.padStart(len, fillText)
}
return typeof params === 'number' ? parseInt(newParams) : newParams
}
/**
* @group 【public】
* @category 获取数据类型
* @param {any} data 传入的数据
* @param {CASE_TYPE} caseType 返回的字符串全部小写、或全部大写
* @return {*} 返回数据类型字符串
*/
export const getDataType = (data: any, caseType: CASE_TYPE = CASE_TYPE.LOWER): string => {
const type = Object.prototype.toString.call(data).match(/\s+(\S*)\]/)[1]
return caseType === CASE_TYPE.LOWER ? type.toLowerCase() : caseType === CASE_TYPE.UPPER ? type.toUpperCase() : type
}
/**
* @group 【public】
* @category 判断是否是null
* @param {any} params 传入的数据
* @return {*} 返回是否是null
*/
export const isNull = (params: any): boolean => {
return getDataType(params) === 'null'
}
/**
* @group 【public】
* @category 判断是否是undefined
* @param {any} params 传入的数据
* @return {*} 返回是否是undefined
*/
export const isUndefined = (params: any): boolean => {
return getDataType(params) === 'undefined'
}
/**
* @group 【public】
* @category 判断是否是空(空字符串\null\undefined)
* @param {any} params 传入的数据
* @return {*} 返回是否是空
*/
export const isEmpty = (params): boolean => {
return params === '' || isNull(params) || isUndefined(params)
}
/**
* @group 【public】
* @category 转换基础数据类型
* @param {baseType} params 要转换的数据
* @param {baseType} target 目标数据类型
* @return {*} 转换后的数据
*/
export const transfromDataType = <T extends Exclude<baseType, symbol>>(params: baseType, targetType: T): Exclude<baseType, symbol> => {
const paramsDataType = getDataType(params)
if (paramsDataType === targetType) {
return (params as T)
}
let targetValue: Exclude<baseType, symbol>
switch(targetType) {
case 'number':
targetValue = +(params as T)
break;
case 'string':
targetValue = (params as T) + ''
break;
case 'boolean':
targetValue = !!params
break;
case 'array':
targetValue = [params]
break;
case 'null':
targetValue = null
break;
case 'undefined':
targetValue = void(0)
break;
default:
targetValue = null
break;
}
return targetValue
}
/**
* @group 【public】
* @category 函数节流
* @param {number} delay 延时时间
* @param {boolean | Function} noTrailing
* @param {boolean | Function} callback 回调函数
* @param {boolean | Function} debounceMode 是否立即执行
* @return {Function} 返回的节流函数
*/
export function throttle(delay: number, noTrailing: boolean | Function, callback?: boolean | Function, debounceMode?: boolean | Function): Function {
let timeoutID: any; // 定时器id
let cancelled = false; // 是否已经取消
let lastExec = 0; // 最后一次触发的时间
// 清除定时器
function clearExistingTimeout() {
if (timeoutID) {
clearTimeout(timeoutID);
}
}
// 取消操作
function cancel() {
clearExistingTimeout();
cancelled = true;
}
// 将参数进行更换
if (typeof noTrailing !== 'boolean') {
debounceMode = callback;
callback = noTrailing;
noTrailing = undefined;
}
function wrapper(...arguments_) {
let self = this;
let elapsed = Date.now() - lastExec; // 距离最后一次触发的时间间隔
if (cancelled) {
return;
}
// 触发回调函数
function exec() {
lastExec = Date.now();
if (typeof callback === 'function') {
callback.apply(self, arguments_);
}
}
function clear() {
timeoutID = undefined;
}
// 如果立即触发,则直接先触发一次回调
if (debounceMode && !timeoutID) {
exec();
}
clearExistingTimeout();
// 如果不是立即触发,则等触发间隔大于设置的时间时,进行触发
if (debounceMode === undefined && elapsed > delay) {
exec();
} else if (noTrailing !== true) {
timeoutID = setTimeout(
debounceMode ? clear : exec,
debounceMode === undefined ? delay - elapsed : delay
);
}
}
wrapper.cancel = cancel;
return wrapper;
}
/**
* @group 【public】
* @category 函数防抖
* @param {number} delay 延时时间
* @param {boolean | Function} atBegin 是否立即触发
* @param {Function} callback 回调函数
* @return {Function} 返回防抖函数
*/
export function debounce(delay: number, atBegin: boolean | Function, callback?: Function): Function {
return callback === undefined
? throttle(delay, atBegin, false)
: throttle(delay, callback, atBegin !== false);
}
//复制到剪贴板
function copyByExecCommand(textToCopy: string) {
const inputElement = document.createElement('textarea');
inputElement.value = textToCopy;
inputElement.style.top = '0';
inputElement.style.left = '0';
inputElement.style.position = 'fixed';
document.body.appendChild(inputElement);
inputElement.focus();
inputElement.select();
const successful = (() => {
try {
return document.execCommand('copy');
} catch (e) {
console.error(e);
return false;
}
})();
document.body.removeChild(inputElement);
return successful;
}
/**
* @group 【public】
* @category 复制到剪贴板
* @param {string} textToCopy 要复制的文字
* @return {*}
*/
export const copyToClipboard = async(textToCopy: string) => {
if (!hasWindow()) {
return false
}
if (!navigator.clipboard) {
return copyByExecCommand(textToCopy);
}
try {
await navigator.clipboard.writeText(textToCopy);
return true;
} catch (e) {
console.error(e);
return false;
}
};
/**
* @group 【public】
* @category 获取序列化字符串中的参数,默认返回全部参数的对象格式
* @param {string} params 需要查询的key
* @param {string} searchUrl 字符串,默认为location.search
* @return {string | object} 返回对应key的value,默认返回key、value键值对的对象格式
*/
export const getQueryParams = (params: string, searchUrl?: string): string | object => {
// 如果searchUrl不存在,且window存在,则将location.search设置为默认值
if (isEmpty(searchUrl)) {
if (!hasWindow()) {
return !!params ? '' : {}
} else {
searchUrl = window.location.search
}
}
const startIndex = searchUrl.indexOf('?')
const query = startIndex > 0 ? searchUrl.substring(startIndex) : searchUrl
const queryArr = query.split('&')
if (!!params) {
for (const item of queryArr) {
const paramsArr = item.split('=')
if (paramsArr[0] === params) {
return paramsArr[1]
}
}
return ''
}
const allParams = {}
for (const item of queryArr) {
const paramsArr = item.split('=')
allParams[paramsArr[0]] = paramsArr[1] || ''
}
return allParams
}
/**
* @group 【public】
* @category 对象转为url格式
* @param {object} params 对象格式
* @param {string} firstStr 第一个字符,默认为:?
* @param {string} separator 分隔符,默认为:&
* @param {Function} filterFunction 自定义过滤函数
* @return {string} 返回的url
*/
export const objToUrl = (params: object, firstStr: string = '?', separator: string = '&', filterFunction?: Function): string => {
if (getDataType(params) !== 'object') {
return ''
}
const urlArr = []
// 是否有自定义过滤函数
const hasFilter = getDataType(filterFunction) === 'function'
// 只保留value为string格式的内容
const filterKeys =
hasFilter ?
Object.keys(params).filter(item => filterFunction(item))
:
Object.keys(params).filter(item => typeof params[item] === 'string')
filterKeys.forEach((item) => {
urlArr.push(`${item}=${params[item]}`)
})
const url = urlArr.join(separator)
if (!url) {
return ''
}
return firstStr ? `${firstStr}${url}` : url
}