主要記錄一些在項目中經常用到模塊,進行了一個封裝,增加代碼的可維護性及易讀性。
1.比較兩個對象/數組..中的值是否完全相等
// 對比兩個對象之間的差別
contrastObjSame(originObj, curObj) {
if(originObj === undefined || curObj === undefined) {
return false;
}
if(Object.prototype.toString.call(originObj) !== Object.prototype.toString.call(curObj)) {
return false;
}
if(typeof originObj !== 'object') {
if(originObj !== curObj) {
return false;
}
return true;
} else if(Object.prototype.toString.call(originObj).toLowerCase().indexOf(' object') >= 0) {
let originObjKeyArr = Object.keys(originObj);
let curObjKeyArr = Object.keys(curObj);
if(originObjKeyArr.length !== curObjKeyArr.length) {
return false;
}
for(let key in originObj) {
if(curObj[key] === undefined) {
return false;
}
if(!this.contrastObjSame(originObj[key], curObj[key])) {
return false;
}
}
return true;
} else if(Object.prototype.toString.call(originObj).toLowerCase().indexOf(' array') >= 0) {
let originLen = originObj.length;
let curLen = originObj.length;
if(originLen !== curLen) {
return false;
}
for(let i = 0; i < originLen; i++) {
if(!this.contrastObjSame(originObj[i], curObj[i])) {
return false;
}
}
return true;
} else{
return originObj === curObj;
}
}
2.深拷貝
deepCopy(o) {
// 數組
if (o instanceof Array) {
return o.map(item => {
return this.deepCopy(item);
});
} else if (o instanceof Object) {
let temp = {};
Object.keys(o).map(item => {
temp[item] = this.deepCopy(o[item]);
});
return temp;
} else {
return o;
}
}
3.值校驗
/** 值校驗
* @params:
* {obj.name}校驗的值;
* {obj.errorTip}錯誤顯示內容;
* {obj.required}是否必填;
* {obj.regExp}正則數組;
* {obj.regExp[index].reg}校驗規則-正則
* {obj.regExp[index].attr}校驗規則屬性-正則
* {obj.regExp[index].ifForbid}校驗規則-true:符合規則的不通過;false:符合規則的通過
* {obj.regExp[index].err}錯誤提示
*/
validateValue(value, obj, item) {
if (typeof obj === 'undefined') {
return {
result: true,
msg: '不存在校驗項'
};
} else if (typeof value === 'undefined' && typeof obj.errorTip !== 'undefined') {
obj.errorTip = '';
return {
result: true,
msg: '不存在校驗項'
};
} else if (typeof value === 'undefined' && typeof obj.errorTip === 'undefined') {
return {
result: true,
msg: '不存在校驗項&不存在信息錯誤提示'
};
}
if (typeof obj.errorTip !== 'undefined') {
obj.errorTip = '';
}
if (obj.required && (!value && value !== 0)) {
if (typeof obj.errorTip !== 'undefined') {
obj.errorTip = '請輸入正確的值';
}
return {
result: false,
ifRequiredFill: false,
msg: '請輸入正確的值'
};
} else if (obj.regExp && obj.regExp.length > 0) {
for (var i = 0, len = obj.regExp.length; i < len; i++) {
let attr = obj.regExp[i].attr || 'ig';
let pattern = new RegExp(obj.regExp[i].reg, attr);
let ifForbid = obj.regExp[i].ifForbid || false;
let ifHasValueCheck = obj.regExp[i].ifHasValueCheck || false;
if (ifHasValueCheck && !value) {
continue;
}
if (value && ((ifForbid && pattern.test(value)) || (!ifForbid && !pattern.test(value)))) {
if (obj.regExp[i].err && typeof obj.errorTip !== 'undefined') {
obj.errorTip = obj.regExp[i].err;
}
break;
}
}
if (i >= len) {
return {
result: true,
msg: '校驗通過'
};
} else {
return {
result: false,
ifRequiredFill: true,
msg: obj.regExp[i].err || '校驗未通過'
};
}
} else {
return {
result: true,
msg: '校驗通過'
};
}
}
4.生成隨機數
// 生成隨機數
getRandomNum(randomLength) {
let rL = randomLength || 18;
return Number(Math.random().toString().substr(3, rL) + Date.now()).toString(36);
}
5.文件導出
// 導出文件 - base64轉為文件
base64ToFile(base64Data, tempfilename, contentType) {
if (!base64Data) {
return;
}
contentType = contentType || 'application/vnd.ms-excel';
var sliceSize = 1024;
var byteCharacters = atob(base64Data);
var bytesLength = byteCharacters.length;
var slicesCount = Math.ceil(bytesLength / sliceSize);
var byteArrays = new Array(slicesCount);
for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
var begin = sliceIndex * sliceSize;
var end = Math.min(begin + sliceSize, bytesLength);
var bytes = new Array(end - begin);
for (var offset = begin, i = 0; offset < end; ++i, ++offset) {
bytes[i] = byteCharacters[offset].charCodeAt(0);
}
byteArrays[sliceIndex] = new Uint8Array(bytes);
}
var file = new File(byteArrays, tempfilename, { type: contentType });
return file;
},
// 導出文件 -- 下載二進制流binary
// 注意download兼容性不佳
downloadBinary(data, filename, type) {
if (!data) {
return;
}
type = type || 'application/vnd.ms-excel';
var file = new Blob([data], { type: type });
if (window.navigator.msSaveOrOpenBlob) // IE10+
window.navigator.msSaveOrOpenBlob(file, filename);
else { // Others
var link = document.createElement("a"),
url = URL.createObjectURL(file);
link.style.display = 'none';
link.href = url;
link.download = filename || this.getRandomNum();
document.body.appendChild(link);
link.click();
setTimeout(function() {
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
}, 0);
}
},
// 導出文件 -- base64 -- 先轉為binary-文件-blob在下載
downloadBase64File(data, filename, type) {
if (!data) {
return;
}
this.downloadBinary(this.base64ToFile(data, filename, type), filename, type);
},
// 導出文件 -- 下載base64
// 注意download兼容性不佳
// 注釋部分有待檢驗
downloadBase64(data, filename, type) {
if (!data) {
return;
}
type = type || 'application/vnd.ms-excel';
let file = `data:${type};base64,${data}`
// if (window.navigator.msSaveOrOpenBlob) // IE10+
// window.navigator.msSaveOrOpenBlob(file, filename);
// else { // Others
var link = document.createElement("a"),
url = file;
link.style.display = 'none';
link.href = url;
link.download = filename;
document.body.appendChild(link);
link.click();
}
6.格式化時間
// 獲取時間
// @params: {time}時間戳/date格式;{format}顯示示格式 Y-M-D H:F:S
getFormateTime(time, formatStr) {
let format = formatStr || 'Y-M-D';
if (!time) return '- -';
// if (time.toString().length !== 13) return time;
if (!(Object.prototype.toString.call(time).toLowerCase().indexOf('date') >= 0 || typeof time === 'number' || typeof time === 'string')) {
return '- -';
}
let date = null;
if (Object.prototype.toString.call(time).toLowerCase().indexOf('date') < 0) {
time = parseInt(time);
date = new Date(time);
}
if (Object.prototype.toString.call(date).toLowerCase().indexOf('date') < 0) {
return '- -';
}
let year = date.getFullYear();
let month = date.getMonth() + 1;
month = month < 10 ? '0' + month : month;
let day = date.getDate();
day = day < 10 ? '0' + day : day;
let hours = date.getHours();
hours = hours < 10 ? '0' + hours : hours;
let minutes = date.getMinutes();
minutes = minutes < 10 ? '0' + minutes : minutes;
let seconds = date.getSeconds();
seconds = seconds < 10 ? '0' + seconds : seconds;
// 去頭尾空格
format = format.replace(/(^\s*)|(\s*$)/g, '');
format = format.replace(/(Y|y)/gi, year);
format = format.replace(/(M|m)/gi, month);
format = format.replace(/(D|d)/gi, day);
format = format.replace(/(H|h)/gi, hours);
format = format.replace(/(F|f)/gi, minutes);
format = format.replace(/(S|s)/gi, seconds);
return format;
}
// 獲取距離現在XX天的時間
// 有大的值取大的(1年10月 = 1年前)
// @params: {time}時間戳/date格式;{format}顯示示格式最小的顯示時間:Y/M/D/H/F/S
getFromTime(time, format) {
if (!time) return "- -";
// if (time.toString().length != 13) return time;
if (!(Object.prototype.toString.call(time).toLowerCase().indexOf('date') >= 0 || typeof time === 'number' || typeof time === 'string')) {
return '- -';
}
let date = null;
if (Object.prototype.toString.call(time).toLowerCase().indexOf('date') < 0) {
time = parseInt(time);
date = new Date(time);
}
if (Object.prototype.toString.call(date).toLowerCase().indexOf('date') < 0) {
return '- -';
}
// 默認最小是天
let level = 3;
switch (format) {
case 'Y':
level = 1;
break;
case 'M':
level = 2;
break;
case 'D':
level = 3;
break;
case 'H':
level = 4;
break;
case 'F':
level = 5;
break;
case 'S':
level = 6;
break;
};
let curDate = new Date();
if (level <= 3) {
curDate.setHours(date.getHours());
}
if (level <= 4) {
curDate.setMinutes(date.getMinutes());
}
if (level <= 5) {
curDate.setSeconds(date.getSeconds());
}
curDate.setMilliseconds(date.getMilliseconds());
let tag = curDate - date < 0 ? "后" : "前";
let timeOffset = Math.abs(curDate.getTime() - date.getTime()) / 1000;
let secondsOffset = Math.floor(timeOffset);
let minutesOffset = Math.floor(timeOffset / 60);
let hoursOffset = Math.floor(timeOffset / 60 / 60);
let dayOffset = Math.floor(timeOffset / 60 / 60 / 24);
if (level <= 3) {
dayOffset = curDate - date > 0 ? Math.floor(timeOffset / 60 / 60 / 24) : Math.ceil(timeOffset / 60 / 60 / 24);
}
let monthOffset = Math.floor(dayOffset / 30);
let yearOffset = Math.floor(dayOffset / 365);
let ans = '';
if (yearOffset !== 0 && level >= 1) {
ans = `${yearOffset} 年`;
} else if (monthOffset !== 0 && level >= 2) {
ans = `${monthOffset} 月`;
} else if (dayOffset !== 0 && level >= 3) {
ans = `${dayOffset} 天`;
} else if (hoursOffset !== 0 && level >= 4) {
ans = `${hoursOffset} 小時`
} else if (minutesOffset !== 0 && level >= 5) {
ans = `${minutesOffset} 分鍾`
} else if (secondsOffset !== 0 && level >= 6) {
ans = `${secondsOffset} 秒`;
} else if (level === 3) {
ans = '今天';
} else if (level > 3) {
ans = '剛剛'
}
ans = (ans === '今天' || ans === '剛剛') ? ans : ans + tag;
return ans;
}
終極版
// 時間格式化輔助函數 date:毫秒數 format:'yyyy-MM-dd hh:mm:ss'
dateTimeFormatter(date, format) {
if (!date || date == "") {
return ""
}
if (typeof date === "string") {
var mts = date.match(/(\/Date\((\d+)\)\/)/)
if (mts && mts.length >= 3) {
date = parseInt(mts[2])
}
}
date = new Date(date)
if (!date || date.toUTCString() == "Invalid Date") {
return ""
}
var map = {
"M": date.getMonth() + 1, //月份
"d": date.getDate(), //日
"h": date.getHours(), //小時
"m": date.getMinutes(), //分
"s": date.getSeconds(), //秒
"q": Math.floor((date.getMonth() + 3) / 3), //季度
"S": date.getMilliseconds() //毫秒
}
format = format.replace(/([yMdhmsqS])+/g, function(all, t) {
var v = map[t]
if (v !== undefined) {
if (all.length > 1) {
v = '0' + v
v = v.substr(v.length - 2)
}
return v
} else if (t === 'y') {
return (date.getFullYear() + '').substr(4 - all.length)
}
return all
})
return format
}
7. vue element-ui 指令 - 讓彈窗可移動
// 讓elemntui的el-dialog可以移動
// 調用方式v-dialogDrag='彈窗顯示/隱藏參數'
dialogDrag: {
bind(el, binding, vnode, oldVnode) {
const dialogHeaderEl = el.querySelector('.el-dialog__header');
const dragDom = el.querySelector('.el-dialog');
const windowWidth = document.body.clientWidth;
const windwoHeight = document.body.clientHeight;
// 空間不足,禁止移動
if (windowWidth <= dragDom.offsetWidth && windwoHeight <= dragDom.offsetHeight) {
return;
}
// 初始化
el.style.overflow = 'visible';
el.style.marginTop = dragDom.style.marginTop;
el.style.marginLeft = 'auto';
el.style.marginRight = 'auto';
setTimeout(() => {
el.style.left = (windowWidth - dragDom.offsetWidth) / 2 + 'px';
}, 0);
el.style.right = 'auto';
el.style.bottom = 'auto';
dragDom.style.marginTop = 0;
dialogHeaderEl.style.cursor = 'move';
// 獲取原有屬性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
const sty = el.currentStyle || window.getComputedStyle(el, null);
const styMarginTop = el.style.marginTop;
dialogHeaderEl.onmousedown = (e) => {
// 鼠標按下,計算當前元素距離可視區的距離
const disX = e.clientX - dialogHeaderEl.offsetLeft;
const disY = e.clientY - dialogHeaderEl.offsetTop;
// 獲取到的值帶px 正則匹配替換
let styL, styT;
// 注意在ie中 第一次獲取到的值為組件自帶50% 移動之后賦值為px
if (sty.left.includes('%')) {
styL = +windowWidth * (+sty.left.replace(/\%/g, '') / 100);
styT = +windwoHeight * (+sty.top.replace(/\%/g, '') / 100);
} else {
styL = +sty.left.replace(/\px/g, '');
styT = +sty.top.replace(/\px/g, '');
};
document.onmousemove = function(e) {
// 通過事件委托,計算移動的距離
let l = e.clientX - disX + styL;
let t = e.clientY - disY + styT;
let marginTopPx = styMarginTop;
let leftOver = windowWidth - dragDom.offsetWidth;
if (styMarginTop.indexOf('vh') >= 0) {
marginTopPx = windwoHeight / 100 * parseFloat(styMarginTop.replace(/\px/g, ''))
}
let marginBottomLeft = windwoHeight - marginTopPx - el.offsetHeight + 50;
// 邊界值控制
if (l < 0 && windowWidth > dragDom.offsetWidth) {
l = 0;
} else if (l > leftOver && windowWidth > dragDom.offsetWidth) {
l = leftOver;
}
if (t < -marginTopPx && windwoHeight > dragDom.offsetHeight) {
t = -marginTopPx;
} else if (t > marginBottomLeft && windwoHeight > dragDom.offsetHeight) {
t = marginBottomLeft;
}
// 移動當前元素
if (windowWidth > dragDom.offsetWidth) {
el.style.left = `${l}px`;
}
if (windwoHeight > dragDom.offsetHeight) {
el.style.top = `${t}px`;
}
//將此時的位置傳出去
//binding.value({x:e.pageX,y:e.pageY})
};
document.onmouseup = function(e) {
document.onmousemove = null;
document.onmouseup = null;
};
}
},
update(el, binding, vnode, oldVnode) {
const dragDom = el.querySelector('.el-dialog');
const windowWidth = document.body.clientWidth;
// 恢復位置
if (binding.value && binding.oldValue !== binding.value) {
setTimeout(() => {
el.style.left = (document.body.clientWidth - dragDom.offsetWidth) / 2 + 'px';
el.style.top = 0;
}, 0);
}
}
}
以上內容,如有錯誤請指出,不甚感激。
如需轉載,請注明出處