你越是认真生活,你的生活就会越美好!

将小数转化为百分比(保留四位小数,四舍五入)

function ChangeDecimalToPercentage(data) {
  let data1 = (data*100).toFixed(4)+"%"
  return data1
}

ChangeDecimalToPercentage(0.9823567) // '98.2357%'

保留小数点后两位四舍五入

function NumFilter (value) {
  // 截取当前数据到小数点后两位
  let realVal = parseFloat(value).toFixed(2)
  return realVal
}

NumFilter(0.985) // '0.98'
NumFilter(0.984) // '0.98'

全局通用的数据类型判断

function getType(obj){
  let type  = typeof obj;
  if (type !== "object") {    // 先进行typeof判断,如果是基础数据类型,直接返回
    return type;
  }
  // 对于typeof返回结果是object的,再进行如下的判断,正则返回结果
  return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1');  // 注意正则中间有个空格
}
/* 代码验证,需要注意大小写,哪些是typeof判断,哪些是toString判断?思考下 */
getType([])     // "Array" typeof []是object,因此toString返回
getType('123')  // "string" typeof 直接返回
getType(window) // "Window" toString返回
getType(null)   // "Null"首字母大写,typeof null是object,需toString来判断
getType(undefined)   // "undefined" typeof 直接返回
getType()            // "undefined" typeof 直接返回
getType(function(){}) // "function" typeof能判断,因此首字母小写
getType(/123/g)      //"RegExp" toString返回

复制文字

    copy(input) {
      // input 复制的文字
      const cssText = 'position:fixed;pointer-events:none;z-index:-9999;opacity:0;'
      const copyErrorMessage = 'Failed to copy value to clipboard. Unknown type.'
      let value

      if (typeof input !== 'string') try {
        value = JSON.stringify(input)
      } catch (e) {
        throw copyErrorMessage
      }
      else value = input

      const textarea = document.createElement('textarea')

      textarea.value = value
      textarea.setAttribute('readonly', '')
      textarea.style.cssText = cssText

      document.body.appendChild(textarea)

      if (navigator.userAgent.match(/ipad|ipod|iphone/i)) {
        textarea.contentEditable = true
        textarea.readOnly = true

        const range = document.createRange()

        range.selectNodeContents(textarea)

        const selection = window.getSelection()

        selection.removeAllRanges()
        selection.addRange(range)
        textarea.setSelectionRange(0, 999999)
      } else textarea.select()

      let success = false

      try {
        success = document.execCommand('copy')
      } catch (err) {
        console.warn(err)
      }

      document.body.removeChild(textarea)

      return success
    }

canvas生成水印

      // canvas 实现 watermark
      function __canvasWM({
        container = document.body,
        width = '380px',
        height = '110px',
        textAlign = 'center',
        textBaseline = 'middle',
        // font = "14px microsoft yahei",
        font = '15px PingFangSC-Regular, PingFang SC',
        fillStyle = 'rgba(184, 184, 184, 0.3)',
        content = '请勿外传',
        // rotate = '-32',
        rotate = '0',
        zIndex = 10,
      } = {}) {
        var args = arguments[0]
        var canvas = document.createElement('canvas')

        canvas.setAttribute('width', width)
        canvas.setAttribute('height', height)
        var ctx = canvas.getContext('2d')

        ctx.textAlign = textAlign
        ctx.textAlign = textAlign
        ctx.textBaseline = textBaseline
        ctx.font = font
        ctx.fillStyle = fillStyle
        ctx.rotate((Math.PI / 180) * rotate)
        ctx.fillText(content, parseFloat(width) / 2, parseFloat(height) / 2)

        var base64Url = canvas.toDataURL()
        const watermarkDiv = document.createElement('div')
        watermarkDiv.setAttribute(
          'style',
          `
            position:fixed;
            top:-1100px;
            left:0px;
            min-width:5000px;
            min-height:5000px;
            z-index:${zIndex};
            pointer-events:none;
            background-repeat:repeat;
            transform: rotate(-30deg);
            background-image:url('${base64Url}')`
        )
        container.style.position = 'relative'
        container.insertBefore(watermarkDiv, container.firstChild)
        watermarkDiv.setAttribute('id', 'watermark')
      }
      __canvasWM({
        content: `陈坚泓     前端开发工程师`,
      })

效果如下
在这里插入图片描述

下载文件

// // 下载文件
// url: 文件地址
function downloadFile (url, fileName) {
  let link = document.createElement('a')
  link.style.display = 'none'
  link.href = url
  link.setAttribute('download', fileName) // 必须带后缀 例如: test.png
  link.setAttribute('target', '_blank')
  document.body.appendChild(link)
  link.click()
}

判断微信浏览器

getWxClient() {
      // 判断微信环境
      var isMobile = /Android|webOS|iPhone|iPod|BlackBerry/i.test(
        navigator.userAgent
      )
      var ua = navigator.userAgent.toLowerCase()
      var isWx = !!/micromessenger/.test(ua)
      return isMobile && isWx
    },

getWxClient() // 如果是返回true 不是返回false

判断手机为安卓还是苹果

// 判断手机为安卓还是苹果
    isAndroidOrIos() {
      let u = navigator.userAgent
      let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1 // android终端
      let isIos = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) // ios终端
      if (isAndroid) {
        return 'Android'
      } else if (isIos) {
        return 'Ios'
      }
    }

微信环境下禁止分享

document.addEventListener('WeixinJSBridgeReady', (onBridgeReady) => {
   // 通过下面这个API隐藏右上角按钮
   // eslint-disable-next-line no-undef
   WeixinJSBridge.call('hideOptionMenu')
 })

判断是否PC客户端

export const isPC = () => {
  var userAgentInfo = navigator.userAgent;
  var Agents = ["Android", "iPhone",
    "SymbianOS", "Windows Phone",
    "iPad", "iPod"];
  var flag = true;
  for (var v = 0; v < Agents.length; v++) {
    if (userAgentInfo.indexOf(Agents[v]) > 0) {
      flag = false;
      break;
    }
  }
  return flag;
}

isPC() // 如果是返回true 不是返回false

获取当前时间 (2020-03-28)

getTime() {
  let date = new Date()
  let year = date.getFullYear()
  let month = date.getMonth() + 1
  let strDate = date.getDate()
  if (month >= 1 && month <= 9) {
    month = '0' + month
  }
  if (strDate >= 0 && strDate <= 9) {
    strDate = '0' + strDate
  }
  let currentdate = `${year}-${month}-${strDate}`
  return currentdate
}

// getTime() // 2020-03-28

获取当前时间(“2020-08-16 11:35:06”)

fixedTime(val) {
      return val < 10 ? '0' + val : val
    },
    getFormatDate() {
      var date = new Date()
      var currentDate = date.getFullYear() + '-' + this.fixedTime(date.getMonth() + 1) + '-' + this.fixedTime(date.getDate()) + ' ' + this.fixedTime(date.getHours()) + ':' + this.fixedTime(date.getMinutes()) + ':' + this.fixedTime(date.getSeconds())
      return currentDate
    },

js将时间转换成时间戳

js获取当前时间戳的方法

// 第一种:获取的时间戳是把毫秒改成000显示,第二种和第三种是获取了当前毫秒的时间戳。
var timestamp1 = Date.parse(new Date());
// 或者
var timestamp2 = (new Date()).valueOf();
// 或者
var timestamp3 = new Date().getTime();

js获取制定时间戳的方法

// getTime()返回数值的单位是毫秒。
var oldTime = (new Date("2015/06/23 08:00:20")).getTime()/1000;

js把时间戳转为为普通日期格式

1.Date toLocaleString方法

function getLocalTime(nS) {     
   return new Date(parseInt(nS) * 1000).toLocaleString().replace(/:\d{1,2}$/,' ');     
}

getLocalTime("1608628527") // "2020/12/22 下午5:15 "

parseInt() 函数可解析一个字符串,并返回一个整数。

js中时间操作单位是毫秒。

toLocaleString() 方法可根据本地时间把 Date 对象转换为字符串,并返回结果。

replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。

replace(/:\d{1,2}$/,’ ')验证替换以:开始有一位或二位数字的结束字符串,就是秒;替换为空

出生日期计算年龄 24Y5M

getAge(‘1995-07-08’) 返回24Y5M

export const getAge = (str) => {
// str = '1995-07-08'
  var r = str.match(/^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/);
  if (r == null) return false
  var d = new Date(r[1], r[3] - 1, r[4])
  if (d.getFullYear() == r[1] && (d.getMonth() + 1) == r[3] && d.getDate() == r[4]) {
    var date = new Date()
    var Y = date.getFullYear() - r[1]
    var M = date.getMonth() + 1 - r[3]
    var D = date.getDate()
    if (parseInt(D) - parseInt(r[4]) < 0) {
      M--;
      if (M < 0) {
        Y--
        M = 11
      }
    }
    if (M < 0) {
      Y--
      M = 11
    }
    return (Y + "Y" + M + "M")
  }
}

getAge('1995-07-08') // "24Y5M"(即24周岁5个月)

根据生日返回周岁(24)

	// this.getAge(1995-07-08)  返回24  (2020-03-23)
    getAge(birthday) {
      // birthday = 1995-07-08
      var returnAge
      var birthdayArr = birthday.split('-')
      var birthYear = birthdayArr[0]
      var birthMonth = birthdayArr[1]
      var birthDay = birthdayArr[2]
      var d = new Date()
      var nowYear = d.getFullYear()
      var nowMonth = d.getMonth() + 1
      var nowDay = d.getDate()
      // 这里用了 === 号 要把类型都转为数字
      if (+nowYear === +birthYear) {
        returnAge = 0// 同年 则为0周岁
      } else {
        var ageDiff = nowYear - birthYear // 年之差
        if (ageDiff > 0) {
        // 这里用了 === 号 要把类型都转为数字
          if (+nowMonth === +birthMonth) {
            var dayDiff = nowDay - birthDay// 日之差
            if (dayDiff < 0) {
              returnAge = ageDiff - 1
            } else {
              returnAge = ageDiff
            }
          } else {
            var monthDiff = nowMonth - birthMonth// 月之差
            if (monthDiff < 0) {
              returnAge = ageDiff - 1
            } else {
              returnAge = ageDiff
            }
          }
        } else {
          returnAge = -1// 返回-1 表示出生日期输入错误 晚于今天
        }
      }
      return returnAge// 返回周岁年龄
    }

获取保险生效日期、截止日期

    getTime() {
      // 获取保险生效日期 截止日期
      let date = new Date()
      let year = +date.getFullYear()
      let month = +date.getMonth() + 1 // getMonth()返回值是 0(一月) 到 11(十二月) 之间的一个整数
      let strDate = +date.getDate()
      let maxDate
      maxDate = new Date(year, month, 0).getDate()
      if (strDate + 1 > maxDate) {
        month += 1
        strDate = 1
        if (month > 12) {
          year++
          month = 1
          strDate = 31
        }
      } else {
        strDate += 1
      }
      // 个位数+0
      if (strDate > 0 && strDate <= 9) {
        strDate = '0' + strDate
      }
      if (month > 0 && month <= 9) {
        month = '0' + month
      }
      this.startDate = `${year}-${month}-${strDate}`
      if (+strDate === 1) {
        if (month === 1) {
          year--
          month = 12
          strDate = 31
        } else {
          month--
          strDate = new Date(year, month, 0).getDate()
        }
      } else {
        strDate--
      }
      year++
      // 个位数+0
      if (strDate > 0 && strDate <= 9) {
        strDate = '0' + +strDate
      }
      if (month > 0 && month <= 9) {
        month = '0' + +month
      }
      this.endDate = `${year}-${month}-${strDate}`
    }
// getTime()  2020-04-07时调用
// startDate = 2020-04-08
// endDate = 2021-04-07

数字每千位加逗号

export const commafy = (num) => {
  return num && num.toString()
    .replace(/\d+/, function(s){
         return s.replace(/(\d)(?=(\d{3})+$)/g, '$1,')
     })
}

commafy(19999999) // "19,999,999"

手机号码中间四位隐藏星号显示

export const hideMobile = (mobile) => {
  return mobile.replace(/^(\d{3})\d{4}(\d{4})$/, "$1****$2")
}

hideMobile('13049997092') // "130****7092"

获取URL链接参数

根据参数名称获取参数值

// name为参数名
getUrlParam(name) {
    var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)')
    var result = window.location.search.substr(1).match(reg)
    return result ? decodeURIComponent(result[2]) : null
  }

链接参数赋值到一个对象上

const search = window.location.href.split('?')[1].split('&')
 search.forEach(item => {
   this.userInfo[item.split('=')[0]] = decodeURI(item.split('=')[1])
 })

设置cookie

// 设置指定cookie
// name:cookie名称    value对应cookie的值    iDay有效期天数 如7表示7天
export const setCookie = (name, value, iDay) => {
  let oDate = new Date()
  if (iDay) {
    oDate.setDate(oDate.getDate() + iDay)
  } else {
    console.log('iDay:' + iDay)
    oDate = iDay
  }
  // 域名domain=.ybj.com   .表示前面可以匹配所有   77.ybj.com 或者 75.ybj.com等都可以获取到该cookie
  document.cookie = `${name}=${value};expires=${oDate};domain=.ybj.com;path=/`
}

获取指定cookie

// name:cookie名称
export const getCookie = (name) => {
  let arr1 = document.cookie.split('; ')
  let i = 0;
  for (i = 0; i < arr1.length; i++) {
    var arr2 = arr1[i].split('=')
    if (arr2[0] == name) {
      return arr2[1]
    }
  }
  return ''
}

添加vconsole调试

 <script language="javascript" type="text/javascript" src="//images.vrm.cn/9x/2020/09/08/vconsole.min.js"></script>
<script>
var vConsole = new VConsole();
</script>

findUpwardComponent () 返回父组件

findBrotherComponents() 返回兄弟组件

findDownwardComponent() 返回子组件

validator() 注册表单验证

src/utils/index.js

// 返回context父实例componentName
import Validator from './validator'
const findUpwardComponent = (context, componentName) => {
  let parent = context.$parent
  let name = parent.$options.name
  while (parent && (!name || !name.includes(componentName))) {
    parent = parent.$parent
    if (parent) name = parent.$options.name
  }
  return parent
}
// 返回context的兄弟实例componentName
const findBrotherComponents = (ctx, componentName, exceptMe = true) => {
  const $brothers = ctx.$parent.$children.filter(item => {
    return item.$options.name && item.$options.name.includes(componentName)
  })
  const index = $brothers.findIndex(item => item._uid === ctx._uid)
  if (exceptMe && index > -1) $brothers.splice(index, 1)
  return $brothers
}
// 返回context的子实例componentName
const findDownwardComponent = (context, componentName) => {
  const $children = context.$children
  let bean = null
  if ($children.length) {
    for (const child of $children) {
      const name = child.$options.name
      if (name && name.includes(componentName)) {
        bean = child
        break
      } else {
        bean = findDownwardComponent(child, componentName)
        if (bean) break
      }
    }
  }
  return bean
}
// 注册表单验证
const validator = (rules, form) => {
  try {
    Object.keys(rules).forEach(key => {
      const value = rules[key]
      value.pattern.split('&').forEach((pattern, index) => {
        const result = new Validator({
          value: form[key],
          pattern,
          message: value.message.split('&')[index]
        }).test()
        if (!result.valid) {
          throw new Error(result.message)
        }
      })
    })
    return true
  } catch (e) {
    toast.info(e.message)
  }
}


export {
	findUpwardComponent,
	findBrotherComponents,
	findDownwardComponent,
	validator
}

src/utils/validator.js

/* eslint-disable */
export default class Validator {
  constructor(model) {
    this.value = model.value
    this.pattern = model.pattern
    this.message = model.message || '验证失败'
    this.valid = true
    this.init()
  }
  init() {
    switch (this.pattern) {
      case 'mobile':
        this.pattern = /^0?((13[0-9])|(14[0-9])|(15([0-3]|[5-9]))|(166)|(18[0-9])|(17[0-9])|(19[8-9]))[0-9]{8}$/
        break
      case 'idcard':
        this.pattern = /^[1-9][0-9]{5}(19|20)[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9X]$/
        break
      case 'name':
        this.pattern = /^[A-Za-z_\-\u4e00-\u9fa5]{2,20}$/
        break
      case 'email':
        this.pattern = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/
        break
      case 'birthday':
        this.pattern = /^[1-9]\d{3}([-|\/|\.])?((0\d)|([1-9])|(1[0-2]))\1(([0|1|2]\d)|([1-9])|3[0-1])$/
        break
      case 'required':
        this.pattern = cb => {
          this.value ? cb() : cb(this.message)
        }
        break
      default:
        break
    }
  }
  callback(message) {
    this.valid = !message
    this.message = message
  }
  test() {
    if (typeof this.pattern === 'function') {
      this.pattern(this.callback.bind(this))
    } else {
      this.valid = this.value ? this.pattern.test(this.value) : true
    }
    return { valid: this.valid, message: this.valid ? undefined : this.message }
  }
}

调用

import {findUpwardComponent, findBrotherComponents, findDownwardComponent} from '@/utils/index'
console.log(findDownwardComponent(this, 'layer_0003'))

也可以这样调用

import * as utils from '@/utils/index'
console.log(utils.findDownwardComponent(this, 'layer'))
// utils.findDownwardComponent(this, 'layer') 相当于 当先实例的子实例layer 里面的this
// 也相当于通过$refs.layer获取到的一样


// 表单验证规则
let fields = [
      {
        label: '姓名',
        prop: 'name',
        other: { placeholder: '', sex: { visible: 1, type: 0, text: '男/女' } }
      },
      {
        label: '生日',
        prop: 'birthday',
        other: { placeholder: '', maxAge: 50, minAge: 20, defaultAge: 30 }
      },
      {
        label: '手机',
        prop: 'mobile',
        other: {
          placeholder: '',
          captcha: { type: 0, activityId: '', callback: { type: 'none' } }
        }
      },
      {
        label: '协议',
        prop: 'agreecCall',
        other: {
          autoCheck: 1,
          autoCheckAfterFinish: 1,
          type: 0,
          company: '',
          product: '',
          text:
            '我已知晓并许可太平保险专线致电我沟通赠险领取事宜及<b>《服务协议》</b>'
        }
      }
    ]
const rules = fields.reduce((rules, field) => {
        if (field.prop === 'name') {
          rules.name = { pattern: 'required&name', message: `请输入您的${field.label}&姓名格式错误` }
          field.other.sex.visible === 1 && (rules.sex = { 'pattern': 'required', 'message': '请选择性别' })
        } else if (field.prop === 'birthday') {
          rules.birthday = { pattern: 'required&birthday', message: `请选择您的${field.label}&生日格式错误` }
        } else if (field.prop === 'mobile') {
          rules.mobile = { pattern: 'required&mobile', message: `请输入您的${field.label}&手机号码格式错误` }
          field.other.captcha.type === 1 && (rules.mobileCode = { 'pattern': 'required', 'message': '请输入验证码' })
        } else if (field.prop === 'agreecCall') {
          rules.agreecCall = { pattern: 'required', message: '请勾选服务协议' }
        } else if (field.prop === 'email') {
          rules.email = { pattern: 'required&email', message: `请输入您的${field.label}&邮箱格式错误` }
        } else if (field.other.type === 'input') {
          rules[field.prop] = { pattern: 'required', message: `请输入${field.label}` }
        } else if (['select', 'radio'].includes(field.other.type)) {
          rules[field.prop] = { pattern: 'required', message: `请选择${field.label}` }
        }
        return rules
      },{})
    
  const userInfo = {
  	agreecCall: 1
	birthday: "1989-10-11"
	id: "id"
	mobile: "130****7092"
	mobileCode: "943499"
	name: "测试"
	sex:}
utils.validator(rules, userInfo) // 返回布尔值
  

rulesObject
在这里插入图片描述

推荐阅读

Vue源码学习完整目录

Vue源码学习完整目录

连点成线 - 前端成长之路

连点成线 - 前端成长之路


谢谢你阅读到了最后~
期待你关注、收藏、评论、点赞~
让我们一起 变得更强

Logo

前往低代码交流专区

更多推荐