# yjr-utils **Repository Path**: yanjingrui/yjr-utils ## Basic Information - **Project Name**: yjr-utils - **Description**: utils for js/ts - **Primary Language**: TypeScript - **License**: MIT - **Default Branch**: master - **Homepage**: https://static-mp-70f40d83-5328-46f9-b7de-0d8f6e8db731.next.bspapp.com/utils/ - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-09-23 - **Last Updated**: 2025-08-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: TypeScript, JavaScript, utils ## README **yjr-utils 在线文档 [点击进入](https://static-mp-70f40d83-5328-46f9-b7de-0d8f6e8db731.next.bspapp.com/utils/)** # 下载安装 **此包采用 ESModule 规范编写** ```js npm i yjr-utils pnpm i yjr-utils yarn add yjr-utils ``` # 如何使用 **全部加载** ```js import * as yjrUtils from 'yjr-utils'; ``` **按需引入** ```js import { fillZero, cloneDeep } from 'yjr-utils'; ``` # 目录 ## 1.单数补 0 **单独补 0** ```js import { fillZero } from 'yjr-utils'; fillZero('3'); // '03' fillZero('13'); // '13' ``` **支持分隔符来批量补 0** ```js fillZero('1:5:9', ':'); // '01:05:09' fillZero('13:6:29', ':'); // '13:06:29' ``` ## 2.深拷贝 **推荐使用 js 原生的深拷贝方法 structuredClone** ```ts /** * 如果担心兼容性可手动引入以下路径来充当垫片; * ( yjr-utils 内置了core-js ) */ import 'core-js/actual/structured-clone'; const data = [ { array: [1, 2, 3], }, ]; const data_2 = structuredClone(data); data === data_2; // false ``` **或者使用 lodash 的 cloneDeep** ```ts // yjr-utils 内部直接转发 lodash 的 cloneDeep import { cloneDeep } from 'yjr-utils'; const obj = { arr: [1, 2, 3], }; const obj_2 = cloneDeep(obj); obj === obj_2; // false ``` ## 3.数组去重 ( _浅拷贝_ ) **基本数据类型去重** ```ts import { toSet } from 'yjr-utils'; toSet(['str', 'str', 110, 110, true, true]); // 运行结果 ['str', 110, true]; ``` **引用数据类型去重(根据某个路径)** ```ts import { toSet } from 'yjr-utils'; toSet( [ { info: [180, 1] }, { info: [177, 2] }, { info: [178, 3] }, { info: [178, 3] }, { info: [171, 5] }, ], 'info[0]', ); // 运行结果 [ { info: [180, 1] }, { info: [177, 2] }, { info: [178, 3] }, { info: [171, 5] }, ]; ``` ## 4.数组排序 ( _浅拷贝_ ) **基本数据类型** ```ts import { doSort } from 'yjr-utils'; doSort([1, 7, 9, 5]); // [ 1, 5, 9, 7 ] doSort([1, 7, 9, 5], 'desc'); // [ 9, 7, 5, 1 ] doSort(['a', 'b', 'd', 'c'], 'asc', 'english'); // [ 'a', 'b', 'c', 'd' ] doSort(['a', 'b', 'd', 'c'], 'desc', 'english'); // [ 'd', 'c', 'b', 'a' ] doSort(['花', '园', '宝', '宝'], 'asc', 'chinese'); // [ '宝', '宝', '花', '园' ] doSort(['花', '园', '宝', '宝'], 'desc', 'chinese'); // [ '园', '花', '宝', '宝' ] ``` **引用数据类型** ```ts import { doSort } from 'yjr-utils'; const data = [ { a: { c: { d: 20 } }, b: 10 }, { a: { c: { d: 18 } }, b: 10 }, { a: { c: { d: 17 } }, b: 10 }, ]; doSort(data, 'asc', 'number', 'a.c.d'); // 结果 [ { a: { c: { d: 17 } }, b: 10 }, { a: { c: { d: 18 } }, b: 10 }, { a: { c: { d: 20 } }, b: 10 }, ]; ``` ## 5.获得最大/小值 ( _浅拷贝_ ) ```js import { getExtreme } from 'yjr-utils'; getExtreme([1, 2, 99]); // 99 getExtreme([1, 2, 99], 'min'); // 1 // 引用数据类型使用 const data = [ { a: { c: { d: 20 } } }, { a: { c: { d: 18 } } }, { a: { c: { d: 17 } } }, ]; getExtreme(data, 'min', 'a.c.d'); // { a: { c: { d: 17 } } } getExtreme(data, 'max', 'a.c.d'); // { a: { c: { d: 20 } } } ``` ## 6.时间格式化 **第二个参数是格式化模版,默认值是'YYYY-MM-DD HH:mm:ss'** ```ts import { timeFormat } from 'yjr-utils'; timeFormat('1999-05-12'); // '1999-05-12 08:00:00' timeFormat(1662622488019, 'YYYY年MM月DD日 HH点mm分ss秒'); // '2022年09月08日 15点34分48秒' ``` ## 7.获得时间差 **传入两个时间,返回一个 [ 天,时,分,秒 ] 组成的数组** ```ts import { timeGap } from 'yjr-utils'; timeGap('2022-09-08 07:23:46', '2022-09-05 10:43:43'); // ['02','20','40','03'] 两个时间相差2天20小时40分钟3秒 timeGap(1662521026000, 1661999899000); // ['06','00','45','26'] 两个时间相差6天0小时45分钟26秒 ``` **传入模板则直接返回格式化好的字符串** ```ts timeGap('2022-09-08 22:23:46', '2022-09-08 10:43:43', '还剩HH小时mm分钟ss秒'); // '还剩11小时40分钟03秒' timeGap('2022-09-08 13:23:46', '2022-09-05 19:54:34', 'DD天HH时mm分ss秒'); // '02天17时29分12秒' timeGap(1662521026000, 1661999899000, 'DD天HH时mm分ss秒'); // '06天00时45分26秒' ``` ## 8.排序效仿 ( _浅拷贝_ ) ```ts import { sortImitate } from 'yjr-utils'; const target = [ { type: 'A', name: '小王' }, { type: 'S', name: '小明' }, { type: 'SS', name: '小红' }, ]; const source = [ { type: 'SS', name: '小强' }, { type: 'A', name: '小刚' }, { type: 'S', name: '小金' }, ]; sortImitate(target, source, 'type'); // 结果 [ { type: 'A', name: '小刚' }, { type: 'S', name: '小金' }, { type: 'SS', name: '小强' }, ]; ``` ## 9.对象成员过滤(回调) ```js import { pickBy } from 'yjr-utils'; const obj = { a: 1, ac2: 2, a3: 3, ac4: 4, }; pickBy(obj, (val) => val >= 2); // { ac2: 2, a3: 3, ac4: 4 } pickBy(obj, (_val, key) => key.startsWith('ac')); // { ac2: 2, ac4: 4 } ``` ## 10.对象成员过滤(回调),逆向 ```js import { omitBy } from 'yjr-utils'; const obj = { a: 1, ac2: 2, a3: 3, ac4: 4, }; omitBy(obj, (val) => val >= 2); // { a: 1 } omitBy(obj, (_val, key) => key.startsWith('ac')); // { a: 1, a3: 3 } ``` ## 11.防抖 ```ts import { debounce } from 'yjr-utils'; const func = () => console.log('resizing'); window.onresize = debounce(func, 500, { // 不等待第一个定时器结束,直接执行 leading: true, // 如果一直被阻塞无法执行代码,则2秒内必定执行一次 maxWait: 2000, }); // 取消 window.onresize.cancel(); // 刷新 window.onresize.flush(); ``` ## 12.节流 ```ts import { throttle } from 'yjr-utils'; const func = () => console.log('resizing'); window.onscroll = throttle(func, 200, { // 不等待第一个定时器结束,直接执行 leading: true, }); // 取消 window.onscroll.cancel(); // 刷新 window.onscroll.flush(); ``` ## 13.数组分割 ```ts import { chunk } from 'yjr-utils'; chunk([1, 2, 3, 4], 2); // [[1,2],[3,4]] 两个成员一组来分组 chunk([1, 2, 3, 4], 3); // [[1,2,3],[4]] 三个成员一组来分组 const data = [ { a: 1, b: 1 }, { a: 2, b: 2 }, { a: 3, b: 3 }, { a: 4, b: 4 }, ]; chunk(data, 2); // 结果 [ [ { a: 1, b: 1 }, { a: 2, b: 2 }, ], [ { a: 3, b: 3 }, { a: 4, b: 4 }, ], ]; ``` ## 14.获得一个随机数 ```ts import { random } from 'yjr-utils'; random(-10, 20); // -2 random(5, 10); // 7 random(1.2, 5.2); // 3.4508875522514773 // 不返回整数 random(0, 4, true); // 3.154170094134428 random(0, 4); // 3 ``` ## 15. 文字超出省略 **支持 空格-汉字-数字-字母-特殊字符-字体图标-表情 等 7 种字符省略处理** ```ts import { textEllipsis } from 'yjr-utils'; textEllipsis('Ab&_12看看 👀🆕😊❤️', 10); // 'Ab&_12看看 👀...' textEllipsis('🉑️23', 3); // '🉑️2...' 某些非常特殊的字体图标会占用2个位置 textEllipsis('❤️ab', 3); // '❤️a...' 某些非常特殊的字体图标会占用2个位置 textEllipsis('abcdef', 4, true); // 'a...' 开启严格模式,'...'也会消费你传入的长度 ``` ## 16.剩余时间 **timeGap 的简化版本,直接传入一个差值时间戳** ```ts import { remainTime } from 'yjr-utils'; remainTime(7081940); // ['00', '01', '58', '02'] remainTime(7081940, '还剩DD天HH小时mm分钟ss秒'); // '还剩00天01小时58分钟02秒' ``` ## 17.监听元素是否可见 ```html
``` ```ts import { watchDomIsVisible } from 'yjr-utils'; const dom = document.getElementById('box'); const handler = (e) => { console.log(e ? '元素可见' : '元素不可见'); }; const { watch, unwatch } = watchDomIsVisible(dom, handler); watch(); // 开始监听 元素露出50%算作可见,反之不可见 unwatch(); // 停止监听 ``` **还可以设置阈值** ```ts // 阈值默认为0.5 可传0-1 const { watch, unwatch } = watchDomIsVisible(dom, handler, 0.3); watch(); // 开始监听 元素露出30%算作可见,反之不可见 unwatch(); // 停止监听 ``` ## 18.获取数据类型 ```ts import { getType } from 'yjr-utils'; getType([1, 2, 3]); // 'array' getType({ a: 10 }); // 'object' getType(null); // 'null' ``` ## 19.合并数据 ```js import { merge } from 'yjr-utils'; const base = { a: [{ b: 2 }, { d: 4 }], }; const other = { a: [{ c: 3 }, { e: 5 }], }; merge(base, other); // 结果 { a: [ { b: 2, c: 3 }, { d: 4, e: 5 }, ]; } ``` ## 20.判断两个变量是否相等 ```ts import { isEqual } from 'yjr-utils'; const base = { a: [1, 2, 3], }; const other = { a: [1, 2, 3], }; isEqual(base, other); // true 结构完全相同 base === other; // false 内存地址不一样 ``` ## 21.使用未发布的数组 Api **如果你想使用 findLast,findLastIndex,with,toSpliced,toReversed** **这些已经在 ESNext.d.ts 中出现但未发布的数组方法,导入该模块即可** ```ts import 'yjr-utils/src/arrayPolyfills.js'; ``` **如果是 ts 项目,则还需要在你项目中的 d.ts 文件中引入声明文件** ```ts ///