zoukankan      html  css  js  c++  java
  • 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);
            }
        }
    }
    

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

  • 相关阅读:
    opencv如何载入内存中的图像文件
    C++ 中指针与引用的区别
    2014新版12306接口分析
    Qt 多线程与数据库操作需要注意的几点问题
    设置 Linux 的 LD_LIBRARY_PATH 变量
    linux+Qt程序如何打包发布
    c++(重载、覆盖、隐藏)
    Pytorch中的强化学习
    WordNet简介
    Pytorch中的数学函数
  • 原文地址:https://www.cnblogs.com/adelina-blog/p/10559676.html
Copyright © 2011-2022 走看看