❧ 实用的代码段大全
- 获取URL参数
- 无限极分类树形结构
- 导出csv文件
- 列表多字段、多排序类型
- 数字格式化展示,包含小数位数限定、百分数、千分位等
- 树结构数据筛选过滤
- 文件大小格式化显示
- 在线文件下载
- ElementUI表单获取焦点提示填写
- 判断是否为移动端
- 列表页搜索过滤分页
获取URL参数
// 代码:const getURLParameters = url => (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce((a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a), {});
// 案例:getURLParameters('http://url.com/page?name=Adam&surname=Smith');// {name: 'Adam', surname: 'Smith'}无限极分类树形结构
// 代码:const toTree = (data) => { // 删除所有 children,以防止多次调用 data.forEach(function (item) { delete item.children })
// 以id为key的map索引数据列 const map = {} data.forEach(function (item) { map[item.value] = item })
const val = [] data.forEach(function (item) { const parent = map[item.pid] // 自身放入对应的父节点下 if (parent) { (parent.children || (parent.children = [])).push(item) } else { // 顶级节点 val.push(item) } }) return val}
// 案例:toTree([{id:1001,pid:1002,name:'Apple'}, ...])导出csv文件
// 代码:function exportCsv(csv, filename = 'export.csv') {
const BOM = '\uFEFF'; const blob = new Blob([BOM + csv], { type: 'text/csv;charset=utf-8;' });
if (navigator.msSaveOrOpenBlob) { navigator.msSaveOrOpenBlob(blob, filename); } else { const downloadLink = document.createElement('a'); downloadLink.href = URL.createObjectURL(blob); downloadLink.download = filename; document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); }}
// 案例:exportCsv('"field1","field2"', '文件名.csv');列表多字段、多排序类型
// 代码:/*** list Array 数据列表* fields string[] 排序字段* order string|string[] 排序类型, asc/desc*/const listSort = (list, fields, order) => { const fieldsLen = fields.length; if (Object.prototype.toString.call(order) == '[object Array]' && order.length != fieldsLen) { throw new Error("字段数组和排序类型数组长度必须一直"); } // 根据排序类型获取最终结果 const getResult = (result, orderType) => { return orderType == 'desc' ? -result : result; } // 排序处理 const dealSort = (data, fields, index) => { const orderType = Object.prototype.toString.call(order) == '[object Array]' ? order[index] : order; const { left, right } = data; const field = fields[index]; const isString = typeof left[field] == 'string' && typeof right[field] == 'string'; if (index == fieldsLen - 1) { return getResult(isString ? left[field].localeCompare(right[field], 'zh-CN') : left[field] - right[field], orderType); } else { if (left[field] == right[field]) { return dealSort(data, fields, index + 1); } return getResult(isString ? left[field].localeCompare(right[field], 'zh-CN') : left[field] - right[field], orderType); } } return list.sort((left, right) => { return dealSort({ left, right }, fields, 0); })}
// 案例:listSort(list, ['name', 'age'], 'asc');listSort(list, ['name', 'age'], ['asc', 'desc']);数字格式化展示,包含小数位数限定、百分数、千分位等
/** * 数字格式化展示,包含小数位数限定、百分数、千分位等 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString * @param num number 数值 * @param options.style string 样式类型,decimal|currency|percent * @param options.maximumFractionDigits number 最多保留小数位数 * @param options.useGrouping number 是否使用千分位 * @return string */const numFormat = (num, options = {}) => { const {style, maximumFractionDigits, useGrouping} = options; const newOptions = {style: style ?? 'decimal', maximumFractionDigits: maximumFractionDigits ?? 2}; if (useGrouping === false) { newOptions.useGrouping = false; } return num.toLocaleString('zh-CN', newOptions);}树结构数据筛选过滤
// 树结构数据筛选过滤const matchTreeData = (arr: {[key: string]: any}[], keyword: string, fields: string[]) => { const newArr: {[key: string]: any}[] = []; arr.forEach((item: {[key: string]: any}) => { for (const field of fields) { if (!item.hasOwnProperty(field)) { continue; } if (item[field] && item[field].indexOf(keyword) !== -1) { newArr.push(item); break; } else { const children = matchTreeData(item.children || [], keyword, fields); if (children.length > 0) { newArr.push({ ...item, children }) break; } } } }) return newArr;}文件大小格式化显示
const formatFileSize = (size: number) => { const value = Number(size); if (size && !isNaN(value)) { const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB', 'BB']; let index = 0; let k = value; if (value >= 1024) { while (k > 1024) { k = k / 1024; index++; } } return `${(k).toFixed(1)}${units[index]}`; } return '-';}在线文件下载
const getBlob = (url: string, cb: Function) => { const xhr = new XMLHttpRequest(); xhr.open("GET", url, true); xhr.responseType = "blob"; xhr.onload = function () { if (xhr.status === 200) { cb(xhr.response); } }; xhr.send();}
const saveAs = (blob: Blob, filename: string) => { const link = document.createElement("a"); const body = document.querySelector("body") as HTMLBodyElement;
link.href = window.URL.createObjectURL(blob); link.download = filename;
// fix Firefox link.style.display = "none"; body.appendChild(link);
link.click(); body.removeChild(link);
window.URL.revokeObjectURL(link.href);}
const download = (url: string, filename: string) => { getBlob(url, function (blob: Blob) { saveAs(blob, filename); });}ElementUI表单获取焦点提示填写
/** * ElementUI表单获取焦点提示填写 * * @param {HTMLElement} dom 元素节点 * @param {string} type input 或 textarea */const elementFocus = (dom: HTMLElement, type: 'input'|'textarea') => { if (!dom || !['input', 'textarea'].includes(type)) { return; } const element = dom.getElementsByClassName(`el-${type}__inner`)[0] as HTMLElement; element.focus();}
/* Vue3使用 */// 初始化定义const instance = getCurrentInstance() as ComponentInternalInstance;// 校验处处理const refs: {[key: string]: any} = instance.refs;elementFocus(refs['domRef'].$el, 'input');判断是否为移动端
const isMobile = () => { const userAgent = navigator.userAgent.toLowerCase(); const device = /ipad|iphone|midp|rv:1.2.3.4|ucweb|android|windows ce|windows mobile/;//可以在这里补充 return device.test(userAgent);}列表页搜索过滤分页
/** * 列表页搜索过滤分页 * @param list 数据列表 * @param options.pager 分页配置 * @param options.keyword 搜索关键词 * @param options.fields 搜索字段 * @param options.filterHook 自定义过滤条件 * @param options.mergeField 根据此合并字段进行分页 * @returns Array */type ListSearchOptions = { pager?: { page: number, size: number, total: number }, keyword?: string, fields?: string[], mergeField?: string, filterHook?: Function,}const pageListSearch = (list: {[key: string]: any}[], options: ListSearchOptions = {}) => {
const { pager, keyword, fields, filterHook, mergeField } = options;
if ((keyword && fields) || filterHook) { list = list.filter((t: {[key: string]: any}) => { let status = false; if (keyword && fields) { const kw = keyword.toLowerCase(); for (const field of fields) { status = status || t[field]?.toLowerCase()?.includes(kw) } } if (filterHook) { status = status || filterHook(t); } return status; }); }
if (!pager) { return list; }
if (mergeField) { const ids: number[] = []; const idMap: {[key: string]: boolean} = {}; let count = 0; list.forEach((item: {[key: string]: any}) => { if (!idMap[item[mergeField]]) { count++; ids.push(item[mergeField]); idMap[item[mergeField]] = true; } item.index = count; });
pager.total = ids.length;
if (pager.page > Math.ceil(pager.total/pager.size)) { pager.page = 1; }
const start = (pager.page - 1) * pager.size; const end = start + pager.size; const newIds = ids.slice(start, end); const newIdMap = {}; for (const id of newIds) { newIdMap[id] = true; } const newList = list.filter((t: {[key: string]: any}) => newIdMap[t[mergeField]]); return newList; }
pager.total = list.length;
if (pager.page > Math.ceil(pager.total/pager.size)) { pager.page = 1; }
const start = (pager.page - 1) * pager.size; const end = start + pager.size;
return list.slice(start, end);}