Vue 工具函数封装

这是一个包含多种JavaScript实用工具函数的模块,如数组去重、生成GUID、HTML转义和反转义、获取DOM样式、节流和防抖函数、数组操作、对象数组处理、树结构转换等。这些函数旨在提高开发效率,简化常见的编程任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、函数

1.通用函数 common/utils.js

记录一些工作中常用的方法,方便以后开发的查阅

 一、函数

1.通用函数 common/utils.js

/**
 * 去除指定属性
 * @name unique
 * @prama attr 去重的属性
 * @return 去重后的数组
 */
export function unique (arr, attr) {
  const res = new Map()
  const fArr = arr.filter((a) => !res.has(a[attr]) && res.set(a[attr], 1))
  console.log('对象数组根据某个属性去重', fArr)
  return fArr.filter(a => a[attr] && a[attr] !== 'undefined')
}

/**
 * 生成guid
 * @name guid
 */
export function guid () {
  return `${S4()}-${S4()}-${S4()}-${S4()}`
}

/**
 * HTML 转译
 * @name htmlEscape
 * @param {String} html 需要反转译的html
 * @return {String} 返回反转译后的html
 */
export const htmlEscape = (html) => {
  if (!html) return ''
  return html.replace(/[<>"&]/g, function (match, pos, originalText) {
    switch (match) {
      case '<':
        return '&lt;'
      case '>':
        return '&gt;'
      case '&':
        return '&amp;'
      case '"':
        return '&quot;'
    }
  })
}

/**
 * HTML 反转译
 * @name htmlEscapeBack
 * @param {String} html 需要转译的html
 * @return {String} 返回转译后的html
*/
export const htmlEscapeBack = (html) => {
  const reg = /(&lt;)|(&gt;)|(&amp;)|(&quot;)/g
  if (!html) return html
  return html.replace(reg, function (match) {
    switch (match) {
      case '&lt;':
        return '<'
      case '&gt;':
        return '>'
      case '&amp;':
        return '&'
      case '&quot;':
        return '"'
    }
  })
}

/**
 * 获取dom节点样式
 * @name getStyle
 * @param {*} obj dom元素
 * @param {*} name 样式树形名称
 */
export function getStyle (obj, name) {
  return window.getComputedStyle ? getComputedStyle(obj, null)[name] : obj.currentStyle[name]
}

/**
 * 节流函数
 * @name throttle
 * @param {*} fn 执行函数
 * @param {*} delay 延迟时间
 */
export const throttle = (fn, delay) => {
  let previous = 0
  // 使用闭包返回一个函数并且用到闭包函数外面的变量previous
  return function () {
    let _this = this
    let args = arguments
    let now = new Date()
    if (now - previous > delay) {
      fn.apply(_this, args)
      previous = now
    }
  }
}

/**
 * 防抖函数
 * @name debounce
 * @param {*} fn 要执行的方法
 * @param {*} delay 延迟
 */
export const debounce = (fn, delay) => {
  let timer // 维护一个 timer
  return function () {
    let _this = this // 取debounce执行作用域的this
    let args = arguments
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(function () {
      fn.apply(_this, args) // 用apply指向调用debounce的对象,相当于_this.fn(args);
    }, delay)
  }
}

/**
 * 获取两个基础数据类型数组的差集
 * @param {Array} list1 数组1
 * @param {Array} list2 数组2
 * @return {Array} list
 */
export const minusArray = (list1, list2) => {
  if (!Array.isArray(list1) || !Array.isArray(list1)) throw new Error('params must be Array')
  if (list1.length > list2.length) {
    const mSet = new Set(list2)
    return list1.filter(x => !mSet.has(x))
  } else {
    const mSet = new Set(list1)
    return list2.filter(x => !mSet.has(x))
  }
}

/**
 * 获取两个对象数组的差集
 * @param {Array} arr1 数组1
 * @param {Array} arr2 数组2
 * @param {String} typeName 判断的key名称
 */
export const getDifferenceSet = (arr1, arr2, typeName) => {
  const list = []
  const differenceObject = arr1.concat(arr2).reduce((acc, cur) => {
    if (acc[cur[typeName]] && acc[cur[typeName]][typeName] === cur[typeName]) {
      delete acc[cur[typeName]]
    } else {
      acc[cur[typeName]] = cur
    }
    return acc
  }, {})
  for (const key in differenceObject) {
    list.push(differenceObject[key])
  }
  return list
}
/**
 * 列表转成树
 * @param {*} list list
 * @param {*} id node-key
 * @param {*} pid parent key
 * @param {*} childrenKey children key
 */
export const listToTree = (list, id = 'id', pkey = 'pid', childrenKey = 'children') => {
  const map = new Map()
  const newList = []
  list && list.forEach(item => {
    map.set(item[id], item)
  })
  map.forEach((item) => {
    if (map.has(item[pkey])) {
      const parent = map.get(item[pkey])
      parent[childrenKey] = parent[childrenKey] || []
      parent[childrenKey].push(item)
    } else {
      newList.push(item)
    }
  })
  return newList
}

/**
 * 树转列表
 * @param {*} tree 树数组
 * @param {*} list 接收结果的数据
 * @param {*} childrenKey 子项的key
 */
export const treeToList = (tree = [], list = [], childrenKey = 'children', handleMethod) => {
  tree.forEach(node => {
    if (typeof handleMethod === 'function') {
      handleMethod(node)
    }
    list.push(node)
    if (node[childrenKey] && node[childrenKey].length) {
      treeToList(node[childrenKey], list, childrenKey, handleMethod)
    }
  })
}

/**
 * 树组件过滤,返回新的数组
 * @param {*} tree 数据列表
 * @param {*} propKey 子项的要过滤的字段名
 * @param {*} value 要过滤的值
 * @param {*} matchPid 匹配的父级ID列表
 * @param {*} idKey id名称
 * @param {*} pid pid
 * @param {*} parentFilterKey 父级元素的字段名
 */
export const filterTree = (tree, propKey, value, childrenKey = 'children', idKey = 'id', pid = 'pid', parentFilterKey = propKey, matchPid = []) => {
  const filterList = []
  tree.forEach(item => {
    const newItem = { ...item }
    const pIncludes = item[parentFilterKey] && item[parentFilterKey].includes(value)
    if (pIncludes) {
      matchPid.push(item[idKey])
      filterList.push(newItem)
    } else if (item[childrenKey] && item[childrenKey].length) {
      if (pIncludes) {
        matchPid.push(item[idKey])
      }
      newItem[childrenKey] = filterTree(item[childrenKey], propKey, value, childrenKey, idKey, pid, parentFilterKey, matchPid)
      if (newItem[childrenKey].length || pIncludes) {
        filterList.push(newItem)
      }
    } else if (matchPid.includes(item[pid])) {
      filterList.push(item)
    } else if (Array.isArray(propKey)) {
      propKey.forEach(pItem => {
        if (item[pItem] && item[pItem].includes(value)) {
          filterList.push(item)
        }
      })
    } else if (item[propKey] && item[propKey].includes(value)) {
      filterList.push(item)
    }
  })
  return filterList
}

/**
 * 复杂类型深拷贝
 * @param {*} obj 数据
 */
export const deepClone = (obj) => {
  if (obj === null || typeof obj !== 'object') return obj
  const cpObj = obj instanceof Array ? [] : {}
  for (let key in obj) cpObj[key] = deepClone(obj[key])
  return cpObj
}

/**
 * 递归深拷贝
 */
export const deepCopy = (obj) => {
    const objCopy = Array.isArray(obj) ? [] : {}
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            if (obj[key] instanceof Object) {
                objCopy[key] = deepCopy(obj[key])
            } else {
                objCopy[key] = obj[key]
            }
        }
    }
    return objCopy
}

/**
 * 获取数据类型
 * @param {*} obj
 */
export const getType = (obj) => {
  let type = Object.prototype.toString.call(obj).match(/^\[object (.*)\]$/)[1].toLowerCase()
  if (type === 'string' && typeof obj === 'object') return 'object' // Let "new String('')" return 'object'
  if (obj === null) return 'null' // PhantomJS has type "DOMWindow" for null
  if (obj === undefined) return 'undefined' // PhantomJS has type "DOMWindow" for undefined
  return type
}

/**
 * getStyle
 * @param {*} obj dom元素
 * @param {*} name 样式树形名称
 */
export function getStyle (obj, name) {
  return window.getComputedStyle && obj ? getComputedStyle(obj, null)[name] : (obj ? obj.currentStyle[name] : 0)
}

/**
 * amountRule
 * @param {*} 千分位计算
 * @param {*} val 计算值
 */
export function amountRule (val) {
  let defaultAmount = ''
  let setAmount = amount + ''
  if (setAmount != 'null' && setAmount != '' && setAmount != 'undefined' && setAmount != '--') {
    defaultAmount = setAmount.split('').join('').replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
    return defaultAmount
  } else {
    return defaultAmount
  }
}

/**
 * flatten
 * @param {*} 数组打平
 * @param {*} arr 数组
 */
export const flatten = (arr) => {
  return arr.reduce((conArr, value) => {
    return conArr.concat(Array.isArray(value) ? flatten(value) : value)
  }, [])
}

// 判断是否为身份证号码,如果是,则中间的10位用*号展示
export const maskIdCard = (idCard: string) => {
  const reg = /^\d{6}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/
  if (reg.test(idCard)) {
    return idCard.replace(/(\d{6})\d{10}(\d{2})/, '$1**********$2')
  }
  return idCard
}

// 判断是否为手机号码,如果是,则中间的5位用*号展示
export const maskPhoneNumber = (phoneNumber: string) => {
  const reg = /^1[3-9]\d{9}$/
  if (reg.test(phoneNumber)) {
    return phoneNumber.replace(/(\d{3})\d{5}(\d{3})/, '$1*****$2')
  }
  return phoneNumber
}

// 判断图片文件类型
export const getImageExtension = (filename: string) => {
  // 正则表达式匹配文件扩展名
  const match = filename.match(/\.(?:jpg|jpeg|png|gif|bmp|webp)$/i)
  return match ? match[0] : ''
}

/**
 * 将数组拼装成字符串
 * @param {Array} str - 数组
 * @param {string} [separator=','] - 分隔符
 * @returns {string} - 字符串
 * @example
 * // '张三,李四,王五'
 * Tools.joinArr(['张三','李四','王五']);
 * // '张三.李四.王五'
 * Tools.joinArr(['张三','李四','王五'],'k2','.');
 */
export const joinArr = (arr: Array<string>, separator?: string) => {
  separator = separator || ','
  if (arr) {
    return arr.join(separator)
  } else {
    return ''
  }
}

/**
 * 本地图片转换base64
 * @param {*} folder 文件夹名称
 * @param {*} fileName 文件名称
 * @param {*} format 文件后缀
 */
export const getLocalImgToBase64 = (folder: string, fileName: string, format = 'png') => {
  let imgUrl = `/static/${folder}/${fileName}.${format}`
  let base64 = uni.getFileSystemManager().readFileSync(imgUrl, 'base64')
  return `data:image/png;base64,${base64}`
}

/**
 * 格式化表单数据并清空内容
 * @param {*} form 表单
 */
export const formatAndClearForm = <T extends Record<string, any>>(form: T): T => {
  // 遍历对象,清空所有值
  const clearValues = (obj: any): any => {
    if (Array.isArray(obj)) {
      return [] // 如果是数组,返回空数组
    } else if (typeof obj === 'object' && obj !== null) {
      const newObj: Record<string, any> = {}
      for (const key in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key)) {
          // 递归清空嵌套对象
          newObj[key] = clearValues(obj[key])
        }
      }
      return newObj
    } else {
      // 如果是基本数据类型,返回空值
      if (typeof obj === 'boolean') {
        return false // 默认布尔值为 false
      } else if (typeof obj === 'number') {
        return 0 // 默认数值为 0
      } else {
        return '' // 默认其他类型为空字符串
      }
    }
  }

  return clearValues(form) as T
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值