JavaScript的工具函数

工具函数

罗马数字和整数互换

export const intToRomanData = {
    1: 'I',
    5: 'V',
    10: 'X',
    50: 'L',
    100: 'C',
    500: 'D',
    1000: 'M'
}
export const romanToIntData = {
    'I': 1,
    'V': 5,
    'X': 10,
    'L': 50,
    'C': 100,
    'D': 500,
    'M': 1000
}
/**
 * 罗马数字和整数互换
 * @param {*} v 
 */
export const intInterconversionRoman = (v)=>{
    let result = 0
    let index = 0
    if(typeof(v)==='string'){
        const len = v.length
        while (index < len) {
            let current = romanToIntData[v[index]]
            result += current
            if (index > 0) {
                let before = romanToIntData[v[index - 1]]
                if ((current === 5 || current === 10) && before === 1) {
                    result -= 2
                }
                if ((current === 50 || current === 100) && before === 10) {
                    result -= 20
                }
                if ((current === 500 || current === 1000) && before === 100) {
                    result -= 200
                }
            }
            index++
        }
    }else if(typeof(v)==='number'){
        index = 1
        result = ''
        while (v) {
            let current = v % 10
            if (current < 4) {
                result = intToRomanData[index].repeat(current) + result
            } else if (current === 4) {
                result = intToRomanData[index] + intToRomanData[index * 5] + result
            } else if (current > 4 && current < 9) {
                result = intToRomanData[index * 5] + intToRomanData[index].repeat(current - 5) + result
            } else {
                result = intToRomanData[index] + intToRomanData[index * 10] + result
            }
            index *= 10
            v = Math.trunc(v / 10)
        }
    }else{
        return new Error('传参类型错误')
    }
    return result
}

格式化时间

/**
 * 格式化时间
 * @param {*} fmt 
 * @param {*} dateString 
 * @returns 
 */
export const fmtDate = function (fmt, dateString) {

    const date = new Date(dateString);

    let ret;
    const opt = {
        "Y+": date.getFullYear().toString(), // 年
        "m+": (date.getMonth() + 1).toString(), // 月
        "d+": date.getDate().toString(), // 日
        "H+": date.getHours().toString(), // 时
        "M+": date.getMinutes().toString(), // 分
        "S+": date.getSeconds().toString() // 秒
        // 有其他格式化字符需求可以继续添加,必须转化成字符串
    };
    for (let k in opt) {
        ret = new RegExp("(" + k + ")").exec(fmt);
        if (ret) {
            fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
        };
    };
    return fmt;
}

浏览器刷新提示

/**
 * 浏览器刷新提示框
 * @param {vue实例} that
 * @param {路由} route 
 */
export const beforeUnloadFunc = (that, route) => {
    window.onbeforeunload = function (e) {
        if (that.$route.fullPath == route) { // 注意这里要替换成自己的当前页面的路由
            e = e || window.event;
            // 兼容IE8和Firefox 4之前的版本
            if (e) {
                e.returnValue = '关闭提示';
            }
            // Chrome, Safari, Firefox 4+, Opera 12+ , IE 9+
            return '关闭提示';
        } else {
            window.onbeforeunload = null
        }
    };
}

深拷贝

/**
 * 深拷贝
 * @param {*} source 
 * @returns 
 */
export const deepClone = (source) => {

    // if(obj instanceof null) return null;

    // if(obj instanceof Date) return new Date(Obj);

    // if(obj instanceof RegExp) return new RegExp(obj);

    if (!source) throw new Error('error arguments', 'deepClone')

    if (typeof source !== 'object') return source;

    const targetObj = source.constructor === Array ? [] : {}
    Object.keys(source).forEach(keys => {
        if (source[keys] && typeof source[keys] === 'object') {
            targetObj[keys] = deepClone(source[keys])
        } else {
            targetObj[keys] = source[keys]
        }
    })
    return targetObj

}

前端简单搜索

/**
 * 前端搜索
 * @param {数组} arr 
 * @param {搜索关键字符串} search 
 * @param {数组对比字符串} str 
 * @returns 
 */
export const strFilterArr = (arr, search, reg) => {
    //  const REG = new RegExp(this.title, "i");
    const newArr = []
    arr.filter((item) => {
        if (item[reg].includes(search)) {
            newArr.push(item);
        }
    });
    return newArr
}

一二级cookie操作

// 获取cookie
export const getCookie = (name) => {
    name += '='
    let cookie = document.cookie.split(';')
    for (let i = 0; i < cookie.length; i++) {
        let c = cookie[i].trim();
        if (c.indexOf(name) == 0) {
            return c.substring(name.length, c.length);
        }
    }
    return "";
}
 //清空cookie
export const clearCookie = () => {
   
    const keys = document.cookie.match(/[^ =;]+(?=\=)/g);
    if (keys) {
        for (let i = keys.length; i--;) {
            document.cookie = keys[i] + '=0;path=/;expires=' + new Date(0).toUTCString(); //清除当前域名下的,例如:m.kevis.com
            document.cookie = keys[i] + '=0;path=/;domain=' + document.domain + ';expires=' + new Date(0).toUTCString(); //清除当前域名下的,例如 .m.xxx.com
            document.cookie = keys[i] + '=0;path=/;domain=kevis.com;expires=' + new Date(0).toUTCString(); //清除一级域名下的或指定的,例如 .xx.com
        }
    }

}

判断浏览器


export const browserName = () => {
// 判断浏览器
    if (window.ActiveXObject) {
        return 'ie'
    } else if (document.getBoxObjectFor) { //只有火狐有
        return 'firefox'
    } else if (window.MessageEvent && !document.getBoxObjectFor) {
        return 'chrome'
    } else if (window.opera) {
        return 'opera'
    } else if (window.openDatebase) {
        return 'safair'
    } else {
        return 'no'
    }
}

中文转首字母

/**
 * 中文转首字母
 */
import https://download.csdn.net/download/weixin_49884775/87352808
export const PinYin = class {
  chineseToPinYin(l1) {
    let l2 = l1.length
    let I1 = ''
    let reg = new RegExp('[a-zA-Z0-9]')
    for (let i = 0; i < l2; i++) {
      let val = l1.substr(i, 1)
      let name = this.arraySearch(val)
      if (reg.test(val)) {
        I1 += val
      } else if (name !== false) {
        I1 += name
      }
    }
    I1 = I1.replace(/ /g, '-')
    while (I1.indexOf('--') > 0) {
      I1 = I1.replace('--', '-')
    }
    return I1[0].toUpperCase()
  }

  arraySearch(l1) {
    for (let name in pinyin) {
      if (pinyin[name].indexOf(l1) !== -1) {
        return this.ucfirst(name)
      }
    }
    return false
  }
  ucfirst(l1) {
    if (l1.length > 0) {
      let first = l1.substr(0, 1).toUpperCase()
      let spare = l1.substr(1, l1.length)
      return first + spare
    }
  }
}


计算数组重复次数

/**
 * 计算数组重复次数
 */
 export const countOccurrences = (arr, val) =>
 arr.reduce((a, v) => (v === val ? a + 1 : a), 0)

base64 blod file互换

/**
 * 将base64转换为blob
 * @param {*} dataurl 
 * @returns 
 */
export const dataURLtoBlob = function (dataurl) {
    let arr = dataurl.split(',')
    let mime = arr[0].match(/:(.*?);/)[1]
    let bstr = atob(arr[1])
    let n = bstr.length
    let u8arr = new Uint8Array(n)
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new Blob([u8arr], {
        type: mime
    });
}
/**
 * 将blob转换为file
 * @param {*} theBlob 
 * @returns 
 */
export const blobToFile = function (theBlob, fileName = 'huxingtu.png') {
    theBlob.lastModifiedDate = new Date();
    theBlob.name = fileName;
    return theBlob;
}
/**
 * 将base64转换为file
 * @param {*} dataurl
 * @returns 
 */
export const dataURItoFile = function (dataurl, name = 'huxing') {
    let arr = dataurl.split(',')
    let mime = arr[0].match(/:(.*?);/)[1]
    let suffix = mime.split('/')[1];
    let bstr = atob(arr[1])
    let n = bstr.length
    let u8arr = new Uint8Array(n)
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
    }
    return new File([u8arr], `${name}.${suffix}`, {
        type: mime,
    })
}

localstore有效期

/*
* localstore添加有效期
*/
export const selfStorage = () => {
  // 存值函数
  Storage.prototype.setCanExpireLocal = (key, value, expire) => {
    // 接收三个参数:键、值、有效分钟数
    // 判断传入的有效期是否为数值或有效
    // isNaN是js的内置函数,用于判断一个值是否为NaN(非数值),
    // 非数值返回true,数值返回false
    if (isNaN(expire) || expire < 1) {
      throw new Error('有效期应为一个有效数值')
    }
    // 60000 是1分钟时间的毫秒数,
    let time = expire * 60000
    let obj = {
      data: value, //存储值
      time: Date.now(), //存值时间戳
      expire: time, //过期时间
    }
    // 注意,localStorage不能直接存储对象类型,sessionStorage也一样
    // 需要先用JSON.stringify()将其转换成字符串,取值时再通过JSON.parse()转换回来
    localStorage.setItem(key, JSON.stringify(obj))
  }

  // 取值函数
  // 接收一个参数,存值的键										
  Storage.prototype.getCanExpireLocal = key => {
    let val = localStorage.getItem(key)
    // 如果没有值就直接返回null
    if (!val) return val
    // 存的时候转换成了字符串,现在转回来
    val = JSON.parse(val)
    // 存值时间戳 +  有效时间 = 过期时间戳
    // 如果当前时间戳大于过期时间戳说明过期了,删除值并返回提示
    if (Date.now() > val.time + val.expire) {
      localStorage.removeItem(key)
      return null
    }
    return val.data
  }
}

自定义指令

复制

/**使用 <el-button class="borra" type="primary" v-click-copy="aaa">复制</el-button>*/
import { Message } from 'element-ui'


// 处理传过来的参数
const handleParams = (el,value) => {
  if(Object.prototype.toString.call(value) === '[object Object]'){
    el.$value = value.value
    el.$offset = value.offset
  }else{
    el.$value = value
    el.$offset = 20
  }
}

export default {
  bind(el, { value }) {
    console.log('copy value', value.value)
    handleParams(el,value);
    el.clickHandler = () => {
      if (!el.$value) {
        console.log('无复制内容')
        return
      }
      let input = document.createElement('input')
      input.value = el.$value
      input.readOnly = 'readOnly'
      input.style.position = 'absoulte'
      input.style.zIndex = '-9999px'
      document.body.appendChild(input)
      input.select()
      let result = document.execCommand('copy')
      if (result) {
        Message({
          message: '复制成功',
          type: 'success',
          offset: el.$offset
        })
        document.body.removeChild(input)
      }
    }
    el.addEventListener('click', el.clickHandler)
  },
  componentUpdated(el, { value }) {
    handleParams(el,value);
  },
  unbind(el) {
    el.removeEventListener('click', el.clickHandler)
  }
}

懒加载

/**
 * 使用<img v-imgLazy data-src="https://a.com/图1.png" src="" alt=""  />
 * @description 图片懒加载指令
 */
function hanldeImgLoad(entries) {
  entries.forEach(v => v.isIntersecting && v.target.setAttribute('src', v.target.getAttribute('data-src')));
}

//判断元素是否在可视区域
function isViewport(el) {
  const viewWidth = window.innerWidth || document.documentElement.clientWidth;
  const viewHeight = window.innerHeight || document.documentElement.clientHeight;
  let {
    top,
    left,
    right,
    bottom,
    width,
    height
  } = el.getBoundingClientRect();
  return top >= 0 && left >= 0 && right + width <= viewWidth && bottom + height <= viewHeight;
}

//threshold设置元素位于界面可视化区域的比例,0~1,1(完全位于可视化区域)
const observe = new IntersectionObserver(hanldeImgLoad, {
  threshold: 0.6
});
export default {
  bind(el) {
    observe.observe(el);
  },
  componentUpdated(el) {
    isViewport(el) && (el.src = el.getAttribute('data-src'));
  },
  unbind(el) {
    observe.unobserve(el);
  },
};

防抖

/** 使用 <el-input v-debounce-input="formItem.inputEvent"></el-input>*/
export default {
  //bind解构出value  node解构出data
  bind: (el, { value }, { data }) => {
    let awaitTime = 0
    if (!Number.isNaN(+data.attrs['debounce-second'])) {
      awaitTime = +data.attrs['debounce-second'] * 1000
    } else {
      console.error('debounce-second type is number or string digit')
    }
    // console.log("debounce-input awaitTime", awaitTime);
    el.handleInput = function(val) {
      if (el.timer) {
        clearTimeout(el.timer)
      }
      el.timer = setTimeout(() => {
        value(val)
      }, awaitTime || 500)
    }
    el.addEventListener('input', el.handleInput)
  },
  unbind: el => {
    el.timer && clearTimeout(el.timer)
    el && el.removeEventListener('input', el.handleInput)
  }
}

自动加载文件

let list = []
//directory {String} -读取文件的路径
//useSubdirectories {Boolean} -是否遍历文件的子目录
//regExp {RegExp} -匹配文件的正则
const requireDirective = require.context('.', false, /\.js$/)
//提供三个接口
//webpackContext 加载文件的接口  调用加载文件__webpack_require__再调用webpackContextResolve
//webpackContext.resolve = webpackContextResolve  根据相对路径去找到绝对路径名接口
//webpackContext.keys = function(){ } 从map取出所有的相对路径接口
console.log('requireDirective', requireDirective)
requireDirective.keys().map((fileName, i) => {
  console.log('fileName', fileName, i)
  if (!fileName.includes('index.js')) {
    const directiveConfig = requireDirective(fileName)
    list.push({ fn: directiveConfig, name: fileName.slice(2).slice(0, -3) })
    console.log('directiveConfig', directiveConfig)
  }
})
export default {
  install(Vue) {
    console.log('install', list)
    list.map(item => {
      Vue.directive(item.name, item.fn.default || item.fn)
    })
    // Vue.directive('limit-input-number', LimitInputNumber)
    // Vue.directive('debounce-input', debounceInput)
  }
}

加密

import jsencrypt from 'jsencrypt';

function rsaUtil(data) {
    let Je = new jsencrypt({
        default_key_size: 1024
    })
    Je.setPublicKey('aaaaaa')
    if (data instanceof Object) {
        data = JSON.stringify(data);
    }
    return Je.encrypt(data);
}
export default rsaUtil;

水印

export default function __canvasWM({
  // 使用 ES6 的函数默认值方式设置参数的默认取值
  container = document.body,
  width = '100vw',
  height = '120%',
  textAlign = 'center',
  textBaseline = 'middle',
  font = "800 15px Microsoft Yahei",
  fillStyle = 'rgba(184, 184, 184, 0.5)',
  content = '请勿外传',
  rotate = '60',
  zIndex = 1000
} = {}) {
  const args = arguments[0];
  console.log(args);
  const canvas = document.createElement('canvas');
  canvas.setAttribute('width', width);
  canvas.setAttribute('height', height);
  const ctx = canvas.getContext("2d");
  ctx.textAlign = textAlign;
  // ctx.textBaseline = textBaseline;
  ctx.font = font;
  ctx.fillStyle = fillStyle;
  ctx.rotate(Math.PI / 360 * rotate);
  ctx.fillText(content, parseFloat(width) / 2, parseFloat(height) / 15,80);
  const base64Url = canvas.toDataURL();
  const __wm = document.querySelector('.__wm');
  const watermarkDiv = __wm || document.createElement("div");
  const styleStr = `
    position:absolute;
    top:1rem;
    left:200px;
    width:calc(100% - 200px);
    height:calc(100% - 1rem);
    z-index:${zIndex};
    pointer-events:none;
    background-image:url('${base64Url}')`;
  watermarkDiv.setAttribute('style', styleStr);
  watermarkDiv.classList.add('__wm');
  if (!__wm) {
    container.style.position = 'relative';
    container.insertBefore(watermarkDiv, container.firstChild);
  }
  const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
  if (MutationObserver) {
    let mo = new MutationObserver(function () {
      const __wm = document.querySelector('.__wm');
      // 只在__wm元素变动才重新调用 __canvasWM
      if ((__wm && __wm.getAttribute('style') !== styleStr) || !__wm) {
        // 避免一直触发
        mo.disconnect();
        mo = null;
      __canvasWM(JSON.parse(JSON.stringify(args)));
      }
    });

    mo.observe(container, {
      attributes: true,
      subtree: true,
      childList: true
    })
  }
}

自适应

export const fun = function (doc, win) {
  const docEl = doc.documentElement
  const resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize'
  const recalc = function () {
    const clientWidth = docEl.clientWidth;
    if (!clientWidth) return;

    //这里是假设在1920px宽度设计稿的情况下,1rem = 20px;
    //可以根据实际需要修改
    docEl.style.fontSize = 100 * (clientWidth / 1920) + 'px';
    // docEl.style.fontSize = 100 * (clientWidth / 1440) + 'px';
  };
  if (!doc.addEventListener) return;
  win.addEventListener(resizeEvt, recalc, false);
  doc.addEventListener('DOMContentLoaded', recalc, false);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值