# 1.延时函数,代替setTimeout,同步语法
// 睡眠若干毫秒, 与async/await配合使用
function sleep(ms) {
return new Promise(resolve => {
let timer = null
timer = setTimeout(() => {
resolve()
clearTimeout(timer)
timer = null
}, ms)
})
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 2、ascii16进制转换、hex编码解码
简洁方法,需要支持 TextEncoder
function encodeUtf8(str) {
const encoder = new TextEncoder();
return Array.from(encoder.encode(str))
.map((item) => item.toString(16))
.join("")
.toUpperCase();
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
function decodeUtf8(str) {
const decoder = new TextDecoder();
let bytes = [];
for (let j = 0; j < str.length; j += 2) {
bytes.push(parseInt(str.slice(j, j + 2), 16));
}
return decoder.decode(new Uint8Array(bytes));
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
常规方法
function encodeUtf8(text) {
let res = "";
const code = encodeURIComponent(text);
const bytes = [];
for (let i = 0; i < code.length; i++) {
const c = code.charAt(i);
if (c === "%") {
const hex = code.charAt(i + 1) + code.charAt(i + 2);
const hexVal = parseInt(hex, 16);
bytes.push(hexVal);
i += 2;
} else bytes.push(c.charCodeAt(0));
}
res = bytes
.map((item) => item.toString(16))
.join("")
.toUpperCase();
return res;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function decodeUtf8(str) {
let bytes = [];
for (let j = 0; j < str.length; j += 2) {
bytes.push(parseInt(str.slice(j, j + 2), 16));
}
let encoded = "";
for (let i = 0; i < bytes.length; i++) {
encoded += "%" + bytes[i].toString(16);
}
return decodeURIComponent(encoded);
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 3、表情utf16处理
/**
* 表情utf16
* @param {String} str
* @returns
*/
utf16toEntities(str) {
let patt = /[\ud800-\udbff][\udc00-\udfff]/g; // 检测utf16字符正则
str = str.replace(patt, function(char) {
let H, L, code;
if (char.length === 2) {
H = char.charCodeAt(0); // 取出高位
L = char.charCodeAt(1); // 取出低位
code = (H - 0xD800) * 0x400 + 0x10000 + L - 0xDC00; // 转换算法
return `&#${ code };`;
} else {
return char;
}
});
return str;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 解码utf16
* @param {*} str
* @returns
*/
uncodeUtf16(str) {
console.log('str', str);
const reg = /\&#.*?;/g;
const result = str?.replace(reg, function(char) {
let H, L, code;
if (char.length == 9) {
code = parseInt(char.match(/[0-9]+/g));
H = Math.floor((code - 0x10000) / 0x400) + 0xd800;
L = ((code - 0x10000) % 0x400) + 0xdc00;
return unescape(`%u${ H.toString(16) }%u${ L.toString(16) }`);
} else {
return char;
}
});
return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 4、字符串前置补位
/**
* 前置补任意数字
* @params num
* @params targetLength 目标长度
* @params hexadecimal 是否需要从10转16进制
*/
function padStartNum(num, targetLength, hexadecimal = false, str = '0') {
let _str = ''
if (hexadecimal) {
_str = Number(num).toString(16)
} else {
_str = num.toString()
}
return _str.padStart(targetLength, str)
}
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
# 5、防抖和节流
/**
* 防抖函数就是在一定时间内,再次触发函数就会清除定时器重新设置延迟时间执行,适用于非高频率操作。
* @param {Function} fn [执行函数]
* @param {Number} [interval=1000] [间隔时间]
* @param {Boolean} [immediate=false] [是否立即执行]
* @return {[type]} [function]
*/
function debounce(fn, interval = 1000, immediate = false) {
// 定时器
let timer
return function () {
const self = this
// 保存参数
const args = arguments
if (timer) clearTimeout(timer)
// 是否立即执行
if (immediate) {
fn.apply(self, args)
immediate = false
}
timer = setTimeout(() => {
fn.apply(self, args)
}, interval)
}
}
/**
* 节流函数就是只允许一个函数在一定时间内执行一次,适用于高频率事件。
* @param {Function} fn [执行函数]
* @param {Number} [interval=1000] [间隔时间]
* @return {[type]} [function]
*/
function throttle(fn, interval = 2000) {
let timer
let preTime = +new Date()
return function () {
const self = this
const args = arguments
const curTime = +new Date()
if (timer) clearTimeout(timer)
// 超过间隔时间执行,并记录当前时间是新的时间点
if (curTime - preTime >= interval) {
preTime = curTime
fn.apply(self, arguments)
} else {
// 间隔时间内设置定时器,保证即使停止操作也至少执行一次
timer = setTimeout(() => {
fn.apply(self, args)
}, interval)
}
}
}
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
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
# 6、bit位转换10进制,以及反解析以及设置对应bit位的值
/**
* bit位转换10进制
* @param {Array} list { value: 十进制值, bitStart: bit起始位, bitLen: bit的长度 }
*/
function bitConversion(list) {
return list.reduce((pre, item) => {
const { value, bitStart } = item;
return pre + ((value << bitStart) >>> 0);
}, 0);
}
/**
* 获取对应bit区间的值
* @param {Number} value 十进制数值
* @param {Number} bitStart bit起始位
* @param {Number} bitLen bit的长度
*/
function getBitValue(value, bitStart, bitLen) {
let t = '0b' + "1".repeat(bitLen);
return (value >> bitStart) & t;
}
/**
* 设置对应bit区间的值
* @param {Number} originValue 原始十进制数值
* @param {Number} setValue 设置十进制数值
* @param {Number} bitStart bit起始位
* @param {Number} bitLen bit的长度
*/
function setBitValue(originValue, setValue, {bitStart, bitLen}) {
return (
originValue -
(getBitValue(originValue, bitStart, bitLen) << bitStart) +
(setValue << bitStart)
);
}
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
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
# bitConversion example
// 【bit0、bit1~bit9(1~360)、bit10~bit17(0~100)、bit18~bit25(0~100】
const list = [
{ value: 1, bitStart: 0, bitLen: 1 },
{ value: 267, bitStart: 1, bitLen: 9 },
{ value: 67, bitStart: 10, bitLen: 8 },
{ value: 78, bitStart: 18, bitLen: 8 },
];
console.log(bitConversion(list)) // 20516375
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# getBitValue example
list.forEach((item, index) => {
console.log(getBitValue(bitConversion(list), item.bitStart, item.bitLen));
})
// 1
// 267
// 67
// 78
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# setBitValue example
let _setBitValue = setBitValue(bitConversion(list), 11, list[2]);
list.forEach((item, index) => {
console.log(getBitValue(_setBitValue, item.bitStart, item.bitLen));
});
// 1
// 267
// 11
// 78
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 7、hsv 转 rgb
/**
* hsv 转 rgb
* @param {Object} 颜色模式 H(hues)表示色相,S(saturation)表示饱和度,V)表示明度
*/
hsv2rgb({ h, s, v }) {
let i, f, p1, p2, p3;
let r = 0,
g = 0,
b = 0;
s = s / 100;
v = v / 100;
if (s < 0) s = 0;
if (s > 1) s = 1;
if (v < 0) v = 0;
if (v > 1) v = 1;
h %= 360;
if (h < 0) h += 360;
h /= 60;
i = Math.floor(h);
f = h - i;
p1 = v * (1 - s);
p2 = v * (1 - s * f);
p3 = v * (1 - s * (1 - f));
switch (i) {
case 0:
r = v;
g = p3;
b = p1;
break;
case 1:
r = p2;
g = v;
b = p1;
break;
case 2:
r = p1;
g = v;
b = p3;
break;
case 3:
r = p1;
g = p2;
b = v;
break;
case 4:
r = p3;
g = p1;
b = v;
break;
case 5:
r = v;
g = p1;
b = p2;
break;
}
return {
r: Math.round(r * 255),
g: Math.round(g * 255),
b: Math.round(b * 255)
};
}
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
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
# 8、rgb 转 hsv
// r,g,b范围为[0,255],转换成h范围为[1,360]
// s,v为百分比形式,范围是[0,100],可根据需求做相应调整
rgbToHsv(r, g, b) {
r = (r || 0) / 255;
g = (g || 0) / 255;
b = (b || 0) / 255;
let h, s, v;
let min = Math.min(r, g, b);
let max = (v = Math.max(r, g, b));
let l = (min + max) / 2;
let difference = max - min;
if (max == min) {
h = 0;
} else {
switch (max) {
case r:
h = (g - b) / difference + (g < b ? 6 : 0);
break;
case g:
h = 2.0 + (b - r) / difference;
break;
case b:
h = 4.0 + (r - g) / difference;
break;
}
h = Math.round(h * 60);
}
if (h <= 0) {
h = 1;
}
if (max == 0) {
s = 0;
} else {
s = 1 - min / max;
}
s = Math.round(s * 100);
v = Math.round(v * 100);
if (h >= 360) {
h = 359;
}
return { h, s, v };
}
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
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
# 9、前置补任意数字
/**
* 前置补任意数字
* @params num
* @params targetLength 目标长度
* @params hexadecimal 是否需要从10转16进制
* @params str 补充的字符
*/
padStartNum(num, targetLength, hexadecimal = false, str = "0") {
let _str = "";
if (hexadecimal) {
_str = Number(num).toString(16);
} else {
_str = num.toString();
}
return _str.padStart(targetLength, str);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 10、图片路径拼接
/**
* 图片路径拼接
* @param {string} [path=''] 服务端返回的路径
* @returns
*/
function parsingPath(path = '') {
if (/(http|https):\/\/([\w.]+\/?)\S*/.test(path)) {
return path
}
if (/^data*/.test(path)) {
return path
}
return `${domain}/${path}`
}
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
# 11、获取文件类型
function getFileType(url) {
let type = 'img'
if (!url) {
return type
}
var regex = /\.([0-9a-z]+)(?:[\?#]|$)/i
var matches = url.match(regex)
if (matches) {
type = matches[1]
}
return type
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 12、获取URL参数
/**
* 获取URL参数
*
* @param {*} name
* @returns
*/
function getQueryString(name) {
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')
var r = window.location.search.substr(1).match(reg)
if (r != null) return r[2]
if (r == null) {
return getQueryVariable(name)
}
}
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
# 13、将相对地址转绝地地址
/**
* 将相对地址转绝地地址
* @params { String } 相对地址
* @returns { String } 绝对地址
*/
const getAbsoluteURL = url => {
let link = document.createElement('a')
let absoluteURL = ''
link.href = url
absoluteURL = link.href
link = null
return absoluteURL
}
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
# 14、睡眠若干毫秒
/**
* 睡眠若干毫秒, 与async/await配合使用
* @param {Number} ms 毫秒值
*/
function sleep(ms) {
return new Promise(resolve => {
let timer = setTimeout(() => {
clearTimeout(timer)
resolve()
}, ms)
})
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 15、格式化金钱,千分分隔
/**
* 格式化金钱,千分分隔
* @param {String | Number} num 数值
* @param {String} sign 分割符号
* @param {Number} addDecimal 添加小数位
* @returns { String } 分割完成的字符串
*/
function formateMoneyCut(num, sign = ',', addDecimal = 0) {
if (num) {
if (!addDecimal) {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, sign)
} else {
return num
.toFixed(addDecimal)
.toString()
.replace(/\B(?=(\d{3})+(?!\d))/g, sign)
}
} else {
let zero = 0
return zero.toFixed(addDecimal)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 16、zip文件解析
import JSZip from 'jszip'
import JSZipUtils from 'jszip-utils'
/**
* zip文件解析
* @param {string} zipUrl zip地址
* @returns {file} 文件
*/
function getZipFiles(zipUrl) {
return new Promise((resolve, reject) => {
JSZipUtils.getBinaryContent(zipUrl, async function (err, data) {
let zipData = null
if (err) {
throw err; // or handle err
}
await JSZip.loadAsync(data).then(function (fileData) {
zipData = fileData.files
});
resolve(zipData)
});
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 17、版本号比较
/**
* Compares two software version numbers (e.g. "1.7.1" or "1.2b").
*
* This function was born in http://stackoverflow.com/a/6832721.
*
* @param {string} v1 The first version to be compared.
* @param {string} v2 The second version to be compared.
* @param {object} [options] Optional flags that affect comparison behavior:
* lexicographical: (true/[false]) compares each part of the version strings lexicographically instead of naturally;
* this allows suffixes such as "b" or "dev" but will cause "1.10" to be considered smaller than "1.2".
* zeroExtend: ([true]/false) changes the result if one version string has less parts than the other. In
* this case the shorter string will be padded with "zero" parts instead of being considered smaller.
*
* @returns {number|NaN}
* - 0 if the versions are equal
* - a negative integer iff v1 < v2 负整数
* - a positive integer iff v1 > v2 正整数
* - NaN if either version string is in the wrong format
*/
function versionCompare(v1, v2, options) {
var lexicographical = (options && options.lexicographical) || false,
zeroExtend = (options && options.zeroExtend) || true,
v1parts = (v1 || '0').split('.'),
v2parts = (v2 || '0').split('.');
function isValidPart(x) {
return (lexicographical ? /^\d+[A-Za-zαß]*$/ : /^\d+[A-Za-zαß]?$/).test(x);
}
if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
return NaN;
}
if (zeroExtend) {
while (v1parts.length < v2parts.length) v1parts.push('0');
while (v2parts.length < v1parts.length) v2parts.push('0');
}
if (!lexicographical) {
v1parts = v1parts.map(function (x) {
var match = (/[A-Za-zαß]/).exec(x);
return Number(match ? x.replace(match[0], '.' + x.charCodeAt(match.index)) : x);
});
v2parts = v2parts.map(function (x) {
var match = (/[A-Za-zαß]/).exec(x);
return Number(match ? x.replace(match[0], '.' + x.charCodeAt(match.index)) : x);
});
}
for (var i = 0; i < v1parts.length; ++i) {
if (v2parts.length == i) {
return 1;
}
if (v1parts[i] == v2parts[i]) {
continue;
}
else if (v1parts[i] > v2parts[i]) {
return 1;
}
else {
return -1;
}
}
if (v1parts.length != v2parts.length) {
return -1;
}
return 0;
}
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
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
# 18、常用设备环境判断
export const browser = (() => {
const ua = navigator.userAgent
return {
isAndroid: ua.indexOf('Android') > -1 || ua.indexOf('Adr') > -1, // android终端
isIOS: !!ua.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), // iOS终端
isPC: (() => { // PC终端
const userAgentInfo = ua.toLowerCase()
const Agents = new Array('android', 'iphone', 'symbianOS', 'windows phone', 'ipad', 'ipod')
let flag = true
for (let v = 0; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flag = false
break
}
}
return flag
})(),
isWeChat: /micromessenger/i.test(ua) || typeof WeixinJSBridge !== "undefined", // 微信环境
isSafari: ua.indexOf('Safari') > -1 && ua.indexOf("Chrome") == -1, // safari浏览器
isUC: ua.indexOf('UCBrowser') > -1 // UC浏览器
}
})()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 19、vue指令,图片 onerror 替换默认图片
/**
* 图片初始化默认图片,onerror替换默认图片
* @param {IMG} initImg 初始默认图片
* @param {IMG} errorImg 加载失败显示的图片
*/
Vue.directive('formatImage', function (el, binding) {
const errorImg = (binding.value && binding.value.errorImg) || require('IMG/icon/default_avatar.png') // 加载失败的默认替换图
const initImg = (binding.value && binding.value.initImg) || errorImg // 图片未加载的初始默认图
const imgURL = el.getAttribute('src') // 实际图片地址
el.src = initImg
if (imgURL) {
let image = new Image()
image.src = imgURL
image.onload = () => {
el.src = imgURL
}
}
el.onerror = () => {
el.src = errorImg;
}
}),
<img :src="rankList.list[0].icon" alt="" v-formatImage />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23