1. 簡(jiǎn)單數(shù)組去重
- 第一種方式:
使用 reduce 函數(shù)返回值是累加的結(jié)果,判斷當(dāng)前遍歷值是否在其中。
function removeDuplicates(arr) {
let result = arr.reduce(function (init, current) {
if (init.indexOf(current) === -1) {
init.push(current);
}
return init;
}, []);
return result;
}
let myArray = ["a", "b", "a", "b", "c", "e", "e", "c", "d", "d", "d", "d"];
console.log(removeDuplicates(myArray)); // ["a", "b", "c", "e", "d"]
- 第二種方式:
先使用排序,把相同的元素放到一起,然后再使用 reduce 方法讓當(dāng)前遍歷對(duì)象跟前一個(gè)進(jìn)行比較,相同就不加入,不同則加入。
function removeDuplicates(arr) {
let result = arr.sort().reduce((init, current) => {
if (init.length === 0 || init[init.length - 1] !== current) {
init.push(current);
}
return init;
}, []);
return result;
}
let arr = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];
console.log(removeDuplicates(arr)); //[1,2,3,4,5]
- 第三種方式:
利用 indexOf 總是返回該項(xiàng)的第一個(gè)出現(xiàn)的索引,所以我們可以判斷當(dāng)前在過(guò)濾循環(huán)中的項(xiàng)是否是重復(fù)的。如果是,我們就不返回到由 filter()方法創(chuàng)建的新數(shù)組中。
function removeDuplicates(arr) {
let result = arr.filter((item, index) => {
return arr.indexOf(item) === index;
});
return result;
}
let arr = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];
console.log(removeDuplicates(arr)); //[1,2,3,4,5]
2. 數(shù)組中對(duì)象去重
function removeDuplicates(arr) {
const tempObj = {};
let result = arr.reduce((init, current) => {
tempObj[current.name]
? ""
: (tempObj[current.name] = true && init.push(current));
return init;
}, []);
return result;
}
// 注意: name字段必須為current中存在的字段
3. 扁平化嵌套數(shù)組
- 方式一:
使用 flat 方法,該方法接受一個(gè)可選參數(shù),幾維數(shù)組展開(kāi)就把數(shù)字幾作為參數(shù),使用 Infinity 作為參數(shù)時(shí)可展開(kāi)任意深度的嵌套數(shù)組
function flatArray(arr) {
return arr.flat();
}
- 方法二:
使用 reduce 方法,該方法僅適用于二維數(shù)組
function flatArray(arr) {
return arr.reduce((init, current) => init.concat(current), []);
}
4. 將數(shù)組轉(zhuǎn)化為樹(shù)形結(jié)構(gòu)
- 將如下數(shù)據(jù)轉(zhuǎn)化為樹(shù)狀結(jié)構(gòu)
let arr = [
{
id: 1,
name: "1",
pid: 0,
},
{
id: 2,
name: "1-1",
pid: 1,
},
{
id: 3,
name: "1-1-1",
pid: 2,
},
];
- 實(shí)現(xiàn)方式
function toTree(data, parentId = 0) {
var itemArr = [];
for (var i = 0; i < data.length; i++) {
var node = data[i];
if (node.pid === parentId) {
var newNode = {
...node,
name: node.name,
id: node.id,
children: toTree(data, node.id),
};
itemArr.push(newNode);
}
}
return itemArr;
}
5. 格式化時(shí)間
- 方式一:
const getDate = (timeStamp, format, type) => {
const d = new Date(timeStamp || 0);
const year = d.getFullYear();
const month = getHandledValue(d.getMonth() + 1);
const day = getHandledValue(d.getDate());
const hour = getHandledValue(d.getHours());
const minute = getHandledValue(d.getMinutes());
const second = getHandledValue(d.getSeconds());
let resStr = "";
if (!type) {
type = "/";
}
switch (format) {
case "yyyymmdd":
return [year, month, day].map(formatNumber).join(type);
case "yyyymm":
return [year, month].map(formatNumber).join(type);
case "mmdd":
return [month, day].map(formatNumber).join(type);
case "yyyy":
return year;
case "mm":
return [month].map(formatNumber);
case "dd":
return [day].map(formatNumber);
case "yyyymmddhhmmss":
return (
[year, month, day].map(formatNumber).join(type) +
" " +
[hour, minute, second].map(formatNumber).join(":")
);
case "yyyymmddhhmm":
return (
[year, month, day].map(formatNumber).join(type) +
" " +
[hour, minute].map(formatNumber).join(":")
);
case "hhmmss":
return [hour, minute, second].map(formatNumber).join(":");
case "hhmm":
return [hour, minute].map(formatNumber).join(":");
case "hh":
return [hour].map(formatNumber);
case "mi":
return [minute].map(formatNumber);
default:
return (
[year, month, day].map(formatNumber).join("/") +
" " +
[hour, minute, second].map(formatNumber).join(":")
);
}
};
- 方式二:
const formatTime = (date) => {
let fmt = 'yyyy-MM-dd hh:mm:ss'
const o = {
'M+': date.getMonth() + 1, // 月份
'd+': date.getDate(), // 日
'h+': date.getHours(), // 小時(shí)
'm+': date.getMinutes(), // 分鐘
's+': date.getSeconds(), // 秒
}
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, date.getFullYear())
}
for (let k in o) {
if (new RegExp('(' + k + ')').test(fmt)) {
fmt = fmt.replace(RegExp.$1, o[k].toString().length == 1 ? '0' + o[k] : o[k])
}
}
return fmt
}
6. 獲取相對(duì)時(shí)間
/**
* @param {String|Number} timeStamp 時(shí)間戳
* @returns {String} 相對(duì)時(shí)間字符串
*/
const getRelativeTime = (timeStamp) => {
// 判斷當(dāng)前傳入的時(shí)間戳是秒格式還是毫秒
const IS_MILLISECOND = isMillisecond(timeStamp);
// 如果是毫秒格式則轉(zhuǎn)為秒格式
if (IS_MILLISECOND) Math.floor((timeStamp /= 1000));
// 傳入的時(shí)間戳可以是數(shù)值或字符串類型,這里統(tǒng)一轉(zhuǎn)為數(shù)值類型
timeStamp = Number(timeStamp);
// 獲取當(dāng)前時(shí)間時(shí)間戳
const currentTime = Math.floor(Date.parse(new Date()) / 1000);
// 判斷傳入時(shí)間戳是否早于當(dāng)前時(shí)間戳
const IS_EARLY = isEarly(timeStamp, currentTime);
// 獲取兩個(gè)時(shí)間戳差值
let diff = currentTime - timeStamp;
// 如果IS_EARLY為false則差值取反
if (!IS_EARLY) diff = -diff;
let resStr = "";
const dirStr = IS_EARLY ? "前" : "后";
// 少于等于59秒
if (diff <= 59) resStr = diff + "秒" + dirStr;
// 多于59秒,少于等于59分鐘59秒
else if (diff > 59 && diff <= 3599)
resStr = Math.floor(diff / 60) + "分鐘" + dirStr;
// 多于59分鐘59秒,少于等于23小時(shí)59分鐘59秒
else if (diff > 3599 && diff <= 86399)
resStr = Math.floor(diff / 3600) + "小時(shí)" + dirStr;
// 多于23小時(shí)59分鐘59秒,少于等于29天59分鐘59秒
else if (diff > 86399 && diff <= 2623859)
resStr = Math.floor(diff / 86400) + "天" + dirStr;
// 多于29天59分鐘59秒,少于364天23小時(shí)59分鐘59秒,且傳入的時(shí)間戳早于當(dāng)前
else if (diff > 2623859 && diff <= 31567859 && IS_EARLY)
resStr = getDate(timeStamp);
else resStr = getDate(timeStamp, "year");
return resStr;
};
7. 獲取當(dāng)前瀏覽器
/**
* @returns {String} 當(dāng)前瀏覽器名稱
*/
const getExplorer = () => {
const ua = window.navigator.userAgent;
const isExplorer = (exp) => {
return ua.indexOf(exp) > -1;
};
if (isExplorer("MSIE")) return "IE";
else if (isExplorer("Firefox")) return "Firefox";
else if (isExplorer("Chrome")) return "Chrome";
else if (isExplorer("Opera")) return "Opera";
else if (isExplorer("Safari")) return "Safari";
};
8. 判斷兩個(gè)對(duì)象是否相等
/**
* @param {*} obj1 對(duì)象
* @param {*} obj2 對(duì)象
* @description 判斷兩個(gè)對(duì)象是否相等,這兩個(gè)對(duì)象的值只能是數(shù)字或字符串
*/
const objEqual = (obj1, obj2) => {
const keysArr1 = Object.keys(obj1);
const keysArr2 = Object.keys(obj2);
if (keysArr1.length !== keysArr2.length) return false;
else if (keysArr1.length === 0 && keysArr2.length === 0) return true;
/* eslint-disable-next-line */ else
return !keysArr1.some((key) => obj1[key] != obj2[key]);
};
9. 百分比轉(zhuǎn)小數(shù)
const percentageToDecimal = (num) => {
if (typeof num !== "number") num = Number(num);
let convert = num;
let unit = 100;
return convert / unit;
};
10. 小數(shù)轉(zhuǎn)百分比
const decimalToPercentage = (num) => {
if (num && typeof num === "number") {
let convert = num;
let unit = 100;
return convert * unit;
} else {
return num;
}
};
11. 數(shù)組按指定份數(shù)分割
const splitArr = (data, senArrLen) => {
//處理成len個(gè)一組的數(shù)據(jù)
let data_len = data.length;
let arrOuter_len =
data_len % senArrLen === 0
? data_len / senArrLen
: parseInt(data_len / senArrLen + "") + 1;
let arrSec_len = data_len > senArrLen ? senArrLen : data_len; //內(nèi)層數(shù)組的長(zhǎng)度
let arrOuter = new Array(arrOuter_len); //最外層數(shù)組
let arrOuter_index = 0; //外層數(shù)組的子元素下標(biāo)
for (let i = 0; i < data_len; i++) {
if (i % senArrLen === 0) {
arrOuter_index++;
let len = arrSec_len * arrOuter_index;
//將內(nèi)層數(shù)組的長(zhǎng)度最小取決于數(shù)據(jù)長(zhǎng)度對(duì)len取余,平時(shí)最內(nèi)層由下面賦值決定
arrOuter[arrOuter_index - 1] = new Array(data_len % senArrLen);
if (arrOuter_index === arrOuter_len)
//最后一組
data_len % senArrLen === 0
? (len = (data_len % senArrLen) + senArrLen * arrOuter_index)
: (len = (data_len % senArrLen) + senArrLen * (arrOuter_index - 1));
let arrSec_index = 0; //第二層數(shù)組的索引
for (let k = i; k < len; k++) {
//第一層數(shù)組的開(kāi)始取決于第二層數(shù)組長(zhǎng)度*當(dāng)前第一層的索引
arrOuter[arrOuter_index - 1][arrSec_index] = data[k];
arrSec_index++;
}
}
}
return arrOuter;
};
12. 下載圖片
const downloadImg = (imgsrc, name) => {
//下載圖片地址和圖片名
let image = new Image();
// 解決跨域 Canvas 污染問(wèn)題
image.setAttribute("crossOrigin", "anonymous");
image.onload = function () {
let canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
let context = canvas.getContext("2d");
context.drawImage(image, 0, 0, image.width, image.height);
let url = canvas.toDataURL("image/png"); //得到圖片的base64編碼數(shù)據(jù)
let a = document.createElement("a"); // 生成一個(gè)a元素
let event = new MouseEvent("click"); // 創(chuàng)建一個(gè)單擊事件
a.download = name || "photo"; // 設(shè)置圖片名稱
a.href = url; // 將生成的URL設(shè)置為a.href屬性
a.dispatchEvent(event); // 觸發(fā)a的單擊事件
};
image.src = imgsrc;
};
13. 拖拽移動(dòng)
export const dragToMove = (dragDom, dragId) => {
var startEvt, moveEvt, endEvt;
// 判斷是否支持觸摸事件
if ("ontouchstart" in window) {
startEvt = "touchstart";
moveEvt = "touchmove";
endEvt = "touchend";
} else {
startEvt = "mousedown";
moveEvt = "mousemove";
endEvt = "mouseup";
}
// 獲取元素
var drag = dragDom;
var disX, disY, left, top, starX, starY;
var firstTime = "",
lastTime = "";
drag.addEventListener(startEvt, function (e) {
// 阻止頁(yè)面的滾動(dòng),縮放
e.preventDefault();
document.getElementById(dragId).setAttribute("data-flag", false);
firstTime = new Date().getTime();
// 兼容IE瀏覽器
var e = e || window.event;
// 手指按下時(shí)的坐標(biāo)
starX = e.touches ? e.touches[0].clientX : e.clientX;
starY = e.touches ? e.touches[0].clientY : e.clientY;
// 手指相對(duì)于拖動(dòng)元素左上角的位置
disX = starX - drag.offsetLeft;
disY = starY - drag.offsetTop;
document.addEventListener(moveEvt, moveFun);
document.addEventListener(endEvt, endFun);
});
function moveFun(e) {
// 兼容IE瀏覽器
var e = e || window.event;
left = (e.touches ? e.touches[0].clientX : e.clientX) - disX;
top = (e.touches ? e.touches[0].clientY : e.clientY) - disY;
// 限制拖拽的X范圍,不能拖出屏幕
if (left < 0) {
left = 0;
} else if (left > document.documentElement.clientWidth - drag.offsetWidth) {
left = document.documentElement.clientWidth - drag.offsetWidth;
}
// 限制拖拽的Y范圍,不能拖出屏幕
if (top < 0) {
top = 0;
} else if (
top >
document.documentElement.clientHeight - drag.offsetHeight
) {
top = document.documentElement.clientHeight - drag.offsetHeight;
}
drag.style.left = left + "px";
drag.style.top = top + "px";
}
function endFun(e) {
document.removeEventListener(moveEvt, moveFun);
document.removeEventListener(endEvt, endFun);
lastTime = new Date().getTime();
if (lastTime - firstTime < 200) {
document.getElementById(dragId).setAttribute("data-flag", true);
if (endEvt == "touchend") {
document.getElementById(dragId).click();
}
}
}
};
14. 從 url 中解析出參數(shù)
/**
* @param {String} url
* @description 從URL中解析參數(shù)
*/
const getParams = (url) => {
const keyValueArr = url.split("?")[1].split("&");
let paramObj = {};
keyValueArr.forEach((item) => {
const keyValue = item.split("=");
paramObj[keyValue[0]] = keyValue[1];
});
return paramObj;
};
15. 格式化金額
const formatNumber = (val = 0) => {
isNaN(val) ? (val = 0) : val;
return (val * 1).toLocaleString("zh", { minimumFractionDigits: 2 });
};
16. 加減乘法
// 減法#
const subtr = (arg1, arg2) => {
let num1 = arg1 || 0;
let num2 = arg2 || 0;
let r1, r2, m, n;
try {
r1 = num1.toString().split(".")[1].length;
} catch (e) {
r1 = 0;
}
try {
r2 = num2.toString().split(".")[1].length;
} catch (e) {
r2 = 0;
}
m = Math.pow(10, Math.max(r1, r2));
n = r1 >= r2 ? r1 : r2;
return ((mul(num1, m) - mul(num2, m)) / m).toFixed(n);
};
//乘法
const mul = (arg1, arg2) => {
let m = 0,
s1 = arg1.toString(),
s2 = arg2.toString();
try {
m += s1.split(".")[1].length;
} catch (e) {}
try {
m += s2.split(".")[1].length;
} catch (e) {}
return (
(Number(s1.replace(".", "")) * Number(s2.replace(".", ""))) /
Math.pow(10, m)
);
};
//加法
const accAdd = (arg1, arg2) => {
let num1 = arg1 || 0;
let num2 = arg2 || 0;
let r1, r2, m;
try {
r1 = num1.toString().split(".")[1].length;
} catch (e) {
r1 = 0;
}
try {
r2 = num2.toString().split(".")[1].length;
} catch (e) {
r2 = 0;
}
m = Math.pow(10, Math.max(r1, r2));
return (mul(num1, m) + mul(num2, m)) / m;
};
17. 自定義指令-按鈕權(quán)限控制
Vue.directive("has", {
inserted: function (el, binding) {
if (!Vue.prototype.$has(binding.value)) {
el.parentNode.removeChild(el);
}
},
});
18. 自定義指令-防快速重復(fù)點(diǎn)擊按鈕
import Vue from "vue";
Vue.directive("preventReClick", {
inserted(el) {
el.addEventListener("click", () => {
if (!el.disabled) {
el.disabled = true;
setTimeout(() => {
el.disabled = false;
}, 2000);
}
});
},
});
19. 獲取時(shí)間差
const getDateDiff = (startTime, endTime, diffType) => {
// 將xxxx-xx-xx的時(shí)間格式,轉(zhuǎn)換為 xxxx/xx/xx的格式
startTime = startTime.replace(/-/g, "/");
endTime = endTime.replace(/-/g, "/");
// 將計(jì)算間隔類性字符轉(zhuǎn)換為小寫(xiě)
diffType = diffType.toLowerCase();
var sTime = new Date(startTime); // 開(kāi)始時(shí)間
var eTime = new Date(endTime); // 結(jié)束時(shí)間
// 作為除數(shù)的數(shù)字
var divNum = 1;
switch (diffType) {
case "second":
divNum = 1000;
break;
case "minute":
divNum = 1000 * 60;
break;
case "hour":
divNum = 1000 * 3600;
break;
case "day":
divNum = 1000 * 3600 * 24;
break;
default:
break;
}
return parseInt((eTime.getTime() - sTime.getTime()) / parseInt(divNum));
};
20. 獲取文件擴(kuò)展名
const getFileType = (filePath) => {
var startIndex = filePath.lastIndexOf(".");
if (startIndex !== -1) {
return filePath.substring(startIndex + 1, filePath.length).toLowerCase();
} else {
return "";
}
};
21. 判斷數(shù)組中是否有重復(fù)對(duì)象
const isRepeat = (arr) => {
const obj = {};
let flag = false;
arr.map((item) => {
obj[item.id] ? (flag = true) : (obj[item.id] = true);
});
return flag;
};
22. 壓縮圖片
export function compress(fileObj) {
return new Promise(resolve => {
function dataURLtoBlob(dataUrl) {
//base64格式圖片 轉(zhuǎn)為Blob
const arr = dataUrl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], fileObj.name, {
lastModified: fileObj.lastModifiedDate,
type: mime
})
}
if (typeof FileReader === 'undefined') {
console.log('當(dāng)前瀏覽器內(nèi)核不支持base64圖標(biāo)壓縮')
resolve(fileObj)
}
try {
const reader = new FileReader()
const image = new Image()
reader.readAsDataURL(fileObj) //開(kāi)始讀取指定的Blob中的內(nèi)容。返回base64
reader.onload = function (ev) {
image.src = String(ev.target.result)
image.onload = function () {
let imgWidth = image.width,
imgHeight = image.height //獲取圖片寬高
//設(shè)置圖片的最大寬度為300
imgWidth = image.width
imgHeight = image.height //設(shè)置等比例高度
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = imgWidth
canvas.height = imgHeight
ctx.drawImage(image, 0, 0, imgWidth, imgHeight) //根據(jù)寬高繪制圖片
const fullQuality = canvas.toDataURL('image/jpeg', 0.05) //canvas轉(zhuǎn)為base64
const blogData = dataURLtoBlob(fullQuality)
resolve(blogData)
}
}
} catch (e) {
resolve(fileObj)
}
})
}
23. 大數(shù)字轉(zhuǎn)換為萬(wàn)/億
/*
* @params : num 數(shù)字
* @params : point 保留幾位小數(shù)
*/
export function transferNumber(num, point) {
let numStr = num.toString().split('.')[0]
if (numStr.length < 6) { // 十萬(wàn)以下不轉(zhuǎn)化原數(shù)字顯示
return numStr
} else if (numStr.length >= 6 && numStr.length <= 8) {
// 6-8位:十萬(wàn) - 千萬(wàn) 轉(zhuǎn)化為萬(wàn)
let decimal = numStr.substring(numStr.length - 4, numStr.length - 4 + point)
return parseFloat(parseInt(num / 10000) + '.' + decimal) +
'萬(wàn)'
} else if (numStr.length > 8) {
// 超過(guò)8為 顯示億
let decimal = numStr.substring(numStr.length - 8, numStr.length - 8 + point)
return parseFloat(parseInt(num / 100000000) + '.' + decimal) + '億'
}
}