生成 uid
/*** 生成uid** @export* @returns*/export function uid () { function s4 () { return Math.floor((1 + Math.random()) * 0x10000) .toString(16) .substring(1) } return `${s4()}${s4()}-${s4()}-${s4()}-${s4()}-${s4()}${s4()}${s4()}`}
获取地址栏参数
/*** 获取地址栏参数** @export* @param {*} url* @returns*/export function getParams (url) { try { url = url.match(/\?([^#]+)/)[1] const arr = url.split('&') let obj = {} for (let i = 0; i < arr.length; i++) { const subArr = arr[i].split('=') obj[subArr[0]] = subArr[1] } return obj } catch (err) { return null }}
设置地址参数
/*** 设置地址参数** @export* @param {*} params* @returns*/export function serUrlParams (url, params) { for (let k in params) { let value = params[k] !== undefined && params[k] !== null ? params[k] : '' value = encodeURIComponent(decodeURIComponent(value)) url += `&${k}=${value}` } return url ? url.substring(1) : ''}
金额格式化
/** formatMoney(s,type)* 功能:金额按千位逗号分割* 参数:s,需要格式化的金额数值.* 参数:type,(number类型)金额的小数位.* 返回:返回格式化后的数值.*/var formatMoney = (val, type) => { if (val === '' || val === 0) return '0.00' val = Number(val) if (isNaN(val)) return '' return val.toFixed(type).replace(/(\d)(?=(\d{3})+\.)/g, '$1,')}
/*** 格式化数字** @export* @param {*} number 需要格式化的数字* @param {number} [decimals=2] 保留几位小数,默认2位* @param {string} [decPoint='.'] 小数点符号,默认是点.* @param {string} [thousandsSep=','] 千分位符号,默认逗号,* @param {string} [roundtag='ceil'] 舍入参数,默认 "ceil" 向上取,"floor"向下取,"round" 四舍五入* @return {*}*/export function formatNumber ( number, decimals = 2, decPoint = '.', thousandsSep = ',', roundtag = 'ceil') { number = (number + '').replace(/[^0-9+-Ee.]/g, '') const n = !isFinite(+number) ? 0 : +number const prec = !isFinite(+decimals) ? 0 : Math.abs(decimals) let s = '' const toFixedFix = function (n, prec) { const k = Math.pow(10, prec) return ( '' + parseFloat( Math[roundtag](parseFloat((n * k).toFixed(prec * 2))).toFixed(prec * 2) ) / k ) } s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.') const re = /(-?\d+)(\d{3})/ while (re.test(s[0])) { s[0] = s[0].replace(re, '$1' + thousandsSep + '$2') } if ((s[1] || '').length < prec) { s[1] = s[1] || '' s[1] += new Array(prec - s[1].length + 1).join('0') } return s.join(decPoint)}
获取地址栏参数
const getURLParameters = url => (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce( (a, v) => ( (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a ), {} )
深度合并对象
const deepMerge = (a, b, fn) => [...new Set([...Object.keys(a), ...Object.keys(b)])].reduce( (acc, key) => ({ ...acc, [key]: fn(key, a[key], b[key]) }), {} );// 例子deepMerge( { a: true, b: { c: [1, 2, 3] } }, { a: false, b: { d: [1, 2, 3] } }, (key, a, b) => (key === 'a' ? a && b : Object.assign({}, a, b)));// { a: false, b: { c: [ 1, 2, 3 ], d: [ 1, 2, 3 ] } }
深度克隆
const deepClone = obj => { if (obj === null) return null let clone = Object.assign({}, obj) Object.keys(clone).forEach( key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]) ) if (Array.isArray(obj)) { clone.length = obj.length return Array.from(clone) } return clone};// 例子const a = { foo: 'bar', obj: { a: 1, b: 2 } }const b = deepClone(a) // a !== b, a.obj !== b.obj
重命名键
const renameKeys = (keysMap, obj) => Object.keys(obj).reduce( (acc, key) => ({ ...acc, ...{ [keysMap[key] || key]: obj[key] } }), {} );// 例子const obj = { name: 'Bobo', job: 'Front-End Master', shoeSize: 100 }renameKeys({ name: 'firstName', job: 'passion' }, obj)// { firstName: 'Bobo', passion: 'Front-End Master', shoeSize: 100 }
解析Cookie
const parseCookie = str => str .split(';') .map(v => v.split('=')) .reduce((acc, v) => { acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim()); return acc; }, {});// 例子parseCookie('foo=bar; equation=E%3Dmc%5E2');// { foo: 'bar', equation: 'E=mc^2' }
序列化Form
const serializeForm = form => Array.from(new FormData(form), field => field.map(encodeURIComponent).join('=') ).join('&');// 例子serializeForm(document.querySelector('#form'));// email=test%40email.com&name=Test%20Name
Form转Object
const formToObject = form => Array.from(new FormData(form)).reduce( (acc, [key, value]) => ({ ...acc, [key]: value }), {} );// 例子formToObject(document.querySelector('#form'));// { email: 'test@email.com', name: 'Test Name' }
记录动画帧
const recordAnimationFrames = (callback, autoStart = true) => { let running = false, raf; const stop = () => { if (!running) return; running = false; cancelAnimationFrame(raf); }; const start = () => { if (running) return; running = true; run(); }; const run = () => { raf = requestAnimationFrame(() => { callback(); if (running) run(); }); }; if (autoStart) start(); return { start, stop };};// 例子const cb = () => console.log('Animation frame fired');const recorder = recordAnimationFrames(cb);// logs 'Animation frame fired' on each animation framerecorder.stop(); // stops loggingrecorder.start(); // starts againconst recorder2 = recordAnimationFrames(cb, false);// `start` needs to be explicitly called to begin recording frames
是否是浏览器环境
const isBrowser = () => ![typeof window, typeof document].includes('undefined');// 例子isBrowser(); // true (browser)isBrowser(); // false (Node)
是否是绝对URL
const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str);// 例子isAbsoluteURL('https://google.com'); // trueisAbsoluteURL('ftp://www.myserver.net'); // trueisAbsoluteURL('/foo/bar'); // false
平滑滚动到顶部
const scrollToTop = () => { const c = document.documentElement.scrollTop || document.body.scrollTop; if (c > 0) { window.requestAnimationFrame(scrollToTop); window.scrollTo(0, c - c / 8); }};// 例子scrollToTop(); // Smooth-scrolls to the top of the page
检测当前用户的首选语言
const detectLanguage = (defaultLang = 'en-US') => navigator.language || (Array.isArray(navigator.languages) && navigator.languages[0]) || defaultLang;// 例子detectLanguage(); // 'zh-CN'
平滑滚动到指定元素
const smoothScroll = element => document.querySelector(element).scrollIntoView({ behavior: 'smooth' });// 例子smoothScroll('#fooBar'); // scrolls smoothly to the element with the id fooBarsmoothScroll('.fooBar');// scrolls smoothly to the first element with a class of fooBar
获取滚动位置
const getScrollPosition = (el = window) => ({ x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft, y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop});// 例子getScrollPosition(); // {x: 0, y: 200}
检测用户设备类型
const detectDeviceType = () => /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( navigator.userAgent ) ? 'Mobile' : 'Desktop';// 例子detectDeviceType(); // 'Mobile' or 'Desktop'
检查是否启用localStorage
const isLocalStorageEnabled = () => { try { const key = `__storage__test`; window.localStorage.setItem(key, null); window.localStorage.removeItem(key); return true; } catch (e) { return false; }};// 例子isLocalStorageEnabled(); // true, if localStorage is accessible
检查是否启用sessionStorage
const isSessionStorageEnabled = () => { try { const key = `__storage__test`; window.sessionStorage.setItem(key, null); window.sessionStorage.removeItem(key); return true; } catch (e) { return false; }};isSessionStorageEnabled(); // true, if sessionStorage is accessible
检查是否支持Touch事件
const supportsTouchEvents = () => window && 'ontouchstart' in window;// 例子supportsTouchEvents(); // true
检查是否见底
const bottomVisible = () => document.documentElement.clientHeight + window.scrollY >= (document.documentElement.scrollHeight || document.documentElement.clientHeight);// 例子bottomVisible(); // true