💡 在前端的方法使用中,一些未被封装,但是常用的方法的总结
工具类方法
保留小数精度问题
/**
- @param {number | string} num 数值
- @param {number | string} percision 精度,保留几位小数
- @return 保留小数后的字符串
*/
function numberWithPercision(num, percision = 0) {
if (isNaN(num) || isNaN(percision) || percision < 0 || percision > 100) {
return ‘’;
}
percision = Number(percision);
if (percision === 0) {
return Math.round(num).toString();
}
const sign = num >= 0 ? ‘’ : ‘-’;
let tNum = Math.abs(num).toString();
const [integer, decimals = ‘’] = tNum.split(‘.’);
const decimalsLen = decimals.length;
if (percision >= decimalsLen) {
return sign + integer + ‘.’ + decimals + ‘0’.repeat(percision - decimalsLen);
}
tNum = Math.round(integer + decimals.substr(0, percision) + ‘.’ +
decimals.substr(percision - decimalsLen)).toString();
tNum = tNum.padStart(integer.length + percision, ‘0’);
const len = tNum.length - percision;
return sign + tNum.substr(0, len) + ‘.’ + tNum.substr(len);
}
日期format
/**
-
@param {string | Date} date 日期
-
@param {string | Array} format 分隔符 或 年月日
-
@return {string} 格式化日期 或 完整年月日日期
*/
function formatDate(date, format = ‘-’) {
if (!date) {
return ‘’;
}let year = ‘’;
let month = ‘’;
let day = ‘’;
if (date instanceof Date) {
year = date.getFullYear();month = date.getMonth() + 1; if (month < 10) { month = '0' + month; } day = date.getDate(); if (day < 10) { day = '0' + day; }
} else {
const dateStr = date.replace(/[^0-9]/g, ‘’);year = dateStr.slice(0, 4); month = dateStr.slice(4, 6); day = dateStr.slice(6);
}
if (!Array.isArray(format)) {
return year + format + month + (day ? format + day : ‘’);
}const [yearStr, monthStr, dayStr] = format;
return (yearStr ? year + yearStr : ‘’) +
(monthStr ? month + monthStr : ‘’) +
(dayStr ? day + dayStr : ‘’);
}
// e.g.
formatDate(new Date(), ‘’); // 20231001
formatDate(new Date(), ‘-’); // 2023-10-01
formatDate(‘20231001’, ‘/’); // 2023/10/01
formatDate(new Date(), [‘年’, ‘月’, ‘日’]); // 2023年10月01日
formatDate(‘20231001’, [‘年’, ‘月’]); // 2023年10月
formatDate(‘20231001’, [‘’, ‘月’, ‘日’]); // 10月01日
时间format
/**
- @param {Date} date 日期
- @param {string} format 分隔符
- @return {string} 格式化时间
*/
function getHMS = (date: Date, format = ‘:’) {
return [
date.getHours().toString().padStart(2, ‘0’),
date.getMinutes().toString().padStart(2, ‘0’),
date.getSeconds().toString().padStart(2, ‘0’),
].join(format);
}
填充内容保留两位小数format
/**
- @param {string} value 需要保留两位小数的输入内容
- @return 保留两位小数的字符串
/
function formatValueReg(value) {
return value
.replace(/[^\d.]/g, ‘’)
.replace(‘.’, ‘KaTeX parse error: Expected 'EOF', got '#' at position 1: #̲’)
.replace(/./g, ‘’)
.replace(‘KaTeX parse error: Expected 'EOF', got '#' at position 1: #̲’, ‘.’)
.replace(/.{2,}/g, ‘.’)
.replace(/^(-)(\d+).(\d\d).*$/, ‘$1$2.$3’);
}
倒计时
/**
- @param {number} time 倒计时时长,单位s
- @return
*/
function countDown(time) {
let t = time;
let timer;
return {
minus: (callback) => {
timer = setInterval(() => {
t --;
callback(t);
if (t <= 0) {
clearInterval(timer);
timer = undefined;
}
}, 1000);
},
clear: () => {
if (timer) {
clearInterval(timer);
timer = undefined;
}
}
}
}
// 使用示例
isSendingSms = true;
const cd = countDown(60);
cd.minus((t) => {
// 保证再次调用时,清除上一次的倒计时
if (!isSendingSms) {
cd.clear();
return;
}
smsCountDown = t;
if (t <= 0) {
reset(‘重新发送’);
}
});
获取相对某个日期的方法
/**
- @param {Date} date 日期值
- @param {number} year 增减年份,增为正,减为负
- @param {number} month 增减月份,增为正,减为负
- @param {number} day 增减日期,增为正,减为负
- @return {Date} 日期
*/
function getDate(date, year = 0, month = 0, day = 0) {
// date格式不要携带 “-” 使用 “/” ,否则ios会报错。 例如 new Date(‘2023/07/28’)
if (year) {
date.setFullYear(date.getFullYear() + year);
}
if (month) {
date.setMonth(date.getMonth() + month);
}
if (day) {
date.setDate(date.getDate() + day);
}
return date;
}
// e.g.
// i.e., today is Tue Aug 01 2023 10:26:25 GMT+0800 (中国标准时间)
getDate(new Date(), 1, 0, 0); // Tue Oct 01 2024 00:00:01 GMT+0800 (中国标准时间)
getDate(new Date(), 1, 1, 0); // Tue Nov 01 2023 00:00:01 GMT+0800 (中国标准时间)
getDate(new Date(), 1, 1, 1); // Tue Nov 02 2023 00:00:01 GMT+0800 (中国标准时间)
getDate(new Date(), -1, -1, -1); // Tue Aug 31 2022 00:00:01 GMT+0800 (中国标准时间)
复制
/**
-
@param {string} value 需要复制的值
-
@param {function} callback 回调方法,返回成功失败结果
-
@return
*/
function copyValue(value, callback) {
if (navigator.userAgent.match(/(iPhone|iPod|iPad);?/i)) {
try {
const copyInput = document.createElement(‘input’);
copyInput.value = value;
copyInput.style.opactiy = ‘0’;
document.body.appendChild(copyInput);
const editable = copyInput.contentEditable;
const readonly = copyInput.readOnly;
copyInput.contentEditable = true;
copyInput.readOnly = false;
const range = document.createRange();
range.selectNodeContents(copyInput);
const sel = window.getSelection();
sel.removeAllRange();
sel.addRange(range);
copyInput.setSelectionRange(0, 9999);
copyInput.contentEditable = editable;
copyInput.readOnly = readonly;
const successful = document.execCommand(‘copy’);
copyInput.blur();
if (successful) {
callback(‘复制成功’);
} else {
callback(‘复制失败’);
}
document.body.removeChild(copyInput);
} catch (error) {
}
return;
}try {
const copyInput = document.createElement(‘input’);
copyInput.value = value;
document.body.appendChild(copyInput);
copyInput.select();
const successful = document.execCommand(‘copy’);
if (successful) {
callback(‘复制成功’);
} else {
callback(‘复制失败’);
}
document.body.removeChild(copyInput);
} catch (error) {
}
}
金额转换
/**
- @param {number | string} amount 金额
- @param {number} percision 精度
- @return {string} 千分隔字符串
*/
function convertToWriting(amount, percision = 2) {
if (!amount) {
return ‘’;
}
// numberWithPercision 是上面的保留小数精度方法
const temp = numberWithPercision(amount, percision).split(‘.’);
return temp[0].replace(/(\d)(?=(\d{3})+$)/g, ‘$1,’) + ‘.’ + (temp[1] || ‘00’);
}
// 示例
// convertToWriting(4561235.157, 2) => 4,561,235.16
乘法运算
/**
- @param {number | string} val 被乘数
- @param {number | string} rate 乘数
- @return {number} 积,返回值有精度问题,若要处理精度,需配合numberWithPercision使用
*/
function floatMul(val, rate) {
val = val.toString();
rate = rate.toString();
let baseNum = 0;
try {
baseNum += val.split(‘.’)[1].length;
} catch (e) {
}
try {
baseNum += rate.split(‘.’)[1].length;
} catch (e) {
}
return Number(val.replace(‘.’, ‘’)) * Number(rate.replace(‘.’, ‘’)) / Math.pow(10, baseNum);
}
除法运算
/**
- @param {number | string} val 被除数
- @param {number | string} rate 除数
- @return {number} 商,返回值有精度问题,若要处理精度,需配合numberWithPercision使用
*/
function floatMul(val, rate) {
val = val.toString();
rate = rate.toString();
let baseNum1 = 0;
let baseNum2 = 0;
let baseNum3 = 0;
let baseNum4 = 0;
try {
baseNum1 = val.split(‘.’)[1].length;
} catch (e) {
baseNum1 = 0;
}
try {
baseNum2 = rate.split(‘.’)[1].length;
} catch (e) {
baseNum2 = 0;
}
baseNum3 = Number(val.replace(‘.’, ‘’));
baseNum4 = Number(rate.replace(‘.’, ‘’));
return (baseNum3 / baseNum4) * Math.pow(10, baseNum2 - baseNum1);
}
加减法
/**
- @param {number} num1 加数,可为负值
- @param {number} num2 加数,可为负值
- @return {number} 和,返回值有精度问题,若要处理精度,需配合numberWithPercision使用
*/
function addNum(num1, num2) {
let sq1 = 0;
let sq2 = 0;
let m = 0;
try {
sq1 = num1.toString().split(‘.’)[1].length;
} catch (e) {
}
try {
sq2 = num2.toString().split(‘.’)[1].length;
} catch (e) {
sq2 = 0;
}
m = Math.pow(10, Math.max(sq1, sq2));
return (num1 * m + num2 * m) / m;
}
生成某个范围内规律的数字数组
/**
- @param {number} start 数值,可为负值
- @param {number} end 数值,可为负值
- @param {number} range 数值,可为负值
- @return {Array} 从start到end之间间隔range的数值数组
*/
function rangeArray(start, end, range = 1) {
if (range === 0 || range < 0 && start < end || range > 0 && start > end) {
return [start];
}
return Array(Math.floor((end - start) / range) + 1).fill(0).map((v, i) => {
return range * i + start;
});
}
// 示例
rangeArray(1, 7); // [1, 2, 3, 4, 5, 6, 7];
rangeArray(7, 1); // [7]
rangeArray(7, 1, -1); // [7, 6, 5, 4, 3, 2, 1];
rangeArray(1, 7, 2) // [1, 3, 5, 7];
rangeArray(1, 7, -1); // [1]
向下取整
// 向下取整千
Math.floor(a / 1000) * 1000
// 示例
// 1234 => 1000
// 1000 => 1000
// 向下取整千,不能和当前值一致
Math.floor((a - 1) / 1000) * 1000
// 示例
// 1234 => 1000
// 2000 => 1000
业务类解决方案
自定义键盘问题——粘贴(仅适用于非密码相关,密码需考虑安全性不可粘贴)
<input :readonly=“isIos” v-model=“inputVal” ref=“input” @paste=“onPaste” />
// 以下是vue + ts里的写法,其他语法可相应转换
export default class Test extends Vue {
private inputValue: string = ‘’;
get inputEl() {
return this.$refs.input as HTMLElement;
}
get isIos() {
return !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
}
private mounted() {
this.inputEl.onfocus = () => {
this.inputFocus();
};
// 由于微信浏览器限制,在focus后二次点击input,不会再次触发click事件,需要用原生的方式绑定
this.inputEl.onclick = () => {
if (this.isIos) {
return;
}
this.inputFocus();
};
}
protected inputFocus() {
if (this.isIos) {
navigator.clipboard.readText().then((res: any) => {
console.log(res); // 此为粘贴后的数据
});
if (document.activeElement instanceof HTMLElement) {
document.activeElement.blur();
}
return;
}
this.inputEl.setAttribute('readonly', 'readonly');
setTimeout(() => {
this.inputEl.removeAttribute('readonly');
});
}
protected onPaste() {
if (this.isIos) {
return;
}
setTimeout(() => {
console.log(this.inputVal); // 此为粘贴后的数据
this.inputVal = ''; // 拿到数据后使用并清空,否则第二次focus会触发自定义键盘的出现
});
}
}
解决input框输入时键盘遮挡页面元素问题
// vue项目index.html中直接引入或添加此段代码 html页面直接script标签引入
document.body.addEventListener(“focusout”, () => {
// 软键盘收起的事件处理
setTimeout(() => {
const scrollHeight = document.documentElement.scrollTop || document.body.scrollTop || 0;window.scrollTo(0, Math.max(scrollHeight - 1, 0));
}, 100);
});
// 页面关闭可以removeListener
切换页面默认滚动温柔地到顶部
html {
scroll-behavior: smooth;
}
滚动到顶部
const scrollToTop = (element) =>
element.scrollIntoView({ behavior: “smooth”, block: “start” })
滚动到底部
const scrollToBottom = (element) =>
element.scrollIntoView({ behavior: “smooth”, block: “end” })
弹窗后禁止背景滚动
vue环境
// 可封装至全局
const preventDefaultAction = () => {
const defaultAction = (e) => {
e.preventDefault();
};
return {
// 禁止滚动
stop: () => {
document.body.style.overflow='hidden';
document.addEventListener('touchmove', defaultAction);
},
// 取消滚动限制
move: () => {
document.body.style.overflow='';
document.removeEventListener('touchmove', defaultAction);
}
}
}
小程序环境
// 外层结构加上catch:touchmove事件,当传入值非空时,则阻止默认行为
hello world ~~
// 弹窗开启,阻止默认事件
openDialog() {
this.setData({
preventDefaultAction: true
})
},
// 弹窗关闭,允许默认行为,外层可滚动
closeDialog() {
this.setData({
preventDefaultAction: null
})
}
})