在项目开发中,我们经常会使用一些工具函数,也经常会用到例如loadsh
等工具库,但是这些工具库的体积往往比较大,如果项目本身已经引入了这些工具库,那么我们就没有必要再引入一次,所以我们需要自己封装一些工具函数,来简化我们的开发。
在
src/utils
目录下创建tools
文件夹,用于存放通用类工具函数文件。
在tools
文件下创建index.ts
文件
import { ElMessage, MessageHandler } from 'element-plus'
/**
* @description 文档注册enter事件
* @param {Function} cb
* @return {void}
*/
export function handleEnter(cb: Function): void {
if (typeof cb !== 'function')
return
document.onkeydown = (e) => {
const ev: KeyboardEventInit = e || window.event
const keyCode = ev.code || ev.keyCode
if (keyCode === 'Enter' || keyCode === 13)
cb()
}
}
/**
* @description 日期格式化
* @param {string | number} time {string like:{y}-{m}-{d} {h}:{i}:{s} } pattern
* @return {string}
*/
export function parseTime(time: string | number, pattern: string) {
if (arguments.length === 0 || !time)
return null
const format = pattern || '{y}-{m}-{d}'
let date
if (typeof time === 'object') {
date = time
}
else {
if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
time = Number.parseInt(time)
}
else if (typeof time === 'string') {
time = time
.replace(new RegExp(/-/gm), '/')
.replace('T', ' ')
.replace(new RegExp(/\.[\d]{3}/gm), '')
}
if (typeof time === 'number' && time.toString().length === 10)
time = time * 1000
date = new Date(time)
}
const formatObj: Record<string, string> = {
y: date.getFullYear(), // 年
m: date.getMonth() + 1, // 月
d: date.getDate(), // 日
h: date.getHours(), // 时
i: date.getMinutes(), // 分
s: date.getSeconds(), // 秒
a: date.getDay(), // 星期几
}
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key]
// 注意:getDay()返回的是0表示星期天
if (key === 'a')
return ['日', '一', '二', '三', '四', '五', '六'][value]
if (result.length > 0 && Number(value) < 10)
value = `0${value}`
return value || 0
})
return time_str
}
/**
* @description trim函数
* @param {string} str
* @return {string}
*/
export function trim(str: string): string {
return str.replace(/^\s+|\s+$/g, '') // 去除字符串两端的空格
}
/**
* @description uuid的生成
* @return {string}
*/
/**
* @description 生成UUID
* @return {string}
*/
export function getUUID(): string {
const s: string[] = []
const hexDigits = '0123456789abcdef'
for (let i = 0; i < 36; i++) {
s[i] = hexDigits[Math.floor(Math.random() * 0x10)]
}
s[14] = '4'
s[19] = hexDigits[(parseInt(s[19], 16) & 0x3) | 0x8]
s[8] = s[13] = s[18] = s[23] = '-'
const uuid = s.join('')
return uuid
}
// 38673f6b-bacc-4d9b-9330-dd97b7ae238f
/**
* @description 千分位
* @param {string | number} num
* @return {void}
*/
export function addThousand(num: string | number): string {
if (num)
num = Number(num).toFixed(2)
if ((!num && num !== 0) || num == 'NaN')
return '--'
const regForm = /(\d{1,3})(?=(\d{3})+(?:$|\.))/g
num = num.toString().replace(regForm, '$1,')
return num
}
/**
* @description 大数值转换和保留n位有效数字
* @param {number} num {number} digits
* @return {string}
*/
export function numberFormatter(num: number, digits: number | undefined): string {
const si = [
{ value: 1e13, symbol: '亿亿' },
{ value: 1e12, symbol: '万亿' },
{ value: 1e11, symbol: '千亿' },
{ value: 1e10, symbol: '百亿' },
{ value: 1e9, symbol: '十亿' },
{ value: 1e8, symbol: '亿' },
{ value: 1e7, symbol: '千万' },
{ value: 1e6, symbol: '百万' },
{ value: 1e5, symbol: '十万' },
{ value: 1e4, symbol: '万' },
{ value: 1e3, symbol: '千' },
]
for (let i = 0; i < si.length; i++) {
if (num >= si[i].value)
return (num / si[i].value).toFixed(digits).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + si[i].symbol
}
return num.toString()
}
/**
* @description 复制方法
* @param {string} value 传入要复制的值
* @return {string | MessageHandler}
*/
export const copy = (value: string): string | MessageHandler => {
if (!value)
return ElMessage.error('复制失败')
const tag = document.createElement('textarea')
tag.value = value
document.body.appendChild(tag)
tag.select()
document.execCommand('copy')
ElMessage.success('复制成功')
tag.remove()
return value
}
/**
* @description 防抖
* @param {number} timer
* @return {function}
*/
export function debounce(timer = 0): (callback: unknown, delay: number) => void {
return (callback: unknown, delay: number) => {
if (timer)
clearTimeout(timer)
if (typeof callback === 'function')
timer = setTimeout(callback, delay)
}
}
/**
* @description 节流
* @param {number} timer
* @return {function}
*/
export const throttle: (fn: (...args: unknown[]) => void, timer: number) => (...args: unknown[]) => void = (fn, timer = 0) => {
let time: number | null = null
return (...args: unknown[]) => {
if (time)
clearTimeout(time)
time = setTimeout(() => {
fn.apply(this, args)
}, timer)
}
}
在
tools
文件下创建blobType.ts
文件
export const blobType: Record<string, string> = {
'aac': 'image/audio/aac',
'abw': 'application/x-abiword',
'arc': 'application/x-freearc',
'avi': 'video/x-msvideo',
'azw': 'application/vnd.amazon.ebook',
'bin': 'application/octet-stream',
'bmp': 'image/bmp',
'bz': 'application/x-bzip',
'bz2': 'application/x-bzip2',
'csh': 'application/x-csh',
'css': 'text/css',
'csv': 'text/csv',
'doc': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'eot': 'application/vnd.ms-fontobject',
'epub': 'application/epub+zip',
'exe': 'application/x-msdownload',
'gif': 'image/gif',
'htm': 'text/html',
'html': 'text/html',
'ico': 'image/vnd.microsoft.icon',
'ics': 'text/calendar',
'jar': 'application/java-archive',
'jpeg': 'image/jpeg',
'jpg': 'image/jpeg',
'js': 'text/javascript',
'json': 'application/json',
'jsonld': 'application/ld+json',
'mid': 'audio/midi audio/x-midi',
'midi': 'audio/midi audio/x-midi',
'mjs': 'text/javascript',
'mp3': 'audio/mpeg',
'mpeg': 'video/mpeg',
'mpkg': 'application/vnd.apple.installer+xml',
'odp': 'application/vnd.oasis.opendocument.presentation',
'ods': 'application/vnd.oasis.opendocument.spreadsheet',
'odt': 'application/vnd.oasis.opendocument.text',
'oga': 'audio/ogg',
'ogv': 'video/ogg',
'ogx': 'application/ogg',
'otf': 'font/otf',
'png': 'image/png',
'pdf': 'application/pdf',
'ppt': 'application/vnd.ms-powerpoint',
'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'rar': 'application/x-rar-compressed',
'rtf': 'application/rtf',
'sh': 'ima',
'svg': 'image/svg+xml',
'swf': 'application/x-shockwave-flash',
'tar': 'application/x-tar',
'tif': 'image/tiff',
'tiff': 'image/tiff',
'ttf': 'font/ttf',
'txt': 'text/plain',
'vsd': 'application/vnd.visio',
'wav': 'audio/wav',
'weba': 'audio/webm',
'webm': 'video/webm',
'webp': 'image/webp',
'woff': 'font/woff',
'woff2': 'font/woff2',
'xhtml': 'application/xhtml+xml',
'xls': 'application/vnd.ms-excel',
'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'xml': 'text/xml',
'xul': 'application/vnd.mozilla.xul+xml',
'zip': 'application/zip',
'3gp': 'video/3gpp',
'3g2': 'video/3gpp2',
'7z': 'application/x-7z-compressed',
}
在
tools
文件下创建file.ts
文件
import { ElMessage } from 'element-plus'
import { blobType } from './blobType'
export function download(file: any, fileType: string, fileName?: string) {
if (!fileName) {
const timeStr = new Date().getTime()
fileName = `${timeStr}`
}
const type = formatFileType(fileType)
if (!type)
return ElMessage.warning('暂不支持此格式!')
const blob = new Blob([file], { type })
const downloadElement = document.createElement('a')
const href = window.URL.createObjectURL(blob) // 创建下载的链接
downloadElement.href = href
downloadElement.download = fileName // 下载后文件名
document.body.appendChild(downloadElement)
downloadElement.click() // 点击下载
document.body.removeChild(downloadElement) // 下载完成移除元素
window.URL.revokeObjectURL(href) // 释放掉blob对象
}
export function formatFileType(fileFormat: string) {
return blobType[fileFormat]
}
export function blobToFileReader(blob: any, callback: any) {
if (!blob.size)
return ElMessage.warning('暂无资源!')
if (blob.type !== 'application/json')
return callback(blob)
const fr: any = new FileReader()
fr.onloadend = function () {
try {
callback(JSON.parse(fr.result))
}
catch (err) {
ElMessage.warning('资源数据有误!')
}
}
fr.readAsText(blob)
}
在
src/utils
目录下创建cache
文件夹,用于存放存储类工具函数文件。
在cache
文件夹下创建index.ts
文件
/**
* window.localStorage 浏览器永久缓存
* @method set 设置永久缓存
* @method get 获取永久缓存
* @method remove 移除永久缓存
* @method clear 移除全部永久缓存
*/
export const Local = {
// 设置永久缓存
set(key: string, val: any) {
window.localStorage.setItem(key, JSON.stringify(val))
},
// 获取永久缓存
get(key: string) {
const json: any = window.localStorage.getItem(key)
return JSON.parse(json)
},
// 移除永久缓存
remove(key: string) {
window.localStorage.removeItem(key)
},
// 移除全部永久缓存
clear() {
window.localStorage.clear()
},
}
/**
* window.sessionStorage 浏览器临时缓存
* @method set 设置临时缓存
* @method get 获取临时缓存
* @method remove 移除临时缓存
* @method clear 移除全部临时缓存
*/
export const Session = {
// 设置临时缓存
set(key: string, val: any) {
window.sessionStorage.setItem(key, JSON.stringify(val))
},
// 获取临时缓存
get(key: string) {
const json: any = window.sessionStorage.getItem(key)
return JSON.parse(json)
},
// 移除临时缓存
remove(key: string) {
window.sessionStorage.removeItem(key)
},
// 移除全部临时缓存
clear() {
window.sessionStorage.clear()
},
}
工具函数的封装,可以提高代码的复用性,降低维护成本,本文只是介绍了一小部分工具函数的封装,更多的工具函数的封装,可以参考lodash等函数工具库,也可以根据实际需求,封装自己的工具函数。上文中的配置代码可在 github
仓库中直接 copy
,仓库路径:https://github.com/SmallTeddy/ProjectConstructionHub。
经过一段时间的整理和书写,前端新手Vue3+Vite+Ts+Pinia+Sass项目指北系列文章已经全部更新完了,感谢各位小伙伴的支持与厚爱,文章中可能有一些依赖部分会有所更新,最后依赖版本号请参考仓库中的地址进行对照。前端道路道阻且长,富而杂,多而繁,请各位取长补短,各自努力绽放。