正则相关
金额千分位分隔符
num = 1234567.01
regNum = String(num).replace(/(\d{1,3})(?=(\d{3})+(?:$|\.))/g, "$1,")
console.log(regNum); //1,234,567.01
小数的校验
const floatReg = /^[-\+]?\d+(\.\d+)?$/
const floatNum = '-1234.68'
const errorNum = '-1234.6.8'
console.log(floatReg.test(floatNum)) // true
console.log(floatReg.test(errorNum)) // false
校验手机号码
const phoneReg = /^[1][3-9][0-9]{9}$/
const phone1 = '13032326767'
console.log(phoneReg.test(phone1)) // true
const phone2 = '12830172038'
console.log(phoneReg.test(phone2)) // false
身份证号码的校验
const sfzReg = /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
const sfzStr1 = '415106199601013214'
console.log(sfzReg.test(sfzStr1)) // true
const sfzStr2 = '21078119830121218X'
console.log(sfzReg.test(sfzStr2)) // true
邮箱格式校验
const emailReg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/
const emailSina = 'pass_1@sina.com' // 新浪邮箱
const email163 = 'fe_vue@163.com' // 163邮箱
const notEmail = 'test.com' // 错误邮箱
console.log(emailReg.test(emailSina)) // true
console.log(emailReg.test(email163)) // true
console.log(emailReg.test(notEmail)) // false
密码校验
长度为8-16位,包含大小写字母、数字和特殊字符
const passwordReg = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,16}$/
const passwordStr = 'w123W!@4123'
const illegalStr = 'w123W4123412'
console.log(passwordReg.test(passwordStr)); // true
console.log(passwordReg.test(illegalStr)); // false
检测文件格式
const checkFileName = arr => new RegExp(`(${arr.map(name => `.${name}`).join('|')})$`)
// 检测是否为 .txt, .png 或者 .md 文件格式
const filenameReg = checkFileName(['txt', 'png', 'md'])
const jpgFile = 'sun.jpg'
const pngFile = 'sun.png'
const txtFile = 'sun.txt'
const mdFile = 'sun.md'
console.log(filenameReg.test(jpgFile)) // false
console.log(filenameReg.test(pngFile)) // true
console.log(filenameReg.test(txtFile)) // true
console.log(filenameReg.test(mdFile)) // true
清除对象中的空值
向后台请求数据时,入参是一个对象,对象中有空值时需要清除掉.(看前后端约定,也可以后台同学做处理,不过最好前后端都处理)
/**
* 判断值是否为空
*/
const isVoid = (value) =>
value === undefined || value === null || value === ""
const cleanObject = (object) => {
if (!object) {
return {}
}
const result = { ...object };
const excute = obj => Object.keys(obj).forEach((key) => {
const value = obj[key]
typeof value === 'object' && value !== null && excute(value)
isVoid(value) && delete obj[key]
})
excute(result)
return result
}
防抖
平时开发中,会有很多场景会频繁触发事件,比如说搜索框实时发请求. 短时间内多次触发同一事件,只执行最后一次,中间的不执行。
/**
* 非立即执行版
*/
function debounce(func, wait) {
let timer;
return function() {
// this 指向
let context = this;
let args = arguments;
if (timer) clearTimeout(timer);
timer = setTimeout(function() {
func.apply(context, args)
timer = null
}, wait)
}
}
立即执行版的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果
/**
* 立即执行版
*/
function debounce(func, wait) {
let timer
return function() {
// this 指向
let context = this
let args = arguments
if (timer) clearTimeout(timer)
let callNow = !timer
timer = setTimeout(() => {
timer = null
}, wait)
callNow && func.call(context, ...args)
}
}
合成版本
/**
* @desc 函数防抖
* @param func 目标函数
* @param wait 延迟执行毫秒数
* @param immediate true - 立即执行, false - 延迟执行
*/
function debounce(func, wait, immediate = false) {
let timer
return function() {
let context = this,
args = arguments
if (timer) clearTimeout(timer);
if (immediate) {
let callNow = !timer
timer = setTimeout(() => {
timer = null;
}, wait);
if (callNow) func.apply(context, args);
} else {
timer = setTimeout(() => {
func.apply(context, args);
timer = null
}, wait)
}
}
}
节流
平时开发中,会有很多场景会频繁触发事件,比如拖动改变浏览器窗口.
时间戳版本, 首节流
function throttle(func, wait) {
let previous = 0;
return function() {
let now = Date.now();
let context = this;
let args = arguments;
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
}
}
定时器版本,尾节流
function throttle(func, wait) {
let timer
return function() {
let context = this
let args = arguments
if (!timer) {
timer = setTimeout(() => {
timer = null
func.apply(context, args)
}, wait)
}
}
}
完整版(时间戳 + 定时器)
/**
* @desc 函数节流
* @param func 函数
* @param wait 延迟执行毫秒数
*/
function throttle(func, wait) {
let timer = null, previous = 0
return function() {
let remainTime = wait - Date.now() - previous
let context = this
let args = arguments
const excute = () => {
func.apply(context, args)
previous = Date.now()
}
timer && clearTimeout(timer)
if(remainTime <= 0) {
excute()
} else {
timer = setTimeout(() => {
excute()
timer = null
}, remainTime)
}
}
}
深拷贝
const isObject = val => typeof val === "object" && val !== null;
const deepClone = (obj, hash = new WeakMap()) => {
if (!isObject(obj)) return obj;
// 日期对象直接返回一个新的日期对象
if (obj instanceof Date){
return new Date(obj);
}
//正则对象直接返回一个新的正则对象
if (obj instanceof RegExp){
return new RegExp(obj);
}
//如果循环引用,就用 weakMap 来解决
if (hash.has(obj)){
return hash.get(obj);
}
const target = Array.isArray(obj) ? [] : {};
hash.set(obj, target);
Reflect.ownKeys(obj).forEach(item => {
if (isObject(obj[item])) {
target[item] = deepClone(obj[item], hash);
} else {
target[item] = obj[item];
}
});
return target;
};
export default deepClone
前端文件下载
通常有2种方式
- 后端给一个链接,直接通过 window.open(url)打开即可下载,这种通常适用于这个链接可以在公网访问,不需要token鉴权。
- 后端给一个接口,通过传参请求接口,后端返回一个文件流,前端处理文件流,通过a标签下载。
// 要预先安装axios
import axios from 'axios'
export default options => {
const { url, method = 'get', params, fileName = '' } = options;
const data = method === 'get' ? { params } : { data: params };
const config = {
url,
method,
data,
responseType: "blob",
};
return new Promise((resolve, reject) => {
axios(config)
.then(res => {
if (res.data.size > 0) {
let userFileName = ''
if (!fileName) {
userFileName = res.headers['content-disposition'].split('filename=')[1]
if (userFileName && userFileName.includes('"')) userFileName = userFileName.slice(1, -1);
} else {
userFileName = fileName
}
// 获取文件格式
const contentType = res.headers['content-type']
const blob = new Blob([res.data], { type: contentType })
const downloadElement = document.createElement('a')
// 创建下载的链接
const href = window.URL.createObjectURL(blob)
downloadElement.href = href
// 下载后文件名
downloadElement.download = !userFileName ? Date.now().toString() : userFileName
document.body.appendChild(downloadElement)
// 点击下载
downloadElement.click()
// 下载完成移除元素
document.body.removeChild(downloadElement)
// 释放掉blob对象
window.URL.revokeObjectURL(href)
resolve(res)
} else {
console.error('Data is null!')
}
})
.catch(function (error) {
return reject(error)
})
})
}