🌙 一些实用的工具函数
🌙 1.数组对象按key去重
export function uniqueArrObjByKey<T>(arr: T[], key?: keyof T): T[] {
if (!key) {
return Array.from(new Set(arr));
}
const res: T[] = [];
for (let i = 0; i < arr.length; i++) {
const has = res.some(d => d[key] === arr[i][key]);
if (!has) {
res.push(arr[i]);
}
}
return res;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
🌙 3.计算滚动条尺寸
function getScrollbarSize() {
const scrollDiv = document.createElement("div");
scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;opacity:0';
document.body.appendChild(scrollDiv);
// 垂直滚动条宽度
const x = scrollDiv.offsetWidth - scrollDiv.clientWidth;
// 水平滚动条宽度
const y = scrollDiv.offsetHeight - scrollDiv.clientHeight;
document.body.removeChild(scrollDiv);
return {xWidth: x, yWidth: y};
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
🌙 4.判断容器是否出现滚动条
- 判断body元素:
function hasScrollbar() {
return document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight);
}
1
2
3
2
3
- 判断任意元素:
function hasScrollbar(el: HTMLElement, isVertical = true) {
if (isVertical) {
return el.scrollHeight > el.clientHeight;
} else {
return el.scrollWidth > el.clientWidth;
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
🌙 5.判断各种浏览器版本
// 获取各种浏览器和版本
function getBrowserVersion() {
const userAgent = navigator.userAgent;
let info = '';
let tempArray = [];
//判断是否Opera浏览器
const isOpera = userAgent.indexOf('Opera') > -1;
//判断是否IE浏览器
const isIE = userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1 && !isOpera;
//判断是否IE的Edge浏览器
const isEdge = userAgent.toLowerCase().indexOf('edge') > -1 && !isIE;
const isIE11 = userAgent.toLowerCase().indexOf('trident') > -1 && userAgent.indexOf('rv') > -1;
if (/[Ff]irefox(\/\d+\.\d+)/.test(userAgent)) {
tempArray = /([Ff]irefox)\/(\d+\.\d+)/.exec(userAgent) || [];
info += tempArray[1] + tempArray[2];
} else if (isIE) {
let version: string;
let reIE = new RegExp('MSIE (\\d+\\.\\d+);');
reIE.test(userAgent);
let fIEVersion = parseFloat(RegExp['$1']);
if (fIEVersion === 7) {
version = 'IE7';
} else if (fIEVersion === 8) {
version = 'IE8';
} else if (fIEVersion === 9) {
version = 'IE9';
} else if (fIEVersion === 10) {
version = 'IE10';
} else {
version = '0';
}
info += version;
} else if (isEdge) {
info += 'Edge';
} else if (isIE11) {
info += 'IE11';
} else if (/[Cc]hrome\/\d+/.test(userAgent)) {
tempArray = /([Cc]hrome)\/(\d+)/.exec(userAgent) || [];
info += tempArray[1] || '' + tempArray[2] || '';
} else if (/[Vv]ersion\/\d+\.\d+\.\d+(\.\d)* *[Ss]afari/.test(userAgent)) {
tempArray = /[Vv]ersion\/(\d+\.\d+\.\d+)(\.\d)* *([Ss]afari)/.exec(userAgent) || [];
info += tempArray[3] || '' + tempArray[1] || '';
} else if (/[Oo]pera.+[Vv]ersion\/\d+\.\d+/.test(userAgent)) {
tempArray = /([Oo]pera).+[Vv]ersion\/(\d+)\.\d+/.exec(userAgent) || [];
info += tempArray[1] || '' + tempArray[2] || '';
} else {
info += 'unknown';
}
return info;
}
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
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
🌙 6.判断指定元素是否在视口可见
/**
*@param selector: css元素选择器
*@param partial: 是否部分可见
*/
const isDomVisible = (selector: string, partial = false) => {
const dom = document.querySelector(selector);
const {top, left, bottom, right} = dom.getBoundingClientRect();
const {innerHeight, innerWidth} = window;
return partial ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) && ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth)) : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
};
// Examples
isDomVisible('.img'); // (不完全可见)
isDomVisible('.img', true); // (部分可见)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
🌙 7.延迟调用函数
const delayFn = (fn: Function, wait = 100, ...args) => setTimeout(fn, wait, ...args);
1
🌙 8.睡眠等待函数
const sleep = (wait = 100) => new Promise((resolve) => setTimeout(resolve, wait));
// 使用
async function test() {
await sleep(1000);
console.log(1111);
}
// 延迟1s输出了1111
test();
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
🌙 9.判断浏览器选项卡是否处于前台活跃状态
const isBrowserTabFocused = () => !document.hidden;
// Example
isBrowserTabFocused(); // true
1
2
3
4
2
3
4
🌙 10.格式化日期
要求:对于date = new Date('2020-9-8 14:39:09')
,格式化说明如下:
字符串 | 说明 |
---|---|
yyyy | 年份,2020 |
yy | 年份,20 |
MM | 月份,补满两位,09 |
M | 月份,9 |
dd | 日期,补满两位,08 |
d | 日期,8 |
HH | 24小时制,补满两位,14 |
H | 24小时制,14 |
hh | 12小时制,补满两位,02 |
h | 12小时制,2 |
mm | 分钟,补满两位39 |
m | 分钟,39 |
ss | 秒,补满两位,09 |
s | 秒,9 |
w | 星期,为 ['日', '一', '二', '三', '四', '五', '六'] 中的某一个,本次结果:二 |
/**
*@param date: Date日期
*@param str: 格式化字符串 'YYYY-MM-DD HH:mm:ss 星期w'
*/
function formatDate(date: Date, str = 'YYYY-MM-DD HH:mm:ss 星期w') {
const obj: { [key: string]: string | number } = {
YYYY: date.getFullYear(),
YY: ('' + date.getFullYear()).slice(-2),
M: date.getMonth() + 1,
MM: ('0' + (date.getMonth() + 1)).slice(-2),
D: date.getDate(),
DD: ('0' + date.getDate()).slice(-2),
H: date.getHours(),
HH: ('0' + date.getHours()).slice(-2),
h: date.getHours() % 12,
hh: ('0' + (date.getHours() % 12)).slice(-2),
m: date.getMinutes(),
mm: ('0' + date.getMinutes()).slice(-2),
s: date.getSeconds(),
ss: ('0' + date.getSeconds()).slice(-2),
w: ['日', '一', '二', '三', '四', '五', '六'][date.getDay()],
};
return str.replace(/([a-z]+)/gi, $1 => obj[$1].toString());
}
// "2020-09-08 14:39:09 星期二"
formatDate(new Date('2020-9-8 14:39:09'), 'YYYY-MM-DD HH:mm:ss 星期w')
// "2020-09-08 2:39:09 星期二"
formatDate(new Date('2020-9-8 14:39:09'), 'YYYY-MM-DD h:mm:ss 星期w')
// "09-08 二"
formatDate(new Date('2020-9-8 14:39:09'), 'MM-DD w')
// "2020/09/08 二"
formatDate(new Date('2020/9/8 14:39:09'), 'YYYY/MM/DD w')
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
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