写点什么

让你事半功倍的 JS utils 工具函数

作者:南城FE
  • 2022 年 7 月 20 日
  • 本文字数:7489 字

    阅读完需:约 25 分钟

今日分享一篇积累和收集了很久的 JS utils 工具函数,文章代码量较多,建议收藏起来慢慢看,当哪一天需要用到的时候,打开你尘封已久的收藏夹,相信能让你的业务代码开发事半功倍。


汇集了时间相关,DOM 相关,URL 相关,判断相关,图片相关,缓存相关等。部分逻辑处理较为简单,如果是业务量较为复杂的情况建议要斟酌使用,但对于大部分的项目应该是绰绰有余。接下来就进入代码部分吧~

时间相关

时间戳转自定义格式时间

export const dateRegExp = (time, strText) => {  const date = new Date(time)  if (/(y+)/.test(strText)) {    strText = strText.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))  }  const dataType = {    'M+': date.getMonth() + 1,    'd+': date.getDate(),    'h+': date.getHours(),    'm+': date.getMinutes(),    's+': date.getSeconds()  }  for (const typeKey in dataType) {    if (new RegExp(`(${typeKey})`).test(strText)) {      const typeValue = dataType[typeKey] + ''      strText = strText.replace(RegExp.$1, (RegExp.$1.length === 1 ? typeValue : padLeftZero(typeValue)))    }  }  return strText}
复制代码

格式化距离现在已过去的时间

export function formatPassTime(startTime) {    var currentTime = Date.parse(new Date()),        time = currentTime - startTime,        day = parseInt(time / (1000 * 60 * 60 * 24)),        hour = parseInt(time / (1000 * 60 * 60)),        min = parseInt(time / (1000 * 60)),        month = parseInt(day / 30),        year = parseInt(month / 12);    if (year) return year + "年前"    if (month) return month + "个月前"    if (day) return day + "天前"    if (hour) return hour + "小时前"    if (min) return min + "分钟前"    else return '刚刚'}
复制代码

判断两个不同格式的日期是否为同一天

export function isSameDay(d1, d2) {    if (!d2) {        d2 = new Date();    }    var d1_year = d1.getFullYear(),        d1_month = d1.getMonth() + 1,        d1_date = d1.getDate();    var d2_year = d2.getFullYear(),        d2_month = d2.getMonth() + 1,        d2_date = d2.getDate()
return d1_date === d2_date && d1_month === d2_month && d1_year === d2_year;}
复制代码

判断时间是不是今天

export function isTodayDate(time) {    if (new Date(time).toDateString() === new Date().toDateString()) {        return true;    }    return false;}
复制代码

URL 相关

URL 参数转对象

export function parseQueryString(url) {    url = url ? url:window.location.search ;    let search = url[0] === '?' ? url : url.substring(url.lastIndexOf('?'));     let q = {};    search.replace(/([^?&=]+)=([^&]+)/g, (_, k, v) => q[k] = decodeURIComponent(v));    return q;}
复制代码

获取 URL 参数

export function getQueryString(name) {  const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')  const r = window.location.search.substr(1).match(reg)  if (r !== null) {    return decodeURI(r[2])  }  return null}
复制代码

获取 URL hash 后面的参数

export getHashQueryString = (key) => {  const after = window.location.href.split('?')[1]  if (after) {    const reg = new RegExp(`(^|&)${  key  }=([^&]*)(&|$)`)    const r = after.match(reg)    if (r != null) {      return decodeURIComponent(r[2])    }    return null  }  return null}
复制代码

对象序列化

export function serialize(query, encode = false) {  return Object.keys(query)    .map((key) => `${key}=${encode ? encodeURIComponent(query[key]) : query[key]}`)    .join('&')}
复制代码

判断相关

判断是否支持 Intersection

export function isSupportIntersection() {  return (    'IntersectionObserver' in window &&    'IntersectionObserverEntry' in window &&    'intersectionRatio' in window.IntersectionObserverEntry.prototype  )}
复制代码

判断是否 IOS

export const isIOS = (() => {  return /ios|iphone|ipad|ipod/.test(navigator.userAgent.toLowerCase())})()
复制代码

判断是否安卓

export const isAndroid = (() {  return /android/.test(navigator.userAgent.toLowerCase())})()
复制代码

判断微信内置浏览器

export function isWeixin() {  var ua = navigator.userAgent.toLowerCase();  return (ua.match(/MicroMessenger/i) == "micromessenger")}
复制代码

判断是否支持 webp 格式 2 种方式

export function checkSupportWebp() {  return (    document      .createElement('canvas')      .toDataURL('image/webp')      .indexOf('data:image/webp') === 0  )}export function checkSupportWebp2() {  var img = new Image();  img.onload = img.onerror = (event) => {    return event && event.type === "load" ? img.width == 1 : false;  };  img.src = "data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAwA0JaQAA3AA/vuUAAA=";}
复制代码

判断浏览器是否是移动端

export function isMobile() {    const agent = navigator.userAgent;    const k = ["android", "iphone", "ipod", "ipad", "windows phone", "mqqbrowser"];    let flag = false;    // Windows    if (agent.indexOf("Windows NT") < 0 || (agent.indexOf("Windows NT") >= 0 && agent.indexOf("compatible; MSIE 9.0;") >= 0)) {        // Mac PC        if (agent.indexOf("Windows NT") < 0 && agent.indexOf("Macintosh") < 0) {            for (let item of k) {                if (agent.indexOf(item) >= 0) {                    flag = true;                    break;                }            }        }    }    return flag;}
复制代码

文件类型判断


export function checkFileName(fileName, list) { if (typeof fileName !== 'string') return; let name = fileName.toLowerCase(); return list.some(i => name.endsWith(`.${i}`) === true)}
export function isImage(fileName) { return checkFileName(fileName, ['png', 'jpeg', 'jpg', 'png', 'bmp'])}
export function isH5Video(fileName) { return checkFileName(fileName, ['mp4', 'webm', 'ogg'])}export function isPdf(fileName) { return checkFileName(fileName, ['pdf'])}
export function isWord(fileName) { return checkFileName(fileName, ['doc', 'docx'])}
export function isExcel(fileName) { return checkFileName(fileName, ['xlsx', 'xls'])}
复制代码

数据类型判断

export function is(subject, type) {  return Object.prototype.toString.call(subject).substr(8, type.length).toLowerCase() === type}export function isArray(subject) {  return Array.isArray(subject)}export function isObject(subject) {  return is(subject, 'object')}
...
export function isNum(subject) { return !isNaN(subject) && is(subject, 'number')}
复制代码

DOM 相关

查询元素是否存在某个 class

export function hasClass(el, className) {  let reg = new RegExp('(^|\\s)' + className + '(\\s|$)');  return reg.test(el.className);}
复制代码

给某个元素添加 class

export function addClass(el, className) {  if (hasClass(el, className)) {    return;  }  let curClass = el.className.split(' ');  curClass.push(className);  el.className = curClass.join(' ');}
复制代码

删除某个元素的 class

export function removeClass(el, className) {  if (!hasClass(el, className)) {    return;  }
let reg = new RegExp('(^|\\s)' + className + '(\\s|$)', 'g'); el.className = el.className.replace(reg, ' ');}
复制代码

获取页面滚动距离

export function getScrollTop() {  let e = 0  return (    document.documentElement && document.documentElement.scrollTop      ? (e = document.documentElement.scrollTop)      : document.body && (e = document.body.scrollTop),    e  )}
复制代码

滚动到某个位置回调

export function distanceScroll(distance, callback) {  const scrollTop = document.body.scrollTop || document.documentElement.scrollTop  const docHeight = document.body.clientHeight  const screenHeight = window.screen.availHeight  const differ = scrollTop > docHeight - screenHeight - distance  if (differ) {    callback && callback()  }}
复制代码

拨打电话

export const callPhone = (phone) => {  const aElement = document.createElement('a')  aElement.setAttribute('href', `tel:${phone}`)  document.body.appendChild(aElement)  aElement.click()  document.body.removeChild(aElement)}
复制代码

复制文本

export function copy(value, callback) {  if (!document.queryCommandSupported('copy')) {    callback('暂不支持复制')    return  }  const textarea = document.createElement('textarea')  textarea.value = value  textarea.readOnly = Boolean('readOnly')  document.body.appendChild(textarea)  textarea.select()  textarea.setSelectionRange(0, value.length)  document.execCommand('copy')  textarea.remove()  callback('复制成功')}
复制代码

动态加载第三方 js

export function asyncLoadScript(url) {  return new Promise(function (resolve, reject) {    const tag = document.getElementsByTagName('script')    for (const i of tag) {      if (i.src === url) {        resolve()        return      }    }    const script = document.createElement('script')    script.type = 'text/javascript'    script.src = url    script.onerror = reject    document.body.appendChild(script)    script.onload = () => {      resolve()    }  })}
复制代码

解决 requestAnimationFrame 的兼容问题

export function requestAnimationFrame() {  return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || function (callback) {    return setTimeout(callback, (callback.interval || (100 / 60) / 2);  };}()
复制代码

动态创建 form 表单导出数据(POST)

const postExport = (url, data = {}) => {  const form = document.createElement("form");  form.style.display = "none";  form.action = `${Config.baseURL}${url}`;  form.method = "post";  document.body.appendChild(form);  // 动态创建input并给value赋值  for (const key in data) {    const input = document.createElement("input");    input.type = "hidden";    input.name = key;    input.value = data[key];    form.appendChild(input);  }  form.submit();  form.remove();}
复制代码

图片相关

base64 转 Buffer

export function dataURItoBuffer(dataURI) {  var byteString = atob(dataURI.split(',')[1]);  var buffer = new ArrayBuffer(byteString.length);  var view = new Uint8Array(buffer);
for (var i = 0; i < byteString.length; i++) { view[i] = byteString.charCodeAt(i); }
return buffer;}
复制代码

base64 转 Blob

export function dataURItoBlob(dataURI) {  var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];  var buffer = dataURItoBuffer(dataURI);  return new Blob([buffer], {    type: mimeString  });}
复制代码

调整拍照图片方向

export function orientationHelper(canvas, ctx, orientation) {  var w = canvas.width;  var h = canvas.height;
if (orientation > 4) { canvas.width = h; canvas.height = w; }
switch (orientation) { case 2: ctx.translate(w, 0); ctx.scale(-1, 1); break;
case 3: ctx.translate(w, h); ctx.rotate(Math.PI); break;
case 4: ctx.translate(0, h); ctx.scale(1, -1); break;
case 5: ctx.rotate(0.5 * Math.PI); ctx.scale(1, -1); break;
case 6: ctx.rotate(0.5 * Math.PI); ctx.translate(0, -h); break;
case 7: ctx.rotate(0.5 * Math.PI); ctx.translate(w, -h); ctx.scale(-1, 1); break;
case 8: ctx.rotate(-0.5 * Math.PI); ctx.translate(-w, 0); break; }}
复制代码

缓存相关

获取指定 Cookie 值

export const getCookie = (k) => {  const res = RegExp('(^|; )' + encodeURIComponent(k) + '=([^;]*)').exec(document.cookie)  return res && res[2]}
复制代码

设置 Cookie 值

export function setCookie(name, value, expriesDays, encode = false) {  var Days = expriesDays || 10  var exp = new Date()  exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000)  const val = encode ? escape(value) : value  document.cookie = name + '=' + val + ';domain=zhuanzhuan.com;path=/;expires=' + exp.toUTCString()}
复制代码

简易版 Storage 操作,sessionStorage 及 localStorage 类似

const prefix = '_XXX_'export function getStorage(key) {  const content = sessionStorage.getItem(`${prefix}${key}`)  if (content) {    try {      const params = JSON.parse(content)      const expires = params.expires      // 未设置过期 及 未过期      if (!expires || (expires && Date.now() <= expires)) {        return params.data      }    } catch (e) {      console.log(e)    }  }}
export function setStorage(key, data = {}, expires) { try { const params = { data } if (expires) { params.expires = expires } sessionStorage.setItem(`${prefix}${key}`, JSON.stringify(params)) } catch (e) { console.log(e) }}
复制代码

数字相关

数字四舍五入,保留 n 位小数

export function round(number, n) {    n = n ? parseInt(n) : 0    if (n <= 0) return Math.round(number)    number = Math.round(number * Math.pow(10, n)) / Math.pow(10, n)    return number}
复制代码

数字每千位加逗号

export function toThousands(num) {  return num && num.toString()    .replace(/\d+/, function(s){         return s.replace(/(\d)(?=(\d{3})+$)/g, '$1,')     })}
复制代码

随机数

export function random(min, max) {  return Math.floor(Math.random() * (max - min + 1) + min)}
复制代码

字符串相关

手机号码中间 4 位隐藏星号

export function hideMobile(mobile) {  return mobile.replace(/^(\d{3})\d{4}(\d{4})$/, "$1****$2")}
复制代码

检测密码强度 1:密码弱 2:密码中等 3:密码强 4:密码很强

export function checkPassWord(str) {    let level = 0;    if (str.length < 6) {        return level    };    if (/[0-9]/.test(str)) {        level++    };    if (/[a-z]/.test(str)) {        level++    };    if (/[A-Z]/.test(str)) {        level++    };    if(/\W/.test(str)){        level++    }    return level}
复制代码

随机产生某个颜色

export function randomColor() {  return `rgb(${this.random(0, 255)}, ${this.random(0, 255)}, ${this.random(0, 255)})`}
复制代码

字符串替换全部

export function replaceAll(s0, s1, s2){  return s0.replace(new RegExp(s1, "gm"), s2);}
复制代码

版本号比较

传入两个版本号,格式如:4.3.2,返回结果,小于-1,等于 0,大于 1。


export function compareVersion(v1, v2) {  var s1 = v1.split(".").map(v => parseInt(v));  var s2 = v2.split(".").map(v => parseInt(v));
var len1 = s1.length, len2 = s2.length, commonLen = Math.min(len1, len2); for (var i = 0; i < commonLen; ++i) { if (seq1[i] != seq2[i]) return seq1[i]<seq2[i] ? -1 : 1; }
return len1 === len2 ? 0 : (len1 < len2 ? -1 : 1);}
复制代码

对象转 url 字符串供导出接口(GET)使用

const objectToQueryString = (paramObj) => {  const tmpArray = []  // 特殊字符转义  const filter = (str) => {    str += '' // 隐式转换    str = str.replace(/%/g, '%25')    str = str.replace(/\+/g, '%2B')    str = str.replace(/ /g, '%20')    str = str.replace(/\//g, '%2F')    str = str.replace(/\?/g, '%3F')    str = str.replace(/&/g, '%26')    str = str.replace(/\=/g, '%3D')    str = str.replace(/#/g, '%23')    return str  }  for (const attr in paramObj) {    tmpArray.push(`${attr}=${filter(paramObj[attr])}`)  }  return tmpArray.join('&')}
复制代码

其他

函数防抖

export function debounce(fn, delay) {  delay = delay || 1000;  let timer = null;  return function () {    let context = this;    let arg = arguments;    if (timer) {      clearTimeout(timer);    }    timer = setTimeout(() => {      fn.apply(context, arg);    }, delay);  };}
复制代码

节流函数

export function throttle(fn, delay = 300) {  let timer = null;  return function () {    let context = this;    let args = arguments;    if (!timer) {      timer = setTimeout(function () {        fn.apply(context, args);        clearTimeout(timer);      }, delay);    }  };}
复制代码

最后

除开本文所示的场景,也还有很多没有列举到的情况,如果你有认为很不错的工具函数,欢迎留言交流~


专注前端开发,分享前端相关技术干货,公众号:南城大前端(ID: nanchengfe)

发布于: 刚刚阅读数: 3
用户头像

南城FE

关注

还未添加个人签名 2019.02.12 加入

专注前端开发,分享前端知识

评论

发布
暂无评论
让你事半功倍的JS utils工具函数_JavaScript_南城FE_InfoQ写作社区