zoukankan      html  css  js  c++  java
  • 项目中常用方法汇总

    防抖

    export function throttle (fn, interval = 500) {
      let canRun = true
      return function () {
        if (!canRun) return
        canRun = false
        setTimeout(() => {
          fn.apply(this, arguments)
          canRun = true
        }, interval)
      }
    }

    节流

    export function debounce (fn, wait = 500, immediate) {
      let timer
      return function () {
        if (immediate) {
          fn.apply(this, arguments)
        }
        if (timer) clearTimeout(timer)
        timer = setTimeout(() => {
          fn.apply(this, arguments)
        }, wait)
      }
    }

    获取文件名

    export function downloadUrlFile (url, fileName) {
      url = url.replace(/\/g, '/')
      const xhr = new XMLHttpRequest()
      xhr.open('GET', url, true)
      xhr.responseType = 'blob'
      // xhr.setRequestHeader('Authorization', 'Basic a2VybWl0Omtlcm1pdA==');
      xhr.onload = () => {
        if (xhr.status === 200) {
          // 获取文件blob数据并保存
          saveAs(xhr.response, fileName)
        }
      }
      xhr.send()
    }
    /**
     * URL方式保存文件到本地
     * @param data 文件的blob数据
     * @param name 文件名
     */
    function saveAs (data, name) {
      var urlObject = window.URL || window.webkitURL || window
      var exportBlob = new Blob([data])
      var saveLink = document.createElementNS('http://www.w3.org/1999/xhtml', 'a')
      saveLink.href = urlObject.createObjectURL(exportBlob)
      saveLink.download = name
      saveLink.click()
    }
     

    时间戳简析

    export function dateFormat (fmt, date) {
      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 (const 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
    }
    阿拉伯数字转换成大写汉字
    export function numberParseChina (money) {
      // 汉字的数字
      let cnNums = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
      // 基本单位
      let cnIntRadice = ['', '拾', '佰', '仟']
      // 对应整数部分扩展单位
      let cnIntUnits = ['', '万', '亿', '兆']
      // 对应小数部分单位
      let cnDecUnits = ['角', '分', '毫', '厘']
      // 整数金额时后面跟的字符
      let cnInteger = '整'
      // 整型完以后的单位
      let cnIntLast = '圆'
      // 最大处理的数字
      let maxNum = 999999999999999.9999
      // 金额整数部分
      let integerNum
      // 金额小数部分
      let decimalNum
      // 输出的中文金额字符串
      let chineseStr = ''
      // 分离金额后用的数组,预定义
      let parts
      if (money === '') { return '' }
      money = parseFloat(money)
      if (money >= maxNum) {
        // 超出最大处理数字
        return ''
      }
      if (money === 0) {
        chineseStr = cnNums[0] + cnIntLast + cnInteger
        return chineseStr
      }
      // 转换为字符串
      money = money.toString()
      if (money.indexOf('.') === -1) {
        integerNum = money
        decimalNum = ''
      } else {
        parts = money.split('.')
        integerNum = parts[0]
        decimalNum = parts[1].substr(0, 4)
      }
      // 获取整型部分转换
      if (parseInt(integerNum, 10) > 0) {
        let zeroCount = 0
        let IntLen = integerNum.length
        for (let i = 0; i < IntLen; i++) {
          let n = integerNum.substr(i, 1)
          let p = IntLen - i - 1
          let q = p / 4
          let m = p % 4
          if (n === '0') {
            zeroCount++
          } else {
            if (zeroCount > 0) {
              chineseStr += cnNums[0]
            }
            // 归零
            zeroCount = 0
            chineseStr += cnNums[parseInt(n)] + cnIntRadice[m]
          }
          if (m === 0 && zeroCount < 4) {
            chineseStr += cnIntUnits[q]
          }
        }
        chineseStr += cnIntLast
      }
      // 小数部分
      if (decimalNum !== '') {
        let decLen = decimalNum.length
        for (let i = 0; i < decLen; i++) {
          let n = decimalNum.substr(i, 1)
          if (n !== '0') {
            chineseStr += cnNums[Number(n)] + cnDecUnits[i]
          }
        }
      }
      if (chineseStr === '') {
        chineseStr += cnNums[0] + cnIntLast + cnInteger
      } else if (decimalNum === '') {
        chineseStr += cnInteger
      }
      return chineseStr
    }

    数组去重

    export function filterArrayByKey (arr, key) {
      if (!(Array.isArray(arr))) return []
      const hash = {}
      return arr.filter((item) => {
        if (hash[item[key]]) return false
        hash[item[key]] = true
        return true
      })
    }
    格式化金额数字,第一个参数是数字,第二个是保留几位小数,三位加逗号
    export function formatMoney (s, n) {
      if (s) {
        n = n > 0 && n <= 20 ? n : 2
        s = parseFloat((s + '').replace(/[^d.-]/g, '')).toFixed(n) + ''
        let l = s.split('.')[0].split('').reverse()
        let r = s.split('.')[1]
        let t = ''
        for (let i = 0; i < l.length; i++) {
          t += l[i] + ((i + 1) % 3 === 0 && (i + 1) !== l.length ? ',' : '')
        }
        return t.split('').reverse().join('') + '.' + r
      }
    }
    清除一个数组中值为空的项
    export const cleanEmptyInArray = function (array) {
      let [...newArray] = array
      const count = newArray.length
      for (let i = count - 1; i >= 0; i--) {
        if (newArray[i] === '' || newArray[i] === null || newArray[i] === undefined) {
          newArray.splice(i, 1)
        }
      }
      return newArray
    }

    基于ekement表格合计方法

    
    
        /* 合计方法 */
        Vue.prototype.$calcSummaries = function (columns, data, showCheckBox) {
          const sums = []
          columns.forEach((column, index) => {
            const values = data && data.map(item => Number(item[column.property]))
            // console.log(values)
            if (column.columnKey) {
              sums[index] = values.reduce((prev, curr) => {
                const value = Number(curr)
                if (!isNaN(value)) {
                  switch (column.columnKey) {
                    case 'amount':
                      return (Number(prev) + Number(curr)).toFixed(2)
                    case 'number':
                      return (Number(prev) + Number(curr)).toFixed(3)
                    case 'int':
                      return (Number(prev) + Number(curr))
                    case 'amount0':
                      return (Number(prev) + Number(curr)).toFixed(0)
                    default:
                      return (Number(prev) + Number(curr)).toFixed(2)
                  }
                } else {
                  switch (column.columnKey) {
                    case 'amount':
                      return Number(prev).toFixed(2)
                    case 'number':
                      return Number(prev).toFixed(3)
                    case 'int':
                      return Number(prev)
                    default:
                      return Number(prev).toFixed(6)
                  }
                }
              }, 0)
            } else {
              sums[index] = ''
            }
          })
          if (showCheckBox) {
            sums[2] = '合计'
          } else {
            sums[1] = '合计'
          }
          return sums
        }
    
    页面内部合计方法
    getSummaries (param) {
          const { columns, data } = param
          return this.$calcSummaries(columns, data)
        }
    需要合计行加配置项
    column-key="amount"

     过滤对象中空值

    traverse (data) {
          const keys = Object.keys(this.formData)
          for (let item of keys) {
            if (!this.isDef(this.formData[item])) this.$delete(this.formData, item)
          }
        },
        isDef (v) {
          return v !== undefined && v !== null && v !== ''
        },

     值级map转换

    // 付款条款类型
    export const PAYMENT_VALUE = new Map([
      ['ADVANCE', '预付款'],
      ['PAY_FOR_RECEIVE', '到货款'],
      ['PAY_FOR_PROGRESS', '进度款'],
      ['FINAL_FEE', '完工款'],
      ['PAY_FOR_ACCEPT', '验收款'],
      ['QUALITY_ASSURANCE', '质保金'],
      ['PERFORMANCE_BOND', '履约保证金'],
      ['GOODS_OFFSET_COST', '以货抵费'],
      ['OTHERS', '其他']
    ])
    getpaymentVal (val) {
          return PAYMENT_VALUE.get(val)
        },
     

     JSON去重

    unique (type, arr) { // 根据唯一标识no来对数组进行过滤
          const res = new Map() // 定义常量 res,值为一个Map对象实例
          // 返回arr数组过滤后的结果,结果为一个数组   过滤条件是,如果res中没有某个键,就设置这个键的值为1
          return arr.filter((arr) => !res.has(arr[type]) && res.set(arr[type], 1))
        },
    
    // type 删选条件
    // arr 数据源
    日期格式化方法
    /**
     * 日期格式化方法
     * @param {string} date     [可选] 要格式化的时间
     * @param {string} fmt      [可选] 时间格式
     *
     * 月(M)、日(D)、12小时(h)、24小时(H)、分(m)、秒(s)、周(E)、季度(Q) ==> 可以用 1-2 个占位符
     * 年(Y) ==> 1-4 个占位符
     * 毫秒(S) ==> 1 个占位符(是 1-3 位的数字)
     */
    export function formatDate (date = Date.now(), fmt = 'YYYY-MM-DD HH:mm:ss') {
      if (!date) return '-'
      date = new Date(date)
      const o = {
        'M+': date.getMonth() + 1, // 月份
        'D+': date.getDate(), //
        'h+': date.getHours() % 12 || 12, // 12小时
        'H+': date.getHours(), // 24小时
        'm+': date.getMinutes(), // 分钟
        's+': date.getSeconds(), //
        'Q+': Math.floor((date.getMonth() + 3) / 3), // 季度
        S: date.getMilliseconds() // 毫秒
      }
      const week = {
        0: 'u65e5',
        1: 'u4e00',
        2: 'u4e8c',
        3: 'u4e09',
        4: 'u56db',
        5: 'u4e94',
        6: 'u516d'
      }
      if (/(Y+)/.test(fmt)) {
        fmt = fmt.replace(
          RegExp.$1,
          (date.getFullYear() + '').substr(4 - RegExp.$1.length)
        )
      }
      if (/(E+)/.test(fmt)) {
        fmt = fmt.replace(
          RegExp.$1,
          (RegExp.$1.length > 1
            ? RegExp.$1.length > 2
              ? 'u661fu671f'
              : 'u5468'
            : '') + week[date.getDay() + '']
        )
      }
      Object.keys(o).forEach(k => {
        if (new RegExp('(' + k + ')').test(fmt)) {
          fmt = fmt.replace(
            RegExp.$1,
            RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
          )
        }
      })
      return fmt
    }
    /**
     * 获取格式化分时秒钟的毫秒数
     *
     * @param {string} time 根据分时秒格式(如: 12:11.300),获取毫秒
     * @return {Number}
     */
    export function getMilliseconds (time) {
      const reg = /(d+):(d+)(.(d+))*/g
      const ret = reg.exec(time)

      if (!ret) {
        return 0
      }

      const min = ret[1] || 0
      const sec = ret[2] || 0
      const mil = ret[4] || 0

      return (
        parseInt(min, 10) * 60 * 1000 + parseInt(sec, 10) * 1000 + parseInt(mil, 10)
      )
    }

    /**
     * 获取格式化分时秒钟的总秒数
     *
     * @param {string} time 根据分时秒格式(如: 12:11.300),获取秒
     * @return {Number}
     */
    export function getSeconds (time) {
      const mil = getMilliseconds(time)

      return mil / 1000
    }
     

     项目过滤器

    import Vue from 'vue'
    import _lo from 'lodash'
    import { formatDate } from '@/util/datetime'
    import { numberFormat } from '@/util/utils'
    
    const filters = {
      /**
       * 数据特殊处理
       * val: 要转换的数据
       * format: 数据转换格式,是个对象,type指定要转换的类型(目前有map),其他的属性则是特殊类型的数据处理。
       * 如:format: { type: 'map', statusMap: { 0: '已启用', 1: '已停用'}}
       *    format: { type: 'rate'}
       *    format: { type: 'date', fmt: 'YYYY-MM-DD'}
       *  总之,format对象传入要处理的数据类型和要转换的特殊的参数,目前type只有三种类型,有需要的可自行添加。
       */
      getScope: (val, format = { type: '' }, otherData) => {
        if (typeof val === 'undefined' || val === null || val === '') return '-' // 非空判断
        if (!(val || format.type)) return '-'
        switch (format.type) {
          case 'map':
            return format.statusMap[val] || '-'
          case 'reserveZeroMap':
            return format.statusMap[val] ?? '-'
          case 'reserveZero':
            return val ?? '-'
          case 'join':
            let res = val.map((item) => item.valueName).join('')
            return res || '-'
          case 'mapPost':
            return format.statusMap[val] || val
          case 'rate':
            return val + '%'
          case 'fn':
            return format.fn(val, otherData)
          case 'date':
            return formatDate(val, format.fmt)
          case 'price':
            return numberFormat(val, format.digit || 2, '.', ',', 'round')
          case 'number':
            // 对 NAN 数据进行过滤
            if (Number.isNaN(val)) val = 0
            return _lo.round(+val, 3).toFixed(3)
          case 'total':
            return '共计' + val
          case 'shipAddress':
            if (otherData.transportMode === '3') {
              return '-'
            } else {
              return val
            }
          case 'isHas':
            return val ? '' : ''
          default:
            return val || '-'
        }
      }
    }
    
    Object.keys(filters).forEach(key => Vue.filter(key, filters[key]))
    // * 验证金额以100,000.00的方式
    // * @param {*} number 要格式化的数字
    // * @param {*} decimals 保留几位小数
    // * @param {*} decPoint 小数点符号
    // * @param {*} thousandsSep 千分位符号
    // * @param {*} roundtag 舍入参数,默认 'ceil' 向上取,'floor'向下取,'round' 四舍五入
    export function numberFormat (number, decimals, decPoint, thousandsSep, roundtag) {
      number = (number + '').replace(/[^0-9+-Ee.]/g, '')
      roundtag = roundtag || 'ceil' // 'ceil','floor','round'
      var n = !isFinite(+number) ? 0 : +number
      var prec = !isFinite(+decimals) ? 0 : Math.abs(decimals)
      var sep = (!thousandsSep) ? ',' : thousandsSep
      var dec = (typeof decPoint === 'undefined') ? '.' : decPoint
      var s = ''
      var toFixedFix = function (n, prec) {
        var k = Math.pow(10, prec)
        return '' + parseFloat(Math[roundtag](parseFloat((n * k).toFixed(prec * 2))).toFixed(prec * 2)) / k
      }
      s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.')
      var re = /(-?d+)(d{3})/
      while (re.test(s[0])) {
        s[0] = s[0].replace(re, '$1' + sep + '$2')
      }
      if ((s[1] || '').length < prec) {
        s[1] = s[1] || ''
        s[1] += new Array(prec - s[1].length + 1).join('0')
      }
      return s.join(dec)
    }

    基于ele 输入格式验证input

    <template>
      <el-input v-bind="$attrs" v-bind:value="value" v-on="inputListeners">
        <template slot="append">
          <slot name="append"></slot>
        </template>
        <template slot="prepend">
          <slot name="prepend"></slot>
        </template>
        <template slot="prefix">
          <slot name="prefix"></slot>
        </template>
        <template slot="suffix">
          <slot name="suffix"></slot>
        </template>
      </el-input>
    </template>
    
    <script>
    
    /**
     * @Description: input 全局注册组件,新增 mode 和 pattern 属性 (二 选 一)
     * @Description: mode 是定义好的一些 固定模式,可扩展
     * @Description: pattern 是正则表达式,自定义程度高
     * @Description: 所有 el-input 官方属性都可继承
     * @use:
     * <vd-el-input
     *  v-model="xxxx"
     *  placeholder="请输入"
     *  mode="thereDecimal"
     *  clearable></vd-el-input>
     * @author Miracle TJF
     * @date 2020/4/10
    */
    export default {
      name: 'VdInput',
      inheritAttrs: false,
      props: {
        value: {
          type: [String, Number],
          default: ''
        },
        mode: {
          type: String,
          default: ''
        },
        pattern: {
          type: RegExp,
          default () {
            return /.*/
          }
        }
      },
      computed: {
        inputListeners: function () {
          let vm = this
          // `Object.assign` 将所有的对象合并为一个新对象
          return Object.assign({},
            // 我们从父级添加所有的监听器
            this.$listeners,
            // 然后我们添加自定义监听器,
            // 或覆写一些监听器的行为
            {
              // 这里确保组件配合 `v-model` 的工作
              input: function (val) {
                vm.interceptValue(val)
              }
            }
          )
        }
      },
      created () {
        this.initProps()
      },
      data () {
        return {
          currentPattern: this.pattern
        }
      },
      methods: {
        initProps () {
          if (this.mode && modeMap[this.mode]) {
            this.currentPattern = modeMap[this.mode]
          }
        },
        interceptValue (val) {
          if (!val) {
            return this.$emit('input', '')
          }
          const reg = this.generateReg()
          const match = val.match(reg)
          if (match && match[1]) {
            this.$emit('input', match[1])
          }
        },
        generateReg () {
          const source = this.currentPattern.source
          const flags = this.currentPattern.flags
          return new RegExp(`(${source})`, flags)
        }
      }
    }
    
    // 预置格式 (需要额外的可自行完善,注释要写清楚)
    const modeMap = {
      int: /d+/, // 整数
      twoDecimal: /([1-9]d*|0)(.d{0,2})?/, // 两位小数
      threeDecimal: /([1-9]d*|0)(.d{0,3})?/, // 三位小数
      threeIntegerTwoDecimal: /([1-9]d{0,2}|0)(.d{0,2})?/, // 最多三位整数,最多两位小数
      thereDecimal: /d+(.d{0,3})?/, // 三位小数
      twoNotEqualDecimal: /^([1-9][0-9]*)+(.d{0,2})?/, // 大于0两位小数
      natThereDecimal: /^-?d+(.d{0,3})?/, // 正负三位小数
      sixeDecimal: /d{0,9}(.d{0,6})?/, // 小数点前九后六
      eightDecimal: /d{0,8}(.d{0,2})?/, // 小数点前八后二
      thirteenDecimal: /d{0,13}(.d{0,2})?/, // 小数点前十八后二
      tenAndTwo: /([1-9]d{0,9}|0)(.d{0,2})?/, // 前十后二
      canZeroInt: /^(0|[1-9][0-9]*)$/, // 只能输入0或者非0开头的数字
      volumeDecimal: /^[0-9](.d{0,2})?$|^([1-3][0-9]{2}|[1-9][0-9]{0,1})(.d{0,2})?$|^400/ // 大于0小于等于400两位小数
    }
    </script>
    // 挂载全局
    import Vue from 'vue'
    // 输入框组件封装
    import VdElInput from '@/components/globals/VdElInput'

    Vue.component('vd-el-input', VdElInput)
    // 使用
    <vd-el-input
                    v-model.trim="scope.row.amountRate"
                    type="text"
                    placeholder="请输入"
                    style="100%"
                    :maxlength="6"
                    clearable
                    mode="twoNotEqualDecimal"
                  ></vd-el-input>

     递归查找

    function getGroupName(data, id) {
        let a
        if (!data) {
            return
        }
        for (let i = 0; i < data.length; i++) {
            const item = data[i]
            // console.log(item)
            if (item.categoryCode === id) {
                a = item.categoryFullName
                return a
            } else if (item.children && item.children.length > 0) {
                if (getGroupName(item.children, id)) {
                    return a = getGroupName(item.children, id)
                }
            }
        }
        return a
    }
    let str = getGroupName(array, 8)
    console.log('str', str)
  • 相关阅读:
    There is an overlap in the region chain修复
    There is an overlap in the region chain
    region xx not deployed on any region server
    python 中的re模块,正则表达式
    TCP粘包问题解析与解决
    yield from
    Git push提交时报错Permission denied(publickey)...Please make sure you have the correct access rights and the repository exists.
    mysql 中Varchar 与char的区别
    Mysql 字符集及排序规则
    请实现一个装饰器,限制该函数被调用的频率,如10秒一次
  • 原文地址:https://www.cnblogs.com/followme789/p/12956968.html
Copyright © 2011-2022 走看看