常用工具类封装
前言
由于在实际项目开发中,多个项目会同时需要相同的工具类,于是参考线上的开源项目和技术文章对常用的工具类函数进行封装和拓展;有些工具函数的实现是依赖于其他篇目的工具,读者可以留意。
项目地址:https://github.com/zhicaizhu123/Zutils,欢迎 star !
目录
安装使用
1. 安装
# 安装依赖npm install -S zutilsjs
2. 引入
// 全局引入// 按需加载
类型篇
1. 获取各种数据数据类型
const isType = ObjectprototypetoString === `[object ]`;
2. 判断是否为对象
const isObject = typeof val === "function" || typeof val === "object" && !!val;
3. 判断是否为 null
或 undefined
const isEmpty = || ;
4. 判断是否为{}
空对象
const isEmptyObject = && JSON == "{}";
5. 判断是否为数组
const isArray = Array
6. 判断是否为参数列
const isArguments = ;
7. 判断是否为 Null
类型
const isNull = ;
8. 判断是否为 Number
类型
const isNumber = ;
9. 判断是否为 String
类型
const isString = ;
10. 判断是否为 Function
类型
const isFunction = ;
11. 判断是否为 Promise
类型
const isPromise = ;
12. 判断是否为 Date
类型
const isDate = ;
13. 判断是否为 RegExp
类型
const isRegExp = ;
14. 判断是否为 Map
类型
const isMap = ;
15. 判断是否为 Set 类型
const isSet = ;
16. 判断是否为 Symbol 类型
const isSymbol = ;
17. 判断是否为 Error
类型
const isError = ;
18. 判断是否为 Undefined
类型
const isUndefined = ;
19. 判断是否为 NaN
const isNaN = Number;
20. 判断是否为 DOM 元素
const isElement = ? val instanceof HTMLElement : && && valnodeType === 1;
对象篇
1. 克隆对象(浅克隆)
const clone = { for let prop in origin if origin resultprop = originprop; return result;}; // 举例:const obj = name: 'ZCoder' info: name: 'ZCoder'const objClone = obj === objClone // => falseobjinfo === objCloneinfo // => true
2. 深克隆
说明:使用 WeakMap 存储中间数据,避免递归进入死循环导致栈内存溢出了
const deepClone = data weak = if typeof data !== "object" || data === null return data; let result; const Constructor = dataconstructor; for let key in data resultkey = ? : datakey; return result;; // 举例:const obj = name: 'ZCoder' info: name: 'ZCoder'const objClone = obj === objClone // => falseobjinfo === objCloneinfo // => false
3. 合并对象
const extend = Object; // 举例:const obj = name: 'ZCoder' info: name: 'ZCoder'// => {name: 'ZCoder', info: {name: 'ZCoder'}, email: '123'}
4. 根据保留/删除(keep/remove)类型过滤字段
说明:如果
type='keep'
,则keys
为要保留的字段名称列表,否则keys
为要删除的字段名称组成的数组
const filterKeys = Object;
5. 保留给定字段
const keepKeys = ; // 举例: // => {id: 123, name: 'ZCoder'}
6. 删除给定字段
const removeKeys = ; // 举例: // => {email: '123'}
7. 替换对象字段名
说明:
rules
参数为键值对,key-要替换的字段名,value-新的字段名
const replaceKeys = { const keys = Object; return Object;}; // 举例:// => {id: 123, username: "ZCoder", userEmail: "123"}
数组篇
1. 从左/右(left/right)遍历数组
const forEachType = { const list = type === "left" ? arr : ...arr; list;};
2. 左遍历
const forEach = ; // 举例:// => 1// => 2// => 3
3. 右遍历
const forEachRight = ; // 举例:// => 3// => 2// => 1
3. 判断是否为类数组
const isArrayLike = "length" in val; // 举例: // => true // => false
4. 拉平数组
说明:
depth
为要最多拉平的层级
const flatten = arr; // 举例: // => [1, 2, 3, 4, [1, 2, 3], 5, 6, 7, 8, 9]
5. 深度拉平数组
const deepFlatten = ;// 举例:// => [1, 2, 3, 4, 1, 2, 3, 5, 6, 7, 8, 9]
6. 数组去重
const unique = ...arr; // 举例: // => [1, 2, 3, 4, 5]
7. 取两个数组的交集
const intersection = { const arr = arr1; return arr2;}; // 举例: // => [1, 4, 5]
8. 取多个数组的交集
const intersectionAll = args; // 举例: // => [1, 5]
9. 多个元素的并集(去重))
const union = ; // 举例: // => [1, 2, 3, 4, 5, 7, 8]
10. 两个数组的差集
const difference = { const allList = ; const intersectionList = ; return allList;}; // 举例: //=> [1, 5, 6]
11. 多个数组的差集
const differenceAll = args; // 举例: // => [5, 6, 1]
12. 将单层级数组转化为树形结构
说明:
parentId
为父元素的唯一标识,id
为元素的唯一标识,默认为'id'
,pid
为元素的父元素标识,默认为'pid'
,children
为要生成多层级子元素的字段名,默认为'children'
const array2Tree = arr parentId = 0 id = "id" pid = "pid" children = "children" = {} arr ; // 举例:// => // [// {// id: 1, // parent_id: 0, // label: '一级', // children: [// {id: 2, parent_id: 1, label: '二级', children: []},// {id: 3, parent_id: 1, label: '二级', children: []}// ]// }// ]
13. 树状结构转为一维数组
说明:
id
为每个元素的唯一标识,默认为'id'
,children
为多层级的子元素列表字段,默认为'children'
const tree2Array = { let list = tree; return list;}; // 举例:// =>// [// {"id":1,"parent_id":0,"label":"一级"},// {"id":2,"parent_id":1,"label":"二级"},// {"id":3,"parent_id":1,"label":"二级"}// ]
14. 数组转为对象
说明:如果数组元素为对象时指定对象的某个唯一字段为 key 值,没有指定则默认为下标索引值
const array2Object = { if !arrlength console; return null; return arr;}; // 举例:// => {"1":{"id":1,"name":"123"},"2":{"id":2,"name":"456"}}
15. 根据标识获取树状结构的数据链
说明:
id:需要查找的层级id
tree:树状结构数据
filter:需要筛选的字段
options:字段名匹配规则
const getTreeChains = {let opts =id: "id"pId: "pId"children: "children";opts = ...opts ...options ;let list =;let currentId = id;list = list;if filterlength === 1list = list;return list;};// 举例:const treeList =id: 1parentId: 0name: '层级1'children:id: 3parentId: 1name: '层级1-1'children:id: 5parentId: 3name: '层级1-1-1'id: 4parentId: 1name: '层级1-2'id: 2parentId: 0name: '层级2'// => [1, 3, 5]// => [{id: 1, name: '层级1'}, {id: 3, name: '层级1-1'}, {id: 5, name: '层级1-1-1'}]
16. 类数组转为数组
const arrayLike2Array = { if ! console; return ; return Array;}; // 举例:// => ["123", "345"]
17. 根据给定长度进行分组
const chunk = Array; // 举例:// => [[1,2],[3,4],[5,6],[7]]
18. 过滤列表中的空数据
const compact = arr; // 举例:// => [1, 4, 5]
19. 根据条件获取元素的出现次数
const countBy = arr ; // 举例:// => {1: 1, 2: 2, 4: 1, 5: 2, 6: 1, 7: 2}
20. 获取指定元素的出现次数
const countByValue = val; // 举例: // 获取元素为2的出现次数// => 2
21. 获取指定元素的下标值
const indexOfAll = arr; // 举例: // 获取7的下标// => [4, 8]
22. 随机排序
const shuffe = { const list = ...arr; let len = listlength; while len const i = Math; listlen listi = listi listlen; return list;}; // 举例:// => [6, 1, 3, 5, 4, 7, 8, 2, 9]
23. 随机取数组中数据
说明:
size
为取出元素的个数
const sample = { const list = ; return list;}; // 举例:// => [4, 6, 8]
日期篇
可以移步到https://github.com/zhicaizhu123/Zdate查看更多介绍说明!
字符串篇
1. 转化为驼峰值
const camelize = val; // 举例: // => "WebkitTransform" // => "webkitTransform"
2. 转化为中划线值
const dasherize = val ; // 举例: // => "-webkit-transform" // => "webkit-transform"
3. 根据附加属性生成指定条件的正则表达式
用于以下 html 文本处理
const getAttrsReg = { const attrsReg = ; Object; return attrsReg;};
4. 通过附加属性的筛选获取元素列表
说明:用于以下 html 文本处理
const getResultByAttr = { let result = ...list; const attrsReg = ; const res = ; attrsReg; return result;};
5. 从文本中获取指定条件的标签
说明:
- source: 需要解析的源文本
- tag: 需要解析元素的 tagName
- attrs: 附加属性添加更快查询解析元素
const getTagfromHtmlString = { if !source console; return ; if !tag console; return ; const singleTags = "br,hr,img,input,param,meta,link"; let reg = `<[^<>]*>[\\d\\D]+?<\/>` "gmi"; // 判断是否为但标签 if singleTags reg = `<[^<>]*\/?>` "gmi"; let result = source; console if result && resultlength && attrs && Objectlength result = ; return result || ;}; // 举例:// 获取img标签// => ["<img src="/haha.jpg">"] // 获取带有class属性值为'span-item'的span标签// getTagfromHtmlString({ source: ` <div class="container"> <span class="span-item">123</span> <div> <img src="/haha.jpg"> <span class="span-item">456</span> </div> </div> ` tag: 'span' attrs: class: 'span-item'})// =>// [// "<span class="span-item">123</span>", // "<span class="span-item">456</span>"// ]
6. 获取 html 文本中某类元素指定属性的属性值
说明:
- source: 需要解析的源文本
- tag: 需要解析元素的 tagName
- attr: 需要获取属性值的解析元素的属性名称
- attrs: 附加属性添加更快查询解析元素
const getAttrFromHtmlString = { if !source console; return ; if !tag console; return ; if !attr console; return ; const result = ; const attrList = result; return attrList;}; // 举例:// 获取img标签的src属性值// => ["/enen.jpg", "/haha.jpg"]
7. 获取 html 文本中转化为 html 后的纯文本信息
const getPureTextFromHtmlString = source; // 举例:// => "456"
8. 转义 html
说明:一般用于防止XSS攻击
const escapeHtml = { const hash = "&": "&" "<": "<" ">": ">" "'": "'" '"': """ ; return str;}; // 举例:// => "<div class="container"><img src="/enen.jpg"><div><img src="/haha.jpg"><span class="span-item">456</span></div></div>"
数字篇
1. 将参数转为数组
如果参数本身为数组且第一个元素也为数组则返回第一个元素(用于 min、max 、sum)
const args2Array = { let params = args; if argslength === 1 && params = args0; return params;};
2. 汇总
说明:可以以数组形式,或多个参数形式参入,如
sum([1, 2, 3])
或sum(1, 2, 3)
const sum = { const params = ; return ...params;}; // 举例: // => 6 // => 6
3. 取平均数
说明:可以以数组形式,或多个参数形式参入,如
sum([1, 2, 3])
或sum(1, 2, 3)
const average = { const params = ; return / paramslength ? paramslength : 1;}; // 举例: // => 2 // => 2
4. 取最小值
说明:可以以数组形式,或多个参数形式参入,如
sum([1, 2, 3])
或sum(1, 2, 3)
const min = { const params = ; return Mathmin;}; // 举例: // => 1
5. 取最大值
说明:可以以数组形式,或多个参数形式参入,如
sum([1, 2, 3])
或sum(1, 2, 3)
const max = { const params = ; return Mathmax;}; // 举例: // => 3
6. 转化为货币形式
const toCurrency = Stringnum; // 举例: // => "123,456,789"
7. 截取小数点后几位
说明:默认截取两位小数
const toFixed = ? num : num; // 举例: // => 1234567.12
8. 升序
const sortAsc = { const params = ; return ;}; // 举例: // => [1, 2, 2, 3, 4, 4]
9. 降序
const sortDesc = { const params = ; return ;}; // 举例:// => [4, 4, 3, 2, 2, 1]
10. BigInteger 类型处理
说明:
请移步到bignumber.js查看更多介绍说明。
Html 篇
1. 获取元素
说明:
root
如果为true
则el
=window
则会转化为 document.documentElement,否则不做处理;
el
可以是String
,HTMLElement
,Window
类型,如'.user-name'
,document.documentElemen
,window
;
以下html的工具函数的参数el
,child
,parent
,target
涉及到传入元素相关的遵循这个规则。
// 注意:以下的工具函数有对body的引入都取于这里const body = documentdocumentElement || documentbody; const getElement = { if el instanceof Window return root ? body : window; else if return el; else if const currentEl = document; return ? currentEl : null; console; return null;};
2. 获取元素的样式
说明:
el:当前元素
style: 要获取样式字段对应的字符串(驼峰值),如:"zIndex"
const getStyle = { const currentEl = ; if !currentEl return; return currentElcurrentStyle ? currentElcurrentStylestyle : style;};
3. 判断一个元素是否为另一个元素的子元素
说明:
parent:父元素
child:子元素
const elementContains = { const childEl = ; const parentEl = ; if !childEl || !parentEl return; return parentEl;};
4. 获取元素相对父元素的距离
说明:
el:子元素
parent: 父元素
const getElementOffsetTop = { const currentEl = ; const parentEl = ; if !currentEl || !parentEl return; if ! console; return; let isSetPosition = false; if === "staic" parentElstyleposition = "relative"; isSetPosition = true; let offsetTop = currentEloffsetTop; let p = currentEloffsetParent; while p && p !== parentEl && parentEl if navigatoruserAgent === -1 offsetTop += pclientTop; offsetTop += poffsetTop; p = poffsetParent; if isSetPosition parentElstyleposition = "static"; return offsetTop;};
5. 设置元素滚动
说明:
el: 滚动元素
position: 滚动元素最终的scrollTop
isAnimation: 是否启动缓动效果
const scrollTo = { // offset > 0 => 目标位置再窗口顶部的上方 // offset < 0 => 目标位置再窗口顶部的下方 const currentEl = ; if !currentEl return; const step = position - currentElscrollTop > 0 ? 20 : -20; let requestId = null; { if isAnimate && step * position - currentElscrollTop > 0 if step * position - currentElscrollTop > 0 currentElscrollTop += step; requestId = ; else ; else currentElscrollTop = position; } ;}; // 举例:
6. 让目标元素滚动到滚动元素的可视范围
说明:
target: 目标元素
const scrollToTarget = { const currentEl = ; const targetEl = ; if !currentEl || !targetEl return; const offsetTop = ; if offsetTop === null console; else ; };
7. 滚动到顶部
const scrollToTop = { const currentEl = ; if !currentEl return; ;};
8. 滚动到底部
const scrollToBottom = { const currentEl = ; if !currentEl return; ;};
9. 判断 className 类型格式是否正确
说明:
该函数用于下面的addClass
和removeClass
以及hasClass
工具函数
const checkClassNameType = { const currentEl = ; if !currentEl return; if className && ! console; return; const name = className || ; return name0 || "";};
10. 为元素添加类名
说明:
el: 当前元素
className: 样式类名字符串(单个)
const addClass = { const xlassName = ; if !xlassName return; if elclassList elclassList; else const list = elclassName || ; list; elclassName = list; };
11. 移除元素的类名
说明:
el: 当前元素
className: 样式类名字符串(单个)
const removeClass = { const xlassName = ; if !xlassName return; if elclassList elclassList; else const list = elclassName || ; elclassName = list; };
12. 判断是否含有某个类
说明:
el: 当前元素
className: 样式类名字符串(单个)
const hasClass = { const xlassName = ; if !xlassName return false; if elclassList return elclassList; let list = elclassName || ; return list;};
13. 动态加载 js 文件(异步方式)
const loadJs = { const script = document; scripttype = "text/javascript"; if scriptreadyState script { if scriptreadyState === "loaded" || scriptreadyState === "complete" scriptonreadystatechange = null; ; }; else script { ; }; script { } scriptsrc = url; documentbody; }; // 举例:
事件篇
1. 监听元素大小改变事件
说明:实现代码取于 element-ui 源码的代码片段
; const resizeHandler = { for let entry of entries const listeners = entrytarget__resizeListeners__ || ; if listenerslength listeners; }; // 添加resize事件const addResizeListener = { const el = ; if !el return; if !el__resizeListeners__ el__resizeListeners__ = ; el__ro__ = resizeHandler; el__ro__; el__resizeListeners__;}; // 销毁resize事件const removeResizeListener = { const el = ; if !el || !el__resizeListeners__ return; el__resizeListeners__; if !el__resizeListeners__length el__ro__; };
2. 订阅-发布模式
{ thislist = {}; } // 订阅 { if !thislistkey thislistkey = ; thislistkey; } // 发布 { const fns = thislistkey; if !fns || !fnslength return; fns; } // 取消订阅 { const fns = thislistkey; if !fns || !fnslength return; if !fn fns = ; else fns = fns; } // 举例:const observer = const handler = { console}// 订阅observer// 发布observer // => 'Hello ZCoder'// 取消订阅observer
存储篇
因为在项目中我们可能需要对同一类型或者同一模块的数据分模块存储于本地,所以以下本地存储的工具类实现类似于命名空间的方式存储数据。
1. localStorage/sessionStorage
说明:以下只对 localStorage 封装进行讲解,sessionStorage 以此类推。
const Store = windowlocalStorage;const storeMap = ; // 存储不同模块本地存储信息列表 // 创建命名空间 { if storeMap return storeMap; storeMap; return storeMap;} { thisnamespaced = namespaced; thisstate = {}; // 本地存储JSON格式数据 this; } // 初始化当前命名空间的本地存储信息 { try const data = Store; if data thisstate = JSON; this; catch err thisstate = {}; this; } // 保存当前命名空间本地存储信息 { Store; } // 存储字段名对应的内容信息 { thisstatekey = data; this; return thisstate; } // 获取字段名对应的内容信息 { return thisstatekey; } // 删除字段名对应的内容信息 { thisstate = ; this; return thisstate; } // 清空当前命名空间的全部存储信息 { thisstate = {}; Store; } // 举例:const store = store // => {userInfo: {name: "ZCoder"}}store // => {userInfo: {name: "ZCoder"}, token: 1234} store // => {name: "ZCoder"} store // => {userInfo: {name: "ZCoder"}} storeclear'token'
2. cookie
说明:cookie的工具类是参考browser-cookies进行重写,暴露的API于其一致,具体的介绍与使用可以参考browser-cookies
平台判断篇
1. 通过正则表达式和userAgent判断平台类型(用于以下工具函数)
const isPlatform = {return regexp;};
2. 是否为移动设备
const isMobile =;
3. 是否为PC设备
const isPc = !;
4. 是否为iOS
const isIOS = ;
5. 是否为iPad
const isIPad = ;
6. 是否为安卓
const isAndroid = ;
7. 是否为Chrome浏览器
const isChrome = ;
8. 是否为火狐浏览器
const isFirefox = ;
9. 是否为Safari浏览器
const isSafari = ;
10. 是否为QQ浏览器
const isQQBrowser = ;
11. 是否为微信平台
const isMicroMessenger = ;
12. 是否为微博
const isWeibo = ;
12. 其他设备判断
const isDevice = ;
链接篇
1. 将链接参数转为JSON格式返回
const getParam2Json = {const search = url;const result = {};const reg = /=/g;search;return result;}// 举例:// => {name: "ZCoder", email: "xxx126"}
2. 获取链接指定字段名的值
说明:如果参数
key
为字符串数组则返回key-value对象
const getUrlParam = {const params = ;if Arraylet res = {};key;return res;else if typeof key === "string"return paramskey;return void 0;}// 举例:// => "ZCoder"
3. 转换JSON为链接参数字符串
说明:参数
json
为key-value对象,如:{name: 'ZCoder'}
const getJson2Param = {if !json return "";return Object;};// 举例:// => "name=ZCoder&email=xxx126"
4. 添加参数到链接上
说明:参数
params
为key-value对象,如:{name: 'ZCoder'}
const addParam2Url = {const path = url0;let json = ;const paramStr = ;return `?`;};// 举例:// => "http://www.baidu.com?email=xxx126&name=ZCoder"
5.删除链接指定的参数
说明:参数
params
如果为字符串时,多个字段名用英文','连接,如果为字符串数组是,则每个元素对应一个字段名,如果不传或者传的时空字符串或者空数组则删除全部参数
const removeParamFromUrl = {const path = url0;if !params || Array && !paramslength return path;let json = ;json =;const paramStr = ;return paramStr ? `?` : path;}// 举例:// => "http://www.baidu.com?email=xxx126"// => "http://www.baidu.com"// => "http://www.baidu.com"
其他
1. 节流
说明:用于有连续事件响应,每间隔一定时间触发一次 func: 回调 wait: 触发长度间隔时间 leading: leading=false首次不会触发(如果触发了多次)
const throttle = {let previous = 0;let timer = null;const handler = {func;};return {const now = Date;if !previous && leading === falseprevious = now;const remaining = interval - now - previous;timer && ;if remaining <= 0previous = now;;elsetimer = ;};}
2. 防抖
说明:用于连续事件触发结束后只触发一次 func:回调 wait:触发长度间隔时间 immediate:是否立即执行
const debounce = {let timer = null;const handler = {func;};return {if immediate && !timer;timer && ;timer = ;};}
3. Promise结果以数组形式返回
说明:主要用于async/await 返回结果的第一个元素为错误信息,第二个元素为返回结果 如果成功则返回的第一个元素(错误信息)为null,否则为错误信息 promise: Promise对象 error:错误信息,可选
const syncPromise =promise;// 举例:{const err res = awaitconsole}{return Promise}{return Promise}// => [null, '成功']// => ['失败', undefined]
4. requestAnimationFrame/cancelAnimationFrame 兼容模式
const requestAnimationFrame =windowrequestAnimationFrame ||windowwebkitRequestAnimationFrame ||windowmozRequestAnimationFrame ||{animationTimer = ;};const cancelAnimationFrame =windowcancelAnimationFrame ||windowwebkitCancelAnimationFrame ||windowmozCancelAnimationFrame ||{;};
5. 延时函数
说明:
time
为毫秒级别
const delay ={;};// 举例:// => 三秒后打印
6. 组合函数
说明:倒序调用
{const start = argslength - 1;return {let i = start;let result = argsstart;while i-- result = argsi;return result;};}
7. 复制到剪切板(异步方式)
const copy ={const el = document;elvalue = str;el;elstyleposition = "absolute";elstyleleft = "-9999px";documentbody;const selected =documentrangeCount > 0? document: false;el;let isSuccess = false;if documentexecCommand && documentdocument;documentbody;isSuccess = true;if selecteddocument;document;isSuccess ? : ;};// 举例:
8. 匹配提供的正则表达式
说明:用下以下规则判断
const isRule = rule;
9. 是否为合法链接
const isLink =;
10. 是否为合法邮箱
const isEMail =;
11. 是否为合法手机号码
const isTel =
12. 是否为合法固话
const isLandline = ;
13. 是否为合法身份证
const isIdCard = ;
14. 是否为合法QQ
const isQQ = ;
15. 是否为合法微信
const isWechat = ;
16. 是否为邮政编码
const isPost = ;
17. 是否为汉字
const isCharacters = ;
18. 全屏功能
说明:该工具类参考screenfull开发。
const ScreenFullAPIList ="exitFullscreen""requestFullscreen""fullscreenElement""fullscreenEnabled""fullscreenchange""fullscreenerror";const ScreenfullHash = {const prefix = "webkit" "" "moz" "ms";for let i = 0; i < prefixlength; i++ifindocumentreturn ScreenFullAPIList;};{return documentScreenfullHashfullscreenElement || docunentfullscreen;}{documentScreenfullHashfullscreenEnabled;}// 推出全屏{return {if !thisisFullScreen;return;const exitCallback = {this;;};this;;};}// 触发全屏{const element = el || documentdocumentElement || documentbody;return {const requestCallback = {this;;};this;;};}// 全屏切换{return thisisFullscreen ? this : this;}{this;}{this;}{document;}{document;}// 举例:const screenfull =screen // 全屏screen //推出全屏