• 项目中常用方法汇总


    防抖

    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)
  • 相关阅读:
    【背包专题】K
    【背包专题】J
    【背包专题】H
    【背包专题】C
    5972: 【递归入门】全排列
    51nod 1136 欧拉函数【数论】
    【背包专题】G
    【背包专题】I
    【背包专题】F
    各浏览器的Hack写法
  • 原文地址:https://www.cnblogs.com/followme789/p/12956968.html
Copyright © 2020-2023  润新知