关于前端常用的部分公共方法(二)
1.读取json文件内容
/*** 读取JSON文件内容* * @template T 返回的数据类型* @param {File} file 文件选择框选择的文件对象* @returns {Promise<T>} 解析后的JSON数据*/
export function readJSON<T>(file: File): Promise<T> {return new Promise((resolve, reject) => {const fileName = file.name;const fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();if (fileExtension !== "json") {reject(new Error("文件类型不合法,请选择JSON格式文件!"));return;}if (window.FileReader) {const reader = new FileReader();reader.readAsText(file, "UTF-8");reader.onload = () => {try {resolve(JSON.parse(reader.result as string));} catch (error) {reject(new Error("解析JSON文件失败"));}};reader.onerror = () => {reject(new Error("读取文件失败"));};}});
}
代码改进点
- 参数类型从
any
改为明确的File
类型,提升类型安全性 - 添加错误处理逻辑,使用
reject
返回错误状态 - 优化变量命名,
fileType
改为更准确的fileExtension
- 添加
try-catch
处理JSON解析可能出现的异常 - 添加文件读取错误的处理逻辑
使用示例
const fileInput = document.getElementById('file-input') as HTMLInputElement;
fileInput.addEventListener('change', async (event) => {const file = event.target.files?.[0];if (!file) return;try {const data = await readJSON<MyDataType>(file);console.log(data);} catch (error) {console.error(error.message);}
});
2. 判断是否 "经度,纬度" 字符串值
以下是实现判断字符串是否为"经度,纬度"格式的TypeScript代码:
/*** 判断是否 "经度,纬度" 字符串值** @export* @param {string} text 传入的字符串* @return {boolean} 是否 经度,纬度*/
export function isLonLat(text: string): boolean {const reg = /^-?((0|1?[0-7]?[0-9]?)(([.][0-9]*)?)|180(([.][0]*)?)),-?((0|[1-8]?[0-9]?)(([.][0-9]*)?)|90(([.][0]*)?))$/return reg.test(text)
}
该正则表达式解析:
-
经度部分:
-?((0|1?[0-7]?[0-9]?)(([.][0-9]*)?)|180(([.][0]*)?))
- 允许负号开头
- 0-179度,可选小数部分
- 或180度整数(可选.0结尾)
-
纬度部分:
-?((0|[1-8]?[0-9]?)(([.][0-9]*)?)|90(([.][0]*)?))
- 允许负号开头
- 0-89度,可选小数部分
- 或90度整数(可选.0结尾)
-
经度纬度用逗号分隔
3. 获取URL参数
/*** 获取URL参数** @export* @param {string} parameter url参数名* @return {string | null} 参数值*/
export function getQueryString(parameter: string): string | null {return new URL(window.location.href).searchParams.get(parameter)
}
函数说明: 该函数使用现代URL API解析当前页面URL的查询参数,比传统字符串分割方法更可靠。参数说明:
- parameter: 需要获取的URL参数名称
- 返回值: 参数值字符串,若不存在则返回null
使用示例:
// 假设当前URL为 https://example.com?name=test&id=123
const name = getQueryString('name') // 返回 'test'
const age = getQueryString('age') // 返回 null
注意事项:
- 需要浏览器支持URL接口(所有现代浏览器均支持)
- 返回的字符串不会被自动解码,如需解码URI组件需额外处理
- 参数名称区分大小写
4. 将指定的异步方法转为Promise
/*** 将指定的异步方法转为Promise* * @param {*} context* @param {string} apiName* @param {string} [success="success"]* @param {string} [error="error"]* @return {*} Promise*/
export function apiToSync(context: any, apiName: string, success = "success", error = "error") {return new Promise((resolve, reject) => {context[apiName]({[success]: (res: any) => resolve(res),[error]: (err: any) => reject(err)})})
}
/*** 将多个异步方法转为Promise数组* * @param {*} context* @param {string[]} apiNames* @param {string} [success="success"]* @param {string} [error="error"]* @return {*} Promise[]*/
export function apiArrayToSync(context: any, apiNames: string[], success = "success", error = "error") {return apiNames.map(apiName => apiToSync(context, apiName, success, error))
}
代码实现了以下功能:
apiToSync
函数将单个异步API转换为PromiseapiArrayToSync
函数批量转换多个API为Promise数组- 支持自定义成功和失败的回调字段名
- 保留了原始API的context调用方式
- 类型标注使用TypeScript语法
5. 将指定的多个异步方法转为Promise
/*** 将指定的多个异步方法转为Promise** @param {*} context* @param {string[]} apiNames* @param {string} [success="success"]* @param {string} [error="error"]* @return {*} Promise[]*/
export function apiArrayToSync(context: any, apiNames: string[], success = "success", error = "error") {return apiNames.map((name) => {const apiFunc = context[name]return (options: any) =>new Promise((resolve, reject) => {options[success] = function (result: any) {resolve(result)}options[error] = function (error) {reject(error)}apiFunc.call(context, options)})})
}
使用方法
// 假设有一个对象包含异步API方法
const apiObject = {asyncApi1(options: any) {setTimeout(() => {options.success('Result from asyncApi1')}, 1000)},asyncApi2(options: any) {setTimeout(() => {options.success('Result from asyncApi2')}, 500)}
}// 转换为Promise数组
const promiseArray = apiArrayToSync(apiObject, ['asyncApi1', 'asyncApi2'])// 使用Promise.all并行调用
Promise.all([promiseArray[0]({}),promiseArray[1]({})
]).then(results => {console.log(results) // ['Result from asyncApi1', 'Result from asyncApi2']
}).catch(error => {console.error(error)
})
关键点说明
- 该函数将基于回调的异步方法转换为Promise形式
- 支持自定义成功和失败的回调键名
- 返回的是Promise数组,可以配合Promise.all使用
- 保持了原始方法的this绑定
参数说明
context
: 包含异步方法的对象apiNames
: 需要转换的方法名数组success
: 成功回调的键名,默认为'success'error
: 失败回调的键名,默认为'error'
6. 单个权限验证
/*** 单个权限验证* @param value 权限值* @returns 有权限,返回 `true`,反之则反*/
export function auth(value: string): boolean {const stores = useUserInfo();return stores.userInfos.authBtnList.some((v: string) => v === value);
}
7. 多个权限验证,满足一个则为true
/*** 多个权限验证,满足一个则为 true* @param value 权限值* @returns 有权限,返回 `true`,反之则反*/
export function auths(value: Array<string>): boolean {let flag = false;const stores = useUserInfo();stores.userInfos.authBtnList.map((val: string) => {value.map((v: string) => {if (val === v) flag = true;});});return flag;
}
8. 多个权限验证,全部满足则为 true
/*** 多个权限验证,全部满足则为 true* @param value 权限值* @returns 有权限,返回 `true`,反之则反*/
export function authAll(value: Array<string>): boolean {const stores = useUserInfo();return judementSameArr(value, stores.userInfos.authBtnList);
}/*** 判断两数组字符串是否相同(用于按钮权限验证),数组字符串中存在相同时会自动去重(按钮权限标识不会重复)* @param news 新数据* @param old 源数据* @returns 两数组相同返回 `true`,反之则反*/
export function judementSameArr(newArr: unknown[] | string[], oldArr: string[]): boolean {const news = removeDuplicate(newArr);const olds = removeDuplicate(oldArr);let count = 0;const leng = news.length;for (let i in olds) {for (let j in news) {if (olds[i] === news[j]) count++;}}return count === leng ? true : false;
}
9. 获取UI框架图片URL
/*** 获取UI框架图片URL* @param name 图片名称* @param prefix 前置根路径*/
export function getImageUrl(name: string | unknown, prefix = 'frame') {return new URL(`/src/assets/images/${prefix}/${name}.png`, import.meta.url).href;
}/*** 获取业务图片URL* @param name 图片名称*/
export function getBaseImage(name: string | unknown) {return new URL(`/src/assets/images/${name}.png`, import.meta.url).href;
}/*** 获取IConURL* @param name 图标名称*/
export function getIconUrl(name: string | unknown) {return new URL(`/src/assets/icons/${name}.png`, import.meta.url).href;
}
10. 转换秒单位为X小时X分钟X秒的格式
/*** 转换秒单位为X小时X分钟X秒的格式* @returns {String}*/
export function transSeconds(rawSeconds: number) {if (rawSeconds && rawSeconds > 0) {let last = 0;const hours = Math.floor(rawSeconds / 3600);last = rawSeconds - hours * 3600;const minute = parseInt(Math.floor(last / 60).toString());const seconds = parseInt((rawSeconds - hours * 3600 - minute * 60).toString());return `${hours > 0 ? hours + '小时' : ''}${minute}分${seconds}秒`;}return '';
}
11. 输入框限制只能输入数字,并且范围为0-999
<el-input clearable maxlength="3" v-model.number="form.warningthresholdmin" @input="validateMinValue"></el-input>// 输入框限制输入只能输入正整数,并且不能大于999
const validateMinValue = (value: any) => {// 将输入值转换为数字let num = Number(value);if (!value) {form.warningthresholdmin = '';return;}// 检查输入值是否是数字if (isNaN(num)) {// 如果不是数字,将其设置为空字符串form.warningthresholdmin = '';return;}// 检查输入值是否在 0 到 999 的范围内if (num < 0) {num = 0;} else if (num > 999) {num = 999;}// 更新输入框的值form.warningthresholdmin = num;}
12. 输入框限制只能输入数字,支持小数,小数点前四位,小数点后六位(经纬度输入框)
<el-input placeholder="请输入经度" maxlength="10" @input="e => handleInput(e,'longitude')" clearable v-model="form.longitude"></el-input>
<el-input placeholder="请输入纬度" maxlength="10" @input="e => handleInput(e, 'latitude')" clearable v-model="form.latitude"></el-input>// 限制经纬度输入只能输入数字0-9999.999999
const handleInput = (value: any, type: string) => {// 处理空值if (!value) {if (type === "latitude") {form.latitude = '';} else {form.longitude = '';}return;}let val = value.toString();// 非法输入,限制范围或清空if (val === '.') {// 允许小数点开头,后续通过正则处理if (type === "latitude") {form.latitude = '0.';} else {form.longitude = '0.';}} else {// 移除非法字符val = val.replace(/[^0-9\.]/g, '');val = val.replace(/(\..*)\./g, '$1'); // 只允许一个小数点// 限制小数点后六位const parts = val.split('.');if (parts.length > 1 && parts[1].length > 6) {parts[1] = parts[1].substring(0, 6);val = parts.join('.');}// 转换为数字并限制范围let num = parseFloat(val);let number = val;// 检查输入值是否是数字if (isNaN(num)) {// 如果不是数字,将其设置为空字符串if (type === "latitude") {form.latitude = '';} else {form.longitude = '';}return;}// 检查输入值是否在 0 到 999 的范围内if (number < 0) {number = 0;} else if (number > 9999.999999) {number = 9999.999999;}if (type === "latitude") {form.latitude = number;} else {form.longitude = number;}}
}