基于ts写法的一些 项目中会有所用到的功能函数
项目中可能会用到的功能函数,一般定义到外部文件中,hooks中。在此记录一下:
一,判断是否ie浏览器 判断ie的版本
// 判断是否ie浏览器
export const isIE = function isIE() {
if (!!window.ActiveXObject || 'ActiveXObject' in window) {
return true
}
return false
}
// 判断 ie 的版本
export const IEVersion = function IEVersion() {
const { userAgent } = navigator // 取得浏览器的userAgent字符串
const isIE =
userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1 // 判断是否IE<11浏览器
const isEdge = userAgent.indexOf('Edge') > -1 && !isIE // 判断是否IE的Edge浏览器
const isIE11 =
userAgent.indexOf('Trident') > -1 && userAgent.indexOf('rv:11.0') > -1
if (isIE) {
const reIE = /MSIE (\\d+\\.\\d+);/
reIE.test(userAgent)
const fIEVersion = parseFloat(RegExp.$1)
if (fIEVersion === 7) {
return 7
}
if (fIEVersion === 8) {
return 8
}
if (fIEVersion === 9) {
return 9
}
if (fIEVersion === 10) {
return 10
}
return 6 // IE版本<=7
}
if (isEdge) {
return 'edge' // edge
}
if (isIE11) {
return 11 // IE11
}
return -1 // 不是ie浏览器
}
二,转意符换成普通字符
export const escape2Html = function escape2Html(str: string) {
const arrEntities: any = { lt: '<', gt: '>', nbsp: ' ', amp: '&', quot: '"' }
return str.replace(
/&(lt|gt|nbsp|amp|quot);/gi,
(_all: any, t) => arrEntities[t]
)
}
三,'yyyy-MM-dd HH:mm:ss’格式的字符串转日期
export const stringToDate = function stringToDate(str: string) {
const tempStrs = str.split(' ')
const dateStrs = tempStrs[0].split('-')
const year = parseInt(dateStrs[0], 10)
const month = parseInt(dateStrs[1], 10) - 1
const day = parseInt(dateStrs[2], 10)
const timeStrs = tempStrs[1] ? tempStrs[1].split(':') : []
const hour = timeStrs[0] ? parseInt(timeStrs[0], 10) : 0
const minute = timeStrs[1] ? parseInt(timeStrs[1], 10) : 0
const second = timeStrs[2] ? parseInt(timeStrs[2], 10) : 0
const date = new Date(year, month, day, hour, minute, second)
return date
}
四,生成随机数
export const getUUID = function getUUID(len = 6, prefix = '') {
if (len < 1 || len > 48) {
len = 6
}
len = Number.isNaN(len) ? 6 : len
const seed = '0123456789abcdefghijklmnopqrstubwxyzABCEDFGHIJKLMNOPQRSTUVWXYZ'
const seedLen = seed.length - 1
let uuid = ''
// eslint-disable-next-line no-plusplus
while (len--) {
uuid += seed[Math.round(Math.random() * seedLen)]
}
return prefix + uuid
}
五,根据数组生成tree结构
export const setTreeData = function setTreeData(list: any, option: any) {
const nlist = list
const len = nlist.length
const defaultOption: any = {
rootId: '0', // rootId 的key
key: 'id', // id的key
pKey: 'pid', // pid的key
// titleKey: 'title', // 重新设置key-value防止树找不到key
// setTitleByKey: 'name' // 根据数据的key
}
if (option && option.titleKey && option.setTitleByKey) {
// eslint-disable-next-line no-plusplus
for (let i = 0; i < len; i++) {
nlist[i][option.titleKey] = nlist[i][option.setTitleByKey]
}
}
// 合并参数
if (option) {
for (const k in option) {
defaultOption[k] = option[k]
}
}
const result = []
const itemMap: any = {}
for (const item of nlist) {
const id = item[defaultOption.key]
const pid = item[defaultOption.pKey]
if (!itemMap[id]) {
itemMap[id] = {
children: [],
}
}
itemMap[id] = {
...item,
children: itemMap[id].children,
}
const treeItem = itemMap[id]
if (pid === defaultOption.rootId) {
result.push(treeItem)
} else {
if (!itemMap[pid]) {
itemMap[pid] = {
children: [],
}
}
itemMap[pid].children.push(treeItem)
}
}
return result
}
六,判断两个对象是否完全相等 数组去重 数字滚动效果
// 判断两个对象是否相等
export const dataischange = function dataischange(e1: object, s1: object) {
let ischange = false
function f(e: any, s: any) {
for (const k in e) {
if (e[k] && typeof e[k] === 'object') {
f(e[k], s[k])
} else {
// 判断参数发生了变化
// eslint-disable-next-line no-lonely-if
if (e[k] !== s[k]) {
ischange = true
return
}
}
}
}
f(e1, s1)
return ischange
}
// 数组去重
export const uniqueArr = function uniqueArr(array: []) {
const n: any = [] // 一个新的临时数组
// 遍历当前数组
// eslint-disable-next-line no-plusplus
for (let i = 0; i < array.length; i++) {
// 如果当前数组的第i已经保存进了临时数组,那么跳过,
// 否则把当前项push到临时数组里面
if (n.indexOf(array[i]) === -1) n.push(array[i])
}
return n
}
// 数组项为对象时,采用对象key-value进行去重
export const uniqueArrWithKey = function uniqueArrWithKey(
array: any,
key: string | number
) {
const n = []
const r = [] // 一个新的临时数组
// 遍历当前数组
// eslint-disable-next-line no-plusplus
for (let i = 0; i < array.length; i++) {
// 如果当前数组的第i已经保存进了临时数组,那么跳过,
// 否则把当前项push到临时数组里面
if (n.indexOf(array[i][key]) === -1) {
n.push(array[i][key])
r.push(array[i])
}
}
return r
}
// 数字滚动效果
export const scrollToNum = function scrollToNum(el: any, orgin: any, target: any, time = 1) {
const increase = target - orgin > 0
let speed = 1
speed = increase ? speed : -speed
el.innerText = orgin
let intervalTime = (time * 1000) / ((target - orgin) / speed)
if (intervalTime < 10) {
intervalTime = 10
speed = (target - orgin) / ((time * 1000) / intervalTime)
}
const timer = setInterval(() => {
orgin += speed
el.innerText = parseInt(orgin, 10)
if ((increase && orgin >= target) || (!increase && orgin <= target)) {
el.innerText = parseInt(target, 10)
clearInterval(timer)
}
}, intervalTime)
}
七,验证身份证号 的两种方式, 验证手机号
// 验证身份证号
export const checkIdcard = function checkIdcard(idcard: string) {
const checkProv = function checkProv(val: string) {
const pattern = /^[1-9][0-9]/
const provs: any = {
11: '北京',
12: '天津',
13: '河北',
14: '山西',
15: '内蒙古',
21: '辽宁',
22: '吉林',
23: '黑龙江 ',
31: '上海',
32: '江苏',
33: '浙江',
34: '安徽',
35: '福建',
36: '江西',
37: '山东',
41: '河南',
42: '湖北 ',
43: '湖南',
44: '广东',
45: '广西',
46: '海南',
50: '重庆',
51: '四川',
52: '贵州',
53: '云南',
54: '西藏 ',
61: '陕西',
62: '甘肃',
63: '青海',
64: '宁夏',
65: '新疆',
71: '台湾',
83: '台湾',
81: '香港',
82: '澳门',
}
if (pattern.test(val)) {
if (provs[val]) {
return true
}
}
return false
}
const checkDate = function checkDate(val: string) {
const pattern =
/^(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)$/
if (pattern.test(val)) {
const year = val.substring(0, 4)
const month = val.substring(4, 6)
const date = val.substring(6, 8)
const date2 = new Date(`${year}-${month}-${date}`)
if (date2 && date2.getMonth() === parseInt(month, 10) - 1) {
return true
}
}
return false
}
const checkCode = function checkCode(val: string) {
const p =
/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
const factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
const parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2]
const code = val.substring(17)
if (p.test(val)) {
let sum = 0
// eslint-disable-next-line no-plusplus
for (let i = 0; i < 17; i++) {
sum += (val[i] as any) * factor[i]
}
if (parity[sum % 11] === code.toUpperCase()) {
return true
}
}
return false
}
const checkID = function checkID(val: string) {
if (checkCode(val)) {
const date = val.substring(6, 14)
if (checkDate(date)) {
if (checkProv(val.substring(0, 2))) {
return true
}
}
}
return false
}
return checkID(idcard)
}
export const isValidIdCard = function (idCard: string, isIdCard?: boolean) {
if (!isIdCard) return true
let ret = false
const w: any = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
if (idCard.length === 18) {
// 身份证号码长度必须为18,只要校验位正确就算合法
const crc = idCard.substring(17)
// eslint-disable-next-line no-array-constructor
const a = []
let sum = 0
// eslint-disable-next-line no-plusplus
for (let i = 0; i < 17; i++) {
a.push(idCard.substring(i, i + 1))
sum += parseInt(a[i], 10) * parseInt(w[i], 10)
// alert(a[i]);
}
sum %= 11
let res = '-1'
// eslint-disable-next-line default-case
switch (sum) {
case 0: {
res = '1'
break
}
case 1: {
res = '0'
break
}
case 2: {
res = 'X'
break
}
case 3: {
res = '9'
break
}
case 4: {
res = '8'
break
}
case 5: {
res = '7'
break
}
case 6: {
res = '6'
break
}
case 7: {
res = '5'
break
}
case 8: {
res = '4'
break
}
case 9: {
res = '3'
break
}
case 10: {
res = '2'
break
}
}
if (crc.toLowerCase() === res.toLowerCase()) {
ret = true
}
// ret=true;
}
/*
else if(idCard.length == 15){
//15位的身份证号,只验证是否全为数字
var pattern = /\d/;
ret=pattern.test(idCard);
} */
return ret
}
// 验证手机号码
export const checkMobilePhoneNumber = function checkMobilePhoneNumber(
phone: string
) {
if (/^1[3456789]\d{9}$/.test(phone)) {
return true
}
return false
}
八,文件转为链接,base64转为blob,blob转为file,
// 文件转成链接
export const getObjectURL = function getObjectURL(file: any) {
let url = null
if (window.createObjectURL !== undefined) {
// basic
url = window.createObjectURL(file)
} else if (window.URL !== undefined) {
// mozilla(firefox)
url = window.URL.createObjectURL(file)
} else if (window.webkitURL !== undefined) {
// webkit or chrome
url = window.webkitURL.createObjectURL(file)
}
return url
}
// 将base64转换为blob
export const dataURLtoBlob = function dataURLtoBlob(dataurl: any) {
const arr = dataurl.split(',')
const mime = arr[0].match(/:(.*?);/)[1]
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
// eslint-disable-next-line no-plusplus
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], { type: mime })
}
// 将blob转换为file
export const blobToFile = function blobToFile(theBlob: any, fileName?: any) {
theBlob.lastModifiedDate = new Date()
theBlob.name =
fileName || getUUID(32) + (theBlob.type && `.${theBlob.type.split('/')[1]}`)
return theBlob
}
// 该方法需要调取上面两个方法
// base64转file
export const base64ToFile = function base64ToFile(base64: any) {
return blobToFile(dataURLtoBlob(base64))
}
// 将base64转换为File ie下有bug
export function base64ToFileNoIe(dataurl: any, fileName: string) {
const arr = dataurl.split(',')
const mime = arr[0].match(/:(.*?);/)[1]
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
const newFileName =
fileName || getUUID(32) + (mime && `.${mime.split('/')[1]}`)
// eslint-disable-next-line no-plusplus
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], newFileName, { type: mime })
}
/**
* 根据图片的url转换对应的base64值
* @param { String } imageUrl 如:http://xxxx/xxx.png
* @returns base64取值
*/
export async function urlToBase64(imageUrl: string) {
return new Promise((resolve, reject) => {
let canvas: HTMLCanvasElement | null = document.createElement('canvas')
const ctx: CanvasRenderingContext2D | null = canvas.getContext('2d')
let img: HTMLImageElement | null = new Image()
img.crossOrigin = 'Anonymous' // 解决Canvas.toDataURL 图片跨域问题
img.src = imageUrl
img.onload = function () {
canvas!.height = img!.height
canvas!.width = img!.width
ctx!.fillStyle = '#fff' // canvas背景填充颜色默认为黑色
ctx!.fillRect(0, 0, img!.width, img!.height)
ctx!.drawImage(img!, 0, 0) // 参数可自定义
const dataURL = canvas!.toDataURL('image/jpeg', 1) // 获取Base64编码
resolve(dataURL)
canvas = null // 清除canvas元素
img = null // 清除img元素
}
img.onerror = function () {
reject(new Error(`Could not load image at ${imageUrl}`))
}
})
}
九,判断某个数字是否为质数 及 某个自然数中的质数的个数
// 判断是否质数
export function isZhishu(num: any) {
if (typeof num !== 'number') return new Error(`${num} is not a number`)
if (Math.abs(num) > Number.MAX_SAFE_INTEGER)
return new Error(`${num} is a overnum`)
const end = Math.sqrt(Math.abs(num))
// eslint-disable-next-line no-plusplus
for (let i = 2; i <= end; i++) {
if (num % i === 0) {
return false
}
}
return true
}
// 某个自然数中的质数个数
export function allZshishuInNum(num: any) {
if (typeof num !== 'number') return new Error(`${num} is not a number`)
if (Math.abs(num) > Number.MAX_SAFE_INTEGER)
return new Error(`${num} is a overnum`)
if (num === 2) return [2]
if (num === 3) return [2, 3]
const arr = [2, 3]
for (let i = 3; i <= num; i += 2) {
// eslint-disable-next-line no-plusplus
for (let j = 1; j < arr.length; j++) {
if (i % arr[j] !== 0) {
if (j === arr.length - 1) {
arr.push(i)
}
} else {
break
}
}
}
return arr
}
十,其它
// 时间戳转化为对应时间格式
// eslint-disable-next-line consistent-return
export const parseStamp = function parseStamp(
stamp = '' as string | number,
toDay = 0
) {
let date = null
if (!stamp) {
date = new Date()
} else {
date = new Date(stamp)
}
const year: any = date.getFullYear()
let month: any = date.getMonth() + 1
let day: any = date.getDate()
const week: any = date.getDay()
let hour: any = date.getHours()
let min: any = date.getMinutes()
let sec: any = date.getSeconds()
if (month < 10) month = `0${month}`
if (day < 10) {
if (toDay === 7) {
day = `0${day - 1}`
} else {
day = `0${day}`
}
} else if (day >= 10 && toDay === 7) {
day -= 1
} else if (day >= 10 && toDay !== 7) {
// eslint-disable-next-line no-self-assign
day = day
}
let weekData = ''
switch (week) {
case 1:
weekData = '星期一'
break
case 2:
weekData = '星期二'
break
case 3:
weekData = '星期三'
break
case 4:
weekData = '星期四'
break
case 5:
weekData = '星期五'
break
case 6:
weekData = '星期六'
break
case 7:
weekData = '星期日'
break
default:
weekData = ''
break
}
if (hour < 10) hour = `0${hour}`
if (min < 10) min = `0${min}`
if (sec < 10) sec = `0${sec}`
if (toDay === 1) {
// eslint-disable-next-line no-useless-concat
return `${year}-${month}-${day} ` + `00:00:00`
}
if (toDay === 2) {
// eslint-disable-next-line no-useless-concat
return `${year}-${month}-${day} ` + `23:59:59`
}
if (toDay === 3) {
return `${year}-${month}-${day}`
}
if (toDay === 4) {
// eslint-disable-next-line no-useless-concat
return `${year}${month}${day}` + `000000`
}
if (toDay === 5) {
// eslint-disable-next-line no-useless-concat
return `${year}${month}${day}` + `235959`
}
if (toDay === 6) {
return `${year}${month}`
}
if (toDay === 7) {
return new Date(`${year}/${month}/${day}`)
// eslint-disable-next-line eqeqeq
}
if (toDay === 8) {
return year + month
}
if (toDay === 9) {
return `${year}${month}`
}
if (toDay === 10) {
return `${year}-${month}-${day} ${hour}:${min}:${sec}`
}
if (toDay === 11) {
return `${year}/${month}/${day} ${hour}:${min}:${sec} ${weekData}`
}
}
// 根据生日查询年龄
export default function getAge(strBirthday: string): number | string {
let returnAge: number = 0
const [bornYear, bornMoon, bornDay] = strBirthday.split('-')
const nowDate = new Date()
const nowYear = nowDate.getFullYear()
const nowMoon = nowDate.getMonth() + 1
const nowDay = nowDate.getDate()
if (Number(bornYear) === nowYear) {
returnAge = 0
if (Number(bornMoon) > nowMoon) return ''
if (Number(bornMoon) === nowMoon && Number(bornDay) > nowDay) return ''
} else if (Number(bornYear) < nowYear) {
returnAge = nowYear - Number(bornYear)
if (Number(bornMoon) > nowMoon) returnAge -= 1
else if (Number(bornMoon) === nowMoon && Number(bornDay) > nowDay)
returnAge -= 1
} else return ''
return returnAge
}
// 根据身份证查询年龄
export function calculateAge(idNumber: string) {
// 截取身份证号中的出生日期
const birthdayStr = idNumber.slice(6, 14)
// 将出生日期转换为Date对象
const year = parseInt(birthdayStr.slice(0, 4), 10)
const month = parseInt(birthdayStr.slice(4, 6), 10) - 1 // 月份需要减去1,因为月份从0开始计数
const day = parseInt(birthdayStr.slice(6, 8), 10)
const birthday = new Date(year, month, day)
// 获取当前日期
const now = new Date()
// 计算年龄
let age = now.getFullYear() - birthday.getFullYear()
// 如果当前日期小于出生日期,年龄减1
if (
now.getMonth() < birthday.getMonth() ||
(now.getMonth() === birthday.getMonth() &&
now.getDate() < birthday.getDate())
) {
// eslint-disable-next-line no-plusplus
age--
}
return age
}
/**
* @description 从源对象复制属性值到目标对象
* @author Cola
* @param {object} target 目标对象
* @param {object} origin 源对象
* @param {array | undefined} keys 嵌套的key值
* @example target: {a: {value: 1}} origin: {a: 1} keys: ['value']
*/
export const setObjAttrVal = (
target: any,
origin: any,
keys: [] | undefined
) => {
for (const key in target) {
const val = origin[key]
if (key in origin) {
if (keys) {
keys.reduce((p, n, i) => {
if (i === keys.length - 1) {
p[keys[keys.length - 1]] = val
}
return p[n]
}, target[key])
} else {
target[key] = val
}
}
}
return target
}
/**
* 参数一: url
* 参数二: 要截取参数名
*/
export const getQueryVariable = function getQueryVariable(
query: any,
variable: any
) {
query = query || document.location.search
let vars = query.split('?')[1]
vars = vars.split('&')
// eslint-disable-next-line no-plusplus
for (let i = 0; i < vars.length; i++) {
const pair = vars[i].split('=')
if (pair[0] === variable) {
return pair[1]
}
}
return undefined
}
到此总结结束,如果对你有帮助的话,谢谢点赞。(欢迎评论区留言,指出不足。)