JS_通用模块封装

主要记录一些在项目中经常用到模块,进行了一个封装,增加代码的可维护性及易读性。

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);
        }
    }
}

以上内容,如有错误请指出,不甚感激。
如需转载,请注明出处

原文地址:https://www.cnblogs.com/adelina-blog/p/10559676.html