1. 簡單數組去重
- 第一種方式:
使用 reduce 函數返回值是累加的結果,判斷當前遍歷值是否在其中。
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 方法讓當前遍歷對象跟前一個進行比較,相同就不加入,不同則加入。
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 總是返回該項的第一個出現的索引,所以我們可以判斷當前在過濾循環中的項是否是重復的。如果是,我們就不返回到由 filter()方法創建的新數組中。
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. 數組中對象去重
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. 扁平化嵌套數組
- 方式一:
使用 flat 方法,該方法接受一個可選參數,幾維數組展開就把數字幾作為參數,使用 Infinity 作為參數時可展開任意深度的嵌套數組
function flatArray(arr) {
return arr.flat();
}
- 方法二:
使用 reduce 方法,該方法僅適用于二維數組
function flatArray(arr) {
return arr.reduce((init, current) => init.concat(current), []);
}
4. 將數組轉化為樹形結構
- 將如下數據轉化為樹狀結構
let arr = [
{
id: 1,
name: "1",
pid: 0,
},
{
id: 2,
name: "1-1",
pid: 1,
},
{
id: 3,
name: "1-1-1",
pid: 2,
},
];
- 實現方式
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. 格式化時間
- 方式一:
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(), // 小時
'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. 獲取相對時間
/**
* @param {String|Number} timeStamp 時間戳
* @returns {String} 相對時間字符串
*/
const getRelativeTime = (timeStamp) => {
// 判斷當前傳入的時間戳是秒格式還是毫秒
const IS_MILLISECOND = isMillisecond(timeStamp);
// 如果是毫秒格式則轉為秒格式
if (IS_MILLISECOND) Math.floor((timeStamp /= 1000));
// 傳入的時間戳可以是數值或字符串類型,這里統一轉為數值類型
timeStamp = Number(timeStamp);
// 獲取當前時間時間戳
const currentTime = Math.floor(Date.parse(new Date()) / 1000);
// 判斷傳入時間戳是否早于當前時間戳
const IS_EARLY = isEarly(timeStamp, currentTime);
// 獲取兩個時間戳差值
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小時59分鐘59秒
else if (diff > 3599 && diff <= 86399)
resStr = Math.floor(diff / 3600) + "小時" + dirStr;
// 多于23小時59分鐘59秒,少于等于29天59分鐘59秒
else if (diff > 86399 && diff <= 2623859)
resStr = Math.floor(diff / 86400) + "天" + dirStr;
// 多于29天59分鐘59秒,少于364天23小時59分鐘59秒,且傳入的時間戳早于當前
else if (diff > 2623859 && diff <= 31567859 && IS_EARLY)
resStr = getDate(timeStamp);
else resStr = getDate(timeStamp, "year");
return resStr;
};
7. 獲取當前瀏覽器
/**
* @returns {String} 當前瀏覽器名稱
*/
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. 判斷兩個對象是否相等
/**
* @param {*} obj1 對象
* @param {*} obj2 對象
* @description 判斷兩個對象是否相等,這兩個對象的值只能是數字或字符串
*/
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. 百分比轉小數
const percentageToDecimal = (num) => {
if (typeof num !== "number") num = Number(num);
let convert = num;
let unit = 100;
return convert / unit;
};
10. 小數轉百分比
const decimalToPercentage = (num) => {
if (num && typeof num === "number") {
let convert = num;
let unit = 100;
return convert * unit;
} else {
return num;
}
};
11. 數組按指定份數分割
const splitArr = (data, senArrLen) => {
//處理成len個一組的數據
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; //內層數組的長度
let arrOuter = new Array(arrOuter_len); //最外層數組
let arrOuter_index = 0; //外層數組的子元素下標
for (let i = 0; i < data_len; i++) {
if (i % senArrLen === 0) {
arrOuter_index++;
let len = arrSec_len * arrOuter_index;
//將內層數組的長度最小取決于數據長度對len取余,平時最內層由下面賦值決定
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; //第二層數組的索引
for (let k = i; k < len; k++) {
//第一層數組的開始取決于第二層數組長度*當前第一層的索引
arrOuter[arrOuter_index - 1][arrSec_index] = data[k];
arrSec_index++;
}
}
}
return arrOuter;
};
12. 下載圖片
const downloadImg = (imgsrc, name) => {
//下載圖片地址和圖片名
let image = new Image();
// 解決跨域 Canvas 污染問題
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編碼數據
let a = document.createElement("a"); // 生成一個a元素
let event = new MouseEvent("click"); // 創建一個單擊事件
a.download = name || "photo"; // 設置圖片名稱
a.href = url; // 將生成的URL設置為a.href屬性
a.dispatchEvent(event); // 觸發a的單擊事件
};
image.src = imgsrc;
};
13. 拖拽移動
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) {
// 阻止頁面的滾動,縮放
e.preventDefault();
document.getElementById(dragId).setAttribute("data-flag", false);
firstTime = new Date().getTime();
// 兼容IE瀏覽器
var e = e || window.event;
// 手指按下時的坐標
starX = e.touches ? e.touches[0].clientX : e.clientX;
starY = e.touches ? e.touches[0].clientY : e.clientY;
// 手指相對于拖動元素左上角的位置
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 中解析出參數
/**
* @param {String} url
* @description 從URL中解析參數
*/
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. 自定義指令-按鈕權限控制
Vue.directive("has", {
inserted: function (el, binding) {
if (!Vue.prototype.$has(binding.value)) {
el.parentNode.removeChild(el);
}
},
});
18. 自定義指令-防快速重復點擊按鈕
import Vue from "vue";
Vue.directive("preventReClick", {
inserted(el) {
el.addEventListener("click", () => {
if (!el.disabled) {
el.disabled = true;
setTimeout(() => {
el.disabled = false;
}, 2000);
}
});
},
});
19. 獲取時間差
const getDateDiff = (startTime, endTime, diffType) => {
// 將xxxx-xx-xx的時間格式,轉換為 xxxx/xx/xx的格式
startTime = startTime.replace(/-/g, "/");
endTime = endTime.replace(/-/g, "/");
// 將計算間隔類性字符轉換為小寫
diffType = diffType.toLowerCase();
var sTime = new Date(startTime); // 開始時間
var eTime = new Date(endTime); // 結束時間
// 作為除數的數字
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. 獲取文件擴展名
const getFileType = (filePath) => {
var startIndex = filePath.lastIndexOf(".");
if (startIndex !== -1) {
return filePath.substring(startIndex + 1, filePath.length).toLowerCase();
} else {
return "";
}
};
21. 判斷數組中是否有重復對象
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格式圖片 轉為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('當前瀏覽器內核不支持base64圖標壓縮')
resolve(fileObj)
}
try {
const reader = new FileReader()
const image = new Image()
reader.readAsDataURL(fileObj) //開始讀取指定的Blob中的內容。返回base64
reader.onload = function (ev) {
image.src = String(ev.target.result)
image.onload = function () {
let imgWidth = image.width,
imgHeight = image.height //獲取圖片寬高
//設置圖片的最大寬度為300
imgWidth = image.width
imgHeight = image.height //設置等比例高度
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = imgWidth
canvas.height = imgHeight
ctx.drawImage(image, 0, 0, imgWidth, imgHeight) //根據寬高繪制圖片
const fullQuality = canvas.toDataURL('image/jpeg', 0.05) //canvas轉為base64
const blogData = dataURLtoBlob(fullQuality)
resolve(blogData)
}
}
} catch (e) {
resolve(fileObj)
}
})
}
23. 大數字轉換為萬/億
/*
* @params : num 數字
* @params : point 保留幾位小數
*/
export function transferNumber(num, point) {
let numStr = num.toString().split('.')[0]
if (numStr.length < 6) { // 十萬以下不轉化原數字顯示
return numStr
} else if (numStr.length >= 6 && numStr.length <= 8) {
// 6-8位:十萬 - 千萬 轉化為萬
let decimal = numStr.substring(numStr.length - 4, numStr.length - 4 + point)
return parseFloat(parseInt(num / 10000) + '.' + decimal) +
'萬'
} else if (numStr.length > 8) {
// 超過8為 顯示億
let decimal = numStr.substring(numStr.length - 8, numStr.length - 8 + point)
return parseFloat(parseInt(num / 100000000) + '.' + decimal) + '億'
}
}