工具函数
随机生成十六进制颜色
const getRandomColor = () => {
return `#` + [0, 0, 0].map(() => (~~(Math.random() * 0x100)).toString(16).replace(/^(\d)$/, `0$1`)).join(``);
};
getRandomColor();
获取指定范围内的随机整数
getRandom(n, m) {
return Math.floor(Math.random() * (m - n + 1) + n)
}
getRandom(1, 100)
getRandom(0, 5)
根据数组中的元素的唯一属性,筛选出相应的属性值
const ids = [1, 3];
const data = [
{ id: 1, title: 'z' },
{ id: 2, title: 'g' },
{ id: 3, title: 'h' }
];
const idSet = new Set(ids);
const res = data.filter(item => idSet.has(item.id)).map(item => item.title);
console.log(res); // ['z', 'h']
不推荐的写法:
let res = [];
ids.forEach(id => {
data.forEach(item => {
if (id === item.id) {
res.push(item.title);
}
});
});
根据 id 替换或删除数组项
const values = { id: 2, name: '222' };
const arr = [
{ id: 1, name: '11' },
{ id: 2, name: '22' },
{ id: 3, name: '33' }
];
- 如果 values.id 和 arr 中的某一项的 id 相同,就用 values 替换这一项
const updatedArr = arr.map(item => {
if (item.id === values.id) {
return values;
}
return item;
});
- 如果 values.id 和 arr 中的某一项的 id 相同,就删除这一项
const updatedArr = arr.filter(item => item.uuid !== values.uuid);
根据键名将对象转换为数组
有一个对象 { a1: 1, b1: 2, a2: 3, b2: 4 }
,想根据键名中的数字如果相同就放到一个新对象里,最后得到一个数组,期望结果如下:[{ a: 1, b: 2 }, { a: 3, b: 4 }]
const obj = { a1: 1, b1: 2, a2: 3, b2: 4 };
const res = Object.values(
Object.entries(obj).reduce(
(acc, [key, val]) => (Object.assign((acc[[key.match(/\d/)]] ||= {}), { [key.replace(/\d/, '')]: val }), acc),
{}
)
);
console.log(JSON.stringify(res));
||=
表示或等于,a ||= b
等同于 a || (a = b)
&&=
表示且等于,a &&= b
等同于 a && (a = b)
数组拆分
// array 需要拆分的数组,size 每组数组多少个
function arrayChunk(array, size) {
let data = [];
for (let i = 0; i < array.length; i += size) {
data.push(array.slice(i, i + size));
}
return data;
}
const arr = [1, 2, 3, 4];
arrayChunk(arr, 2); // [[1, 2], [3, 4]]
找到数组中连续 n 个元素
从数组中查找元素,获取包括元素在内的 9 个元素
function getNineElements(arr, targetId) {
const targetIndex = arr.findIndex(item => item.id === targetId);
if (targetIndex !== -1) {
// 如果找到目标元素
if (targetIndex >= 8) {
// 如果目标元素前面有8个元素
return arr.slice(targetIndex - 8, targetIndex + 1);
} else {
// 如果目标元素前面不足8个元素,从该元素后面取若干元素,总共9个元素
return arr.slice(0, 9);
}
}
return [];
}
处理数组以生成特定的 ECharts 数据结构
const data = [
{ name: '收入', year: 2018, value: 99535.4681 },
{ name: '支出', year: 2018, value: 78761.4833 },
{ name: '收入', year: 2019, value: 43018.8192 },
{ name: '支出', year: 2019, value: 36920.0656 },
{ name: '收入', year: 2020, value: 78180.2619 },
{ name: '支出', year: 2020, value: 31246.8656 },
{ name: '收入', year: 2021, value: 60299.8414 },
{ name: '支出', year: 2021, value: 51657.13 },
{ name: '收入', year: 2022, value: 811298.0807 },
{ name: '支出', year: 2022, value: 8556.9949 },
{ name: '收入', year: 2023, value: 62680.3691 },
{ name: '支出', year: 2023, value: 36.82 },
{ name: '收入', year: 2024, value: 24753.8608 },
{ name: '支出', year: 2024, value: 50 },
{ name: '收入', year: 2025, value: 80 },
{ name: '支出', year: 2025, value: 65 }
];
// 1. 获取所有的 year 字段值并去重、根据年份排序
const years = Array.from(new Set(data.map(item => item.year))).sort((a, b) => a - b);
console.log('Years:', years);
// 2. 拿到 inputData 和 outputData 数组,并根据年份排序
const inputData = years.map(year => {
const item = data.find(d => d.year === year && d.name === '收入');
return item ? item.value : 0; // 如果没有找到对应年份的数据,则返回 0
});
const outputData = years.map(year => {
const item = data.find(d => d.year === year && d.name === '支出');
return item ? item.value : 0;
});
console.log('收入金额数据:', inputData);
console.log('支出金额数据:', outputData);
// Years: [2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025]
// 申报金额数据: [99535.4681, 43018.8192, 78180.2619, 60299.8414, 811298.0807, 62680.3691, 24753.8608, 80]
// 评审金额数据: [78761.4833, 36920.0656, 31246.8656, 51657.13, 8556.9949, 36.82, 50, 65]
生成树形结构
const data = [
{ id: 1, name: 'a1', pid: 0 },
{ id: 2, name: 'a2', pid: 0 },
{ id: 3, name: 'a3', pid: 1 },
{ id: 4, name: 'a4', pid: 3 },
{ id: 5, name: 'a5', pid: 3 }
];
查找树形元素
const data = [
{
id: 1,
name: '终端管理',
pid: 0,
children: [
{
id: 2,
name: '终端列表',
pid: 1,
children: [{ id: 4, name: '添加终端', pid: 2 }]
},
{ id: 3, name: '划拨设备', pid: 1 }
]
},
{
id: 5,
name: '系统设置',
pid: 0,
children: [
{
id: 6,
name: '权限管理',
pid: 5,
children: [
{ id: 7, name: '用户角色', pid: 6 },
{ id: 8, name: '菜单设置', pid: 6 }
]
}
]
}
];
function getChidlren(data, id) {
let hasFound = false, // 表示是否找到id值
result = null;
const fn = function (data) {
if (Array.isArray(data) && !hasFound) {
data.forEach(item => {
if (item.id === id) {
result = item;
hasFound = true;
} else if (item.children) {
fn(item.children);
}
});
}
};
fn(data);
return result;
}
getChidlren(data, 3);
通过唯一值数组筛选树形结构数据
从一个树形结构的数据中找到数组中的值,并组成新的数组。如下所示,有一个 orgId 组成的数组 key,期望结果是:
const res = [
{ label: '名称1', value: 1 },
{ label: '名称3', value: 3 },
{ label: '名称4', value: 4 },
{ label: '名称6', value: 6 }
];
const key = [1, 3, 4, 6];
const arr = [
{
children: [
{
children: [
{ children: null, orgId: 4, orgName: '名称4' },
{ children: null, orgId: 5, orgName: '名称5' }
],
orgId: 3,
orgName: '名称3'
},
{
children: null,
orgId: 6,
orgName: '名称6'
}
],
orgId: 1,
orgName: '名称1'
},
{
children: [
{
children: [
{ children: null, orgId: 8, orgName: '名称8' },
{ children: null, orgId: 9, orgName: '名称9' }
],
orgId: 7,
orgName: '名称7'
}
],
orgId: 2,
orgName: '名称2'
}
];
function findOrgs(arr, key) {
const res = [];
arr.forEach(obj => {
if (key.includes(obj.orgId)) {
res.push({ label: obj.orgName, value: obj.orgId });
}
if (obj.children && obj.children.length > 0) {
const childRes = findOrgs(obj.children, key);
res.push(...childRes);
}
});
return res;
}
const result = findOrgs(arr, key);
console.log(result);
树形节点搜索关键字,返回完整路径
获取指定范围内的随机数
// 1.最大值和最小值都包含在内
const getRandomNum = (min, max) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
// 2.包含最大值,不包含最小值
const getRandomNum = (min, max) => {
return Math.floor(Math.random() * (max - min)) + min + 1;
};
// 3.包含最小值,不包含最大值
const getRandomNum = (min, max) => {
return Math.floor(Math.random() * (max - min)) + min;
};
// 4.最大值和最小值都不包含在内
const getRandomNum = (min, max) => {
return Math.floor(Math.random() * (max - min - 1)) + min + 1;
};
生成随机 uuid
export const generateUUID = () => {
let d = new Date().getTime();
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
let r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === 'x' ? r : (r & 0x7) | 0x8).toString(16);
});
};
随机字符串
export const generateRdStr = length => {
let text = '';
let possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < length; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
};
经纬度格式化
度转为度分秒
function transformLonlatToDD(lon, lat) {
const lonUnit = lon > 0 ? 'E' : 'W';
const latUnit = lat > 0 ? 'N' : 'S';
const resLon = lonlat(lon) + lonUnit;
const resLat = lonlat(lat) + latUnit;
return [resLon, resLat];
}
function lonlat(coordinate) {
const d = coordinate >> 0; // 度
const m = ((coordinate % 1) * 60) >> 0; // 分
const s = ((((coordinate % 1) * 60) % 1) * 60) >> 0; // 秒
const ms = ((((coordinate % 1) * 60) % 1) * 60) % 1;
const mss = Math.round(parseFloat(ms) * 100) / 100; // 四舍五入,保留两位小数
const lon23 = Math.abs(s) + mss;
const res = Math.abs(d) + 'º' + Math.abs(m) + "'" + lon23.toFixed(2) + "''";
return res;
}
根据经纬度计算距离
function toRadians(degree) {
return (degree * Math.PI) / 180;
}
function distance(lon1, lat1, lon2, lat2) {
const R = 6371; // 地球半径 6371 km
let deltaLatitude = toRadians(lat2 - lat1);
let deltaLongitude = toRadians(lon2 - lon1);
lat1 = toRadians(lat1);
lat2 = toRadians(lat2);
let a =
Math.sin(deltaLatitude / 2) * Math.sin(deltaLatitude / 2) +
Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLongitude / 2) * Math.sin(deltaLongitude / 2);
let c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c;
}
let res = distance(116.293598, 40.227442, 116.29216, 40.200555);
console.log(res); // 3km
浮点数取整
通常使用Math.floor()
、Math.ceil()
、Math.round()
,简便写法:
console.log(~~8.666); // 8
console.log(8.666 >> 0); // 8
console.log(8.666 << 0); // 8
console.log(8.666 | 0); // 8
// >>>不可对负数取整
console.log(8.666 >>> 0); // 8
求幂运算
如求 2 的 3 次方
Math.pow(2, 3);
// 简便写法
let res = 2 ** 3;