总结这一年在项目中用到频率较多的工具函数

lxf2023-03-10 17:52:01

概述

每个项目必然会用到各种各样的工具函数处理不同的逻辑,我自己总结了我这一年多开发以来,用到的比较普遍的一些工具函数,我个人不太喜欢用loadash,不如自己用到的时候自己封装。

关于表单验证的

以下总结的为组件库中Form组件对应的自定义校验规则函数,本质上也用到了校验工具async-validator,更多的细节,可以去文档看,对于做后台系统的,涉及到大量的表单,表单验证必不可少。

验证手机号

function CheckPhone (rule, value, callback)  {
    let reg = /^1\d{10}$/g;
    if (!reg.test(value)) {
      callback(new Error('手机号格式不正确'));
    } else {
      callback();
    }
  }

验证密码

function  CheckAdminPassword  (rule, value, callback) {
    const reg = /[\u4e00-\u9fa5]|\s+/gm;
    const len = value.length;
    if (value) {
      if (len < 8 || len > 14) {
        callback(new Error('密码必须由字母/数字及标点符号3种组成,且字母需大小写都包含,不得有空格、中文,长度8-14位'));
      }
      if (reg.test(value)) {
        callback(new Error('密码必须由字母/数字及标点符号3种组成,且字母需大小写都包含,不得有空格、中文,长度8-14位'));
      }
      if (!checkPwdCombination(value, 'admin')) {
        callback(new Error('密码须由字母/数字及标点符号3种组成,且字母需大小写都包含,不得有空格、中文,长度8-14位'));
      }
    }

    callback();
  }

验证正整数(包含0)

function  CheckPositiveInteger (rule, value, callback){
    let reg = /^[1-9]\d*$/g;
    // console.log(value)
    if (!reg.test(value) && value !== '') {
      callback(new Error('请输入正整数'));
    } else {
      callback();
    }
  }

验证邮箱

function  CheckEmail (rule, value, callback){
     let reg = /^[A-z0-9_]{3,12}@[A-z0-9]{2,12}(\.com|\.cn|\.com\.cn)$/g;
    if (!reg.test(value) && value !== '') {
      callback('邮箱格式不正确');
    } else {
      callback();
    }
  }

验证价格

function CheckPrice (rule, value, callback)  {
    if (!value && value !== 0) {
      return callback(new Error('该项为必填项'));
    } else if (!parseFloat(value) && parseFloat(value) != 0) {
      return callback(new Error('请输入阿拉伯数字'));
    } else if (value < 0) {
      return callback(new Error('请输入正确的价格'));
    } else {
      callback();
    }
  }

验证年龄

 function CheckAge (rule, value, callback)  {
    let reg = /\D/g;

    if (reg.test(value)) {
      callback(new Error('年龄只能为正整数'));
    } else if (parseInt(value) >= 120 || parseInt(value) < 0) {
      callback(new Error('年龄只能小于120'));
    } else {
      callback();
    }
  }

验证IP地址

function CheckIp (rule, value, callback)  {
    let reg =
      /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
    if (!reg.test(value) && value !== '') {
      callback(new Error('输入正确IP地址'));
    } else {
      callback();
    }
  }

验证域名网址

function CheckWebsite (rule, value, callback) {
    let reg = /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/;
    if (!reg.test(value) && value !== '') {
      callback(new Error('请输入正确的网址'));
    } else {
      callback();
    }
  }

关于功能类的工具函数

主要用于数据转化,性能提升而用的

判断当前是电脑端还是移动端

const checkCurrentDeviceType = function () {
      let ua = navigator.userAgent.toLowerCase();
      let btypeInfo = (ua.match(/firefox|chrome|safari|opera/g) || 'other')[0];
      if ((ua.match(/msie|trident/g) || [])[0]) {
        btypeInfo = 'msie';
      }
      let pc = '';
      let prefix = '';
      let plat = '';
      //如果没有触摸事件 判定为PC
      let isTocuh = 'ontouchstart' in window || ua.indexOf('touch') !== -1 || ua.indexOf('mobile') !== -1;
      if (isTocuh) {
        if (ua.indexOf('ipad') !== -1) {
          pc = 'pad';
        } else if (ua.indexOf('mobile') !== -1) {
          pc = 'mobile';
        } else if (ua.indexOf('android') !== -1) {
          pc = 'androidPad';
        } else {
          pc = 'pc';
        }
      } else {
        pc = 'pc';
      }
      switch (btypeInfo) {
        case 'chrome':
        case 'safari':
        case 'mobile':
          prefix = 'webkit';
          break;
        case 'msie':
          prefix = 'ms';
          break;
        case 'firefox':
          prefix = 'Moz';
          break;
        case 'opera':
          prefix = 'O';
          break;
        default:
          prefix = 'webkit';
          break;
      }
      plat = ua.indexOf('android') > 0 ? 'android' : navigator.platform.toLowerCase();
      return {
        version: (ua.match(/[\s\S]+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1], //版本
        plat: plat, //系统
        type: btypeInfo, //浏览器
        pc: pc,
        prefix: prefix, //前缀
        isMobile: pc == 'pc' ? false : true, //是否是移动端
      };
    };

根据链接地址下载文件

    const dowloadFile = function (url) {
      let a = document.createElement('a');
      a.href = url;
      a.click();
    };

判断起止时间一定要比结束时间小

const isValidTime = function (startTime, endTime)  {
      return new Date(endTime).getTime() > new Date(startTime).getTime();
    };

树形结构数据转化(侧边栏或者权限管理)

 /**
     * @Description 组合接口返回的侧边栏路由为树形结构
     * @param { Array } data 需要处理的数据
     * @return { Array } 组合完成的树形结构
     **/
     
     /**
     转化规则如下:
          const data = [
      {
        parent: 0,
        label: '菜单1',
        id: 1,
      },
      {
        parent: 0,
        label: '菜单2',
        id: 2,
      },
      {
        parent: 0,
        label: '菜单3',
        id: 3,
      },
      {
        parent: 2,
        label: '菜单2-1',
        id: 4,
      },
      {
        parent: 3,
        label: '菜单3-1',
        id: 5,
      },
      {
        parent: 5,
        label: '菜单3-1-1',
        id: 6,
      },
    ];   ===>
    data = [
      {
        parent: 0,
        label: '菜单1',
        id: 1,
      },
      {
        parent: 0,
        label: '菜单2',
        id: 2,
        children:[
          {
            parent: 2,
            label: '菜单2-1',
            id: 4,
          },
        ]
      },
      {
        parent: 0,
        label: '菜单3',
        id: 3,
        children:[
          {
            parent: 3,
            label: '菜单3-1',
            id: 5,
            children:[
              {
                parent: 5,
                label: '菜单3-1-1',
                id: 6,
              },
            ]
          },
        ]
      },
    
    ]; 

     **/
const  getSideMenuListToTree = function (data) {
      data ? (data = data) : (data = []);
      let parent = data.filter(item => item.ParentId == 0); //一级菜单
      let childrens = data.filter(item => item.ParentId != 0); //子级菜单
      function formatToTree(parent, childrens) {
        parent.forEach(x => {
          childrens.forEach(v => {
            if (x.Id == v.ParentId) {
              x.children ? x.children.push(v) : (x.children = [v]);
              formatToTree(x.children, childrens);
            }
          });
        });
      }
      function solveTreeData(parent, list) {
        parent.forEach(item => {
          list.push({
            label: item.Title,
            path: item.Url,
            children: (item.children && item.children.length && solveTreeData(item.children, [])) || [],
          });
        });
        return list;
      }
      formatToTree(parent, childrens);
      let res = solveTreeData(parent, []);
      return res;
    };
    
    

手机号脱敏显示

    /**
     *@Author:
     *@Description: 手机号脱敏处理
     * @param { String }   手机号 155xxxxx447
     * @return { String }   返回脱敏处理的手机号 155***447
     */
   const phoneDesensitizationTreatment = (phone)  {
      return phone.replace(/(\d{3})(\d{4})(\d{4})/, (str, $1, $2, $3) => {
        return $1 + '****' + $3;
      });
    };

节流函数

    /**
     *@Author:
     *@Description: 节流函数
     * @param { Function }   fn 需要节流函数
     * @param { Number }   wait 间隔时间差
     * @param { Function }   callback  此回调函数用于获取函数返回值
     */
   const throw = function (fn, wait, callback)  {
      let initTime = 0;
      return function () {
        let nowTime = Date.now();
        if ((nowTime = initTime >= wait)) {
          let res = fn.apply(this, [...arguments]);
          if (typeof callback == 'function') callback(res);
          initTime = nowTime;
        }
      };
    };

防抖函数

    /**
     *@Description: 防抖函数(简化版,项目需求够用了,也不是写啥子库,业务简单防抖就行,不需要花里胡哨的)
     * @param { Function }   fn 需要防抖的函数
     * @param { Number }   wait 间隔时间差
     * @param { Boolean }   immediate 是否开始立即执行
     * @param { Function }   callback  此回调函数用于获取函数返回值
     */
   const debounce = function (fn, wait, immediate = false, callback)  {
      let timer = null;
      let ivoke = false;
      return function () {
        if (timer) clearTimeout(timer);
        if (immediate && !ivoke) {
          let res = fn.apply(this, [...arguments]);
          if (typeof callback == 'function') callback(res);
          ivoke = true;
        } else {
          timer = setTimeout(() => {
            let res = fn.apply(this, [...arguments]);
            if (typeof callback == 'function') callback(res);
            ivoke = true;
          }, wait);
        }
      };
    };

是生成浏览器设备标识

需要借助指纹库:Fingerprint2

//根据当前浏览器生成一个字符串标识当前主机 
 const getBrowerDeviceIdentificationId = async function () {
      return new Promise(async (resolve, reject) => {
        const fp = await Fingerprint2.load();
        const result = await fp.get();
        const visitorId = result.visitorId;
        resolve(visitorId);
      });
    };

删除对象中的空值(根据需要可递归

  // 删除对象中的空字段
   const deleteKey = function o(bj) {
      for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
          const element = obj[key];
          if (element !== 0 && !element && typeof element !== 'boolean') {
            delete obj[key];
          }
        }
      }
      return obj;
    };

时间转化

需要借助时间转化插件:moment.js

const transformDate = function (val, type)  {
      switch (type) {
        case 1:
          return moment(val).format('YYYY/MM/DD');
        case 2:
          return moment(val).format('YYYY-M-D');
        case 3:
          return moment(val).format('YYYY年M月');
        case 4:
          return moment(val).format('YYYY-MM-DD HH:mm');
        case 5:
          return moment(val).format('YYYY-MM-DD');
        case 6:
          return moment(val).format('YYYY年MM月DD日');
        case 7:
          return moment(val).fromNow(); //几天前/几年前/几秒前的格式
        case 8:
          return moment(val).format('YYYY/MM/DD HH:mm');
        case 9:
          return Math.floor((moment(val) - moment()) / 3600000); //时间相减剩余小时(主要用于设置过期时间)
      }
    };

总结

后面会不断追加在项目中常用的一些工具函数,这里记录下,不然每次从头写还是很麻烦的