pen-it 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # pen-it
2
2
 
3
- > 前端常用工具函数,笔笔记下,随手即用
4
-
5
- 一个轻量级的前端工具函数库,涵盖类型判断、日期格式化、数字格式化、字符串处理、存储操作、深拷贝、数组操作、Cookie 操作、浏览器 API 等常用场景。
3
+ 用笔锚定记忆中的前端常用工具函数,一个轻量级的前端实用程序库,支持类型检查、日期/数字格式化、字符串操作、数据存储、深度克隆、数组操作、Cookie 以及浏览器 API
6
4
 
7
5
  ## 安装
8
6
 
@@ -504,4 +502,24 @@ import { isArray, formatFull, deepClone, unique } from 'pen-it'
504
502
 
505
503
  ```ts
506
504
  const off = onScroll(y => console.log(y))
505
+ ```
506
+
507
+ ---
508
+
509
+ ### 防抖与节流 — `control`
510
+
511
+ - **`debounce(fn, delay?, options?)`** — 防抖,停止调用 delay 毫秒后才执行。
512
+
513
+ ```ts
514
+ const fn = debounce((val: string) => console.log(val), 500)
515
+ fn('a'); fn('b'); fn('c')
516
+ // => 'c'
517
+ ```
518
+
519
+ - **`throttle(fn, interval?, options?)`** — 节流,固定间隔内最多执行一次。
520
+
521
+ ```ts
522
+ const fn = throttle((val: string) => console.log(val), 500)
523
+ fn('a'); fn('b'); fn('c')
524
+ // => 'a',500ms 后输出 'c'
507
525
  ```
@@ -0,0 +1,36 @@
1
+ /**
2
+ * 防抖 —— 在事件被触发 n 秒后再执行,如果 n 秒内再次触发则重新计时
3
+ * @param fn - 需要防抖的函数
4
+ * @param delay - 延迟时间(毫秒),默认 300
5
+ * @param options.leading - 首次调用是否立即执行,默认 false
6
+ * @param options.trailing - 停止调用后是否延迟执行,默认 true
7
+ * @returns 防抖后的函数,附带 cancel 方法
8
+ * @example
9
+ * const fn = debounce((val: string) => console.log(val), 500)
10
+ * fn("a"); fn("b"); fn("c")
11
+ * // => "c"
12
+ */
13
+ export declare const debounce: <T extends (...args: any[]) => any>(fn: T, delay?: number, { leading, trailing }?: {
14
+ leading?: boolean;
15
+ trailing?: boolean;
16
+ }) => ((...args: Parameters<T>) => void) & {
17
+ cancel: () => void;
18
+ };
19
+ /**
20
+ * 节流 —— 固定间隔内最多执行一次,超出频率的调用被忽略
21
+ * @param fn - 需要节流的函数
22
+ * @param interval - 间隔时间(毫秒),默认 300
23
+ * @param options.leading - 首次调用是否立即执行,默认 true
24
+ * @param options.trailing - 最后一次调用后是否尾部执行,默认 true
25
+ * @returns 节流后的函数,附带 cancel 方法
26
+ * @example
27
+ * const fn = throttle((val: string) => console.log(val), 500)
28
+ * fn("a"); fn("b"); fn("c")
29
+ * // => "a",500ms 后输出 "c"
30
+ */
31
+ export declare const throttle: <T extends (...args: any[]) => any>(fn: T, interval?: number, { leading, trailing }?: {
32
+ leading?: boolean;
33
+ trailing?: boolean;
34
+ }) => ((...args: Parameters<T>) => void) & {
35
+ cancel: () => void;
36
+ };
package/dist/index.cjs CHANGED
@@ -1020,11 +1020,98 @@ const onScroll = (callback) => {
1020
1020
  return () => window.removeEventListener("scroll", handler);
1021
1021
  };
1022
1022
  //#endregion
1023
+ //#region src/control/index.ts
1024
+ /**
1025
+ * 防抖 —— 在事件被触发 n 秒后再执行,如果 n 秒内再次触发则重新计时
1026
+ * @param fn - 需要防抖的函数
1027
+ * @param delay - 延迟时间(毫秒),默认 300
1028
+ * @param options.leading - 首次调用是否立即执行,默认 false
1029
+ * @param options.trailing - 停止调用后是否延迟执行,默认 true
1030
+ * @returns 防抖后的函数,附带 cancel 方法
1031
+ * @example
1032
+ * const fn = debounce((val: string) => console.log(val), 500)
1033
+ * fn("a"); fn("b"); fn("c")
1034
+ * // => "c"
1035
+ */
1036
+ const debounce = (fn, delay = 300, { leading = false, trailing = true } = {}) => {
1037
+ let timer = null;
1038
+ let lastArgs = null;
1039
+ let shouldTrail = trailing;
1040
+ const debounced = (...args) => {
1041
+ lastArgs = args;
1042
+ if (timer !== null) {
1043
+ clearTimeout(timer);
1044
+ shouldTrail = trailing;
1045
+ } else if (leading) {
1046
+ fn(...args);
1047
+ shouldTrail = false;
1048
+ }
1049
+ timer = setTimeout(() => {
1050
+ if (shouldTrail && lastArgs) fn(...lastArgs);
1051
+ timer = lastArgs = null;
1052
+ shouldTrail = trailing;
1053
+ }, delay);
1054
+ };
1055
+ debounced.cancel = () => {
1056
+ if (timer) {
1057
+ clearTimeout(timer);
1058
+ timer = lastArgs = null;
1059
+ }
1060
+ shouldTrail = trailing;
1061
+ };
1062
+ return debounced;
1063
+ };
1064
+ /**
1065
+ * 节流 —— 固定间隔内最多执行一次,超出频率的调用被忽略
1066
+ * @param fn - 需要节流的函数
1067
+ * @param interval - 间隔时间(毫秒),默认 300
1068
+ * @param options.leading - 首次调用是否立即执行,默认 true
1069
+ * @param options.trailing - 最后一次调用后是否尾部执行,默认 true
1070
+ * @returns 节流后的函数,附带 cancel 方法
1071
+ * @example
1072
+ * const fn = throttle((val: string) => console.log(val), 500)
1073
+ * fn("a"); fn("b"); fn("c")
1074
+ * // => "a",500ms 后输出 "c"
1075
+ */
1076
+ const throttle = (fn, interval = 300, { leading = true, trailing = true } = {}) => {
1077
+ let timer = null;
1078
+ let lastTime = 0;
1079
+ let pendingArgs = null;
1080
+ const throttled = (...args) => {
1081
+ const now = Date.now();
1082
+ if (!lastTime && !leading) lastTime = now;
1083
+ const remaining = interval - (now - lastTime);
1084
+ pendingArgs = args;
1085
+ if (remaining <= 0) {
1086
+ if (timer) {
1087
+ clearTimeout(timer);
1088
+ timer = null;
1089
+ }
1090
+ fn(...args);
1091
+ lastTime = now;
1092
+ pendingArgs = null;
1093
+ } else if (trailing && !timer) timer = setTimeout(() => {
1094
+ timer = null;
1095
+ lastTime = leading ? Date.now() : 0;
1096
+ if (pendingArgs) fn(...pendingArgs);
1097
+ pendingArgs = null;
1098
+ }, remaining);
1099
+ };
1100
+ throttled.cancel = () => {
1101
+ if (timer) {
1102
+ clearTimeout(timer);
1103
+ timer = pendingArgs = null;
1104
+ }
1105
+ };
1106
+ return throttled;
1107
+ };
1108
+ //#endregion
1023
1109
  exports.camelToKebab = camelToKebab;
1024
1110
  exports.capitalize = capitalize;
1025
1111
  exports.compactCN = compactCN;
1026
1112
  exports.compactEN = compactEN;
1027
1113
  exports.copyToClipboard = copyToClipboard;
1114
+ exports.debounce = debounce;
1028
1115
  exports.deepClone = deepClone;
1029
1116
  exports.deepCloneWithJSON = deepCloneWithJSON;
1030
1117
  exports.delCookie = delCookie;
@@ -1086,6 +1173,7 @@ exports.sortByKey = sortByKey;
1086
1173
  exports.sortNumAsc = sortNumAsc;
1087
1174
  exports.sortNumDesc = sortNumDesc;
1088
1175
  exports.spacePhone = spacePhone;
1176
+ exports.throttle = throttle;
1089
1177
  exports.toArray = toArray;
1090
1178
  exports.toCamel = toCamel;
1091
1179
  exports.toQueryString = toQueryString;
package/dist/index.d.ts CHANGED
@@ -5,3 +5,4 @@ export * from './copy';
5
5
  export * from './array';
6
6
  export * from './cookie';
7
7
  export * from './browser';
8
+ export * from './control';
package/dist/index.js CHANGED
@@ -1019,4 +1019,90 @@ const onScroll = (callback) => {
1019
1019
  return () => window.removeEventListener("scroll", handler);
1020
1020
  };
1021
1021
  //#endregion
1022
- export { camelToKebab, capitalize, compactCN, compactEN, copyToClipboard, deepClone, deepCloneWithJSON, delCookie, downloadFile, exportJSON, firstLower, firstUpper, formatFull, formatFullReplace, formatNum, formatRmb, formatWeek, formatYMD, getCookie, getUrlParam, getUrlParams, is, isArray, isAsyncFunction, isBoolean, isDate, isDef, isElement, isEmpty, isEmptySv, isEqual, isFloat, isFunction, isHexColor, isIOS, isInt, isNull, isNullOrUnDef, isNumber, isObject, isPC, isPrimitive, isPromise, isString, isSymbol, isUnDef, isValidEmail, isWindow, kebabToCamel, localClear, localGet, localRm, localSet, maskPhone, onScroll, percentCN, reverse, scrollToBottom, scrollToTop, setCookie, shallowClone, signed, sortByKey, sortNumAsc, sortNumDesc, spacePhone, toArray, toCamel, toQueryString, trimAll, truncate, truncateByWords, unique, uniqueByKey };
1022
+ //#region src/control/index.ts
1023
+ /**
1024
+ * 防抖 —— 在事件被触发 n 秒后再执行,如果 n 秒内再次触发则重新计时
1025
+ * @param fn - 需要防抖的函数
1026
+ * @param delay - 延迟时间(毫秒),默认 300
1027
+ * @param options.leading - 首次调用是否立即执行,默认 false
1028
+ * @param options.trailing - 停止调用后是否延迟执行,默认 true
1029
+ * @returns 防抖后的函数,附带 cancel 方法
1030
+ * @example
1031
+ * const fn = debounce((val: string) => console.log(val), 500)
1032
+ * fn("a"); fn("b"); fn("c")
1033
+ * // => "c"
1034
+ */
1035
+ const debounce = (fn, delay = 300, { leading = false, trailing = true } = {}) => {
1036
+ let timer = null;
1037
+ let lastArgs = null;
1038
+ let shouldTrail = trailing;
1039
+ const debounced = (...args) => {
1040
+ lastArgs = args;
1041
+ if (timer !== null) {
1042
+ clearTimeout(timer);
1043
+ shouldTrail = trailing;
1044
+ } else if (leading) {
1045
+ fn(...args);
1046
+ shouldTrail = false;
1047
+ }
1048
+ timer = setTimeout(() => {
1049
+ if (shouldTrail && lastArgs) fn(...lastArgs);
1050
+ timer = lastArgs = null;
1051
+ shouldTrail = trailing;
1052
+ }, delay);
1053
+ };
1054
+ debounced.cancel = () => {
1055
+ if (timer) {
1056
+ clearTimeout(timer);
1057
+ timer = lastArgs = null;
1058
+ }
1059
+ shouldTrail = trailing;
1060
+ };
1061
+ return debounced;
1062
+ };
1063
+ /**
1064
+ * 节流 —— 固定间隔内最多执行一次,超出频率的调用被忽略
1065
+ * @param fn - 需要节流的函数
1066
+ * @param interval - 间隔时间(毫秒),默认 300
1067
+ * @param options.leading - 首次调用是否立即执行,默认 true
1068
+ * @param options.trailing - 最后一次调用后是否尾部执行,默认 true
1069
+ * @returns 节流后的函数,附带 cancel 方法
1070
+ * @example
1071
+ * const fn = throttle((val: string) => console.log(val), 500)
1072
+ * fn("a"); fn("b"); fn("c")
1073
+ * // => "a",500ms 后输出 "c"
1074
+ */
1075
+ const throttle = (fn, interval = 300, { leading = true, trailing = true } = {}) => {
1076
+ let timer = null;
1077
+ let lastTime = 0;
1078
+ let pendingArgs = null;
1079
+ const throttled = (...args) => {
1080
+ const now = Date.now();
1081
+ if (!lastTime && !leading) lastTime = now;
1082
+ const remaining = interval - (now - lastTime);
1083
+ pendingArgs = args;
1084
+ if (remaining <= 0) {
1085
+ if (timer) {
1086
+ clearTimeout(timer);
1087
+ timer = null;
1088
+ }
1089
+ fn(...args);
1090
+ lastTime = now;
1091
+ pendingArgs = null;
1092
+ } else if (trailing && !timer) timer = setTimeout(() => {
1093
+ timer = null;
1094
+ lastTime = leading ? Date.now() : 0;
1095
+ if (pendingArgs) fn(...pendingArgs);
1096
+ pendingArgs = null;
1097
+ }, remaining);
1098
+ };
1099
+ throttled.cancel = () => {
1100
+ if (timer) {
1101
+ clearTimeout(timer);
1102
+ timer = pendingArgs = null;
1103
+ }
1104
+ };
1105
+ return throttled;
1106
+ };
1107
+ //#endregion
1108
+ export { camelToKebab, capitalize, compactCN, compactEN, copyToClipboard, debounce, deepClone, deepCloneWithJSON, delCookie, downloadFile, exportJSON, firstLower, firstUpper, formatFull, formatFullReplace, formatNum, formatRmb, formatWeek, formatYMD, getCookie, getUrlParam, getUrlParams, is, isArray, isAsyncFunction, isBoolean, isDate, isDef, isElement, isEmpty, isEmptySv, isEqual, isFloat, isFunction, isHexColor, isIOS, isInt, isNull, isNullOrUnDef, isNumber, isObject, isPC, isPrimitive, isPromise, isString, isSymbol, isUnDef, isValidEmail, isWindow, kebabToCamel, localClear, localGet, localRm, localSet, maskPhone, onScroll, percentCN, reverse, scrollToBottom, scrollToTop, setCookie, shallowClone, signed, sortByKey, sortNumAsc, sortNumDesc, spacePhone, throttle, toArray, toCamel, toQueryString, trimAll, truncate, truncateByWords, unique, uniqueByKey };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pen-it",
3
- "version": "1.0.3",
4
- "description": "用笔锚定记忆中的前端常用工具函数 A lightweight frontend utility library for type checking, date/number formatting, string manipulation, storage, deep clone, array operations, cookies, and browser APIs",
3
+ "version": "1.0.5",
4
+ "description": "用笔锚定记忆中的前端常用工具函数,一个轻量级的前端实用程序库,支持类型检查、日期/数字格式化、字符串操作、数据存储、深度克隆、数组操作、Cookie 以及浏览器 API",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.js",