react-util-tools 1.0.0
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 +254 -0
- package/dist/index.cjs +943 -0
- package/dist/index.d.cts +154 -0
- package/dist/index.d.ts +154 -0
- package/dist/index.js +852 -0
- package/package.json +50 -0
- package/src/address/README.md +196 -0
- package/src/address/index.ts +41 -0
- package/src/date/README.md +539 -0
- package/src/date/index.ts +330 -0
- package/src/date/utc/README.md +779 -0
- package/src/date/utc/index.ts +374 -0
- package/src/decimal/README.md +425 -0
- package/src/decimal/index.ts +9 -0
- package/src/decimal/utils/README.md +474 -0
- package/src/decimal/utils/index.ts +244 -0
- package/src/device/README.md +441 -0
- package/src/device/index.ts +214 -0
- package/src/format/README.md +335 -0
- package/src/format/index.ts +189 -0
- package/src/index.ts +107 -0
- package/src/throttle/README.md +152 -0
- package/src/throttle/index.ts +83 -0
- package/tsconfig.json +28 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Throttle 工具
|
|
2
|
+
|
|
3
|
+
提供节流(throttle)和防抖(debounce)功能的工具集。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install your-package-name
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 使用方法
|
|
12
|
+
|
|
13
|
+
### 导入
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
// 按需导入,只打包用到的代码
|
|
17
|
+
import { throttle, debounce } from 'your-package-name'
|
|
18
|
+
|
|
19
|
+
// 或者只导入需要的
|
|
20
|
+
import { throttle } from 'your-package-name'
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### throttle - 节流函数
|
|
24
|
+
|
|
25
|
+
节流函数会在指定时间内只执行一次,适用于需要限制函数执行频率的场景。
|
|
26
|
+
|
|
27
|
+
**参数:**
|
|
28
|
+
- `fn`: 要节流的函数
|
|
29
|
+
- `wait`: 间隔时间(毫秒),默认 3000ms
|
|
30
|
+
- `options`: 配置选项
|
|
31
|
+
- `leading`: 是否在开始时触发,默认 `true`
|
|
32
|
+
- `trailing`: 是否在结束时触发,默认 `true`
|
|
33
|
+
|
|
34
|
+
**示例:**
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { throttle } from 'your-package-name'
|
|
38
|
+
|
|
39
|
+
// 基础用法 - 滚动事件节流
|
|
40
|
+
const handleScroll = throttle(() => {
|
|
41
|
+
console.log('页面滚动中...')
|
|
42
|
+
}, 1000)
|
|
43
|
+
|
|
44
|
+
window.addEventListener('scroll', handleScroll)
|
|
45
|
+
|
|
46
|
+
// 带参数的函数
|
|
47
|
+
const handleResize = throttle((width: number, height: number) => {
|
|
48
|
+
console.log(`窗口大小: ${width}x${height}`)
|
|
49
|
+
}, 500)
|
|
50
|
+
|
|
51
|
+
window.addEventListener('resize', () => {
|
|
52
|
+
handleResize(window.innerWidth, window.innerHeight)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
// 配置选项 - 只在结束时触发
|
|
56
|
+
const handleInput = throttle(
|
|
57
|
+
(value: string) => {
|
|
58
|
+
console.log('输入值:', value)
|
|
59
|
+
},
|
|
60
|
+
1000,
|
|
61
|
+
{ leading: false, trailing: true }
|
|
62
|
+
)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**适用场景:**
|
|
66
|
+
- 滚动事件处理
|
|
67
|
+
- 窗口 resize 事件
|
|
68
|
+
- 鼠标移动事件
|
|
69
|
+
- 频繁的 API 调用限制
|
|
70
|
+
|
|
71
|
+
### debounce - 防抖函数
|
|
72
|
+
|
|
73
|
+
防抖函数会在触发后等待指定时间,如果在等待期间再次触发则重新计时,适用于需要等待用户停止操作后再执行的场景。
|
|
74
|
+
|
|
75
|
+
**参数:**
|
|
76
|
+
- `fn`: 要防抖的函数
|
|
77
|
+
- `wait`: 延迟时间(毫秒),默认 500ms
|
|
78
|
+
- `immediate`: 是否在第一次触发时立即执行,默认 `false`
|
|
79
|
+
|
|
80
|
+
**示例:**
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { debounce } from 'your-package-name'
|
|
84
|
+
|
|
85
|
+
// 基础用法 - 搜索输入防抖
|
|
86
|
+
const handleSearch = debounce((keyword: string) => {
|
|
87
|
+
console.log('搜索关键词:', keyword)
|
|
88
|
+
// 执行搜索 API 调用
|
|
89
|
+
}, 500)
|
|
90
|
+
|
|
91
|
+
searchInput.addEventListener('input', (e) => {
|
|
92
|
+
handleSearch(e.target.value)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
// 立即执行模式
|
|
96
|
+
const handleSave = debounce(
|
|
97
|
+
() => {
|
|
98
|
+
console.log('保存数据')
|
|
99
|
+
},
|
|
100
|
+
1000,
|
|
101
|
+
true // 第一次点击立即执行
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
saveButton.addEventListener('click', handleSave)
|
|
105
|
+
|
|
106
|
+
// 表单验证
|
|
107
|
+
const validateEmail = debounce((email: string) => {
|
|
108
|
+
if (email.includes('@')) {
|
|
109
|
+
console.log('邮箱格式正确')
|
|
110
|
+
} else {
|
|
111
|
+
console.log('邮箱格式错误')
|
|
112
|
+
}
|
|
113
|
+
}, 300)
|
|
114
|
+
|
|
115
|
+
emailInput.addEventListener('input', (e) => {
|
|
116
|
+
validateEmail(e.target.value)
|
|
117
|
+
})
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**适用场景:**
|
|
121
|
+
- 搜索框输入
|
|
122
|
+
- 表单验证
|
|
123
|
+
- 按钮防重复点击
|
|
124
|
+
- 自动保存功能
|
|
125
|
+
|
|
126
|
+
## 区别说明
|
|
127
|
+
|
|
128
|
+
### Throttle(节流)
|
|
129
|
+
- 按照固定时间间隔执行
|
|
130
|
+
- 保证在一定时间内至少执行一次
|
|
131
|
+
- 像水龙头限流,控制流量
|
|
132
|
+
|
|
133
|
+
### Debounce(防抖)
|
|
134
|
+
- 等待操作停止后才执行
|
|
135
|
+
- 如果持续触发则不会执行
|
|
136
|
+
- 像电梯关门,有人进来就重新计时
|
|
137
|
+
|
|
138
|
+
## TypeScript 支持
|
|
139
|
+
|
|
140
|
+
完整的 TypeScript 类型支持,自动推断函数参数和返回值类型。
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
import { throttle } from 'your-package-name'
|
|
144
|
+
|
|
145
|
+
// 类型会被正确推断
|
|
146
|
+
const handler = throttle((x: number, y: string) => {
|
|
147
|
+
console.log(x, y)
|
|
148
|
+
}, 1000)
|
|
149
|
+
|
|
150
|
+
handler(123, 'test') // ✓ 正确
|
|
151
|
+
handler('test', 123) // ✗ 类型错误
|
|
152
|
+
```
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 节流函数:在 wait 时间内只执行一次
|
|
3
|
+
* @param fn 要节流的函数
|
|
4
|
+
* @param wait 间隔时间(默认 3000ms)
|
|
5
|
+
* @param options {leading, trailing} 是否在开始或结束时触发
|
|
6
|
+
*/
|
|
7
|
+
function throttleFn<T extends (...args: any[]) => any>(
|
|
8
|
+
fn: T,
|
|
9
|
+
wait = 3000,
|
|
10
|
+
options: { leading?: boolean; trailing?: boolean } = {}
|
|
11
|
+
): (...args: Parameters<T>) => void {
|
|
12
|
+
let timeout: ReturnType<typeof setTimeout> | null = null
|
|
13
|
+
let lastCallTime: number | null = null
|
|
14
|
+
let lastArgs: Parameters<T> | null = null
|
|
15
|
+
const { leading = true, trailing = true } = options
|
|
16
|
+
|
|
17
|
+
const invoke = (time: number) => {
|
|
18
|
+
fn(...(lastArgs as Parameters<T>))
|
|
19
|
+
lastCallTime = time
|
|
20
|
+
lastArgs = null
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return function (...args: Parameters<T>) {
|
|
24
|
+
const now = Date.now()
|
|
25
|
+
if (lastCallTime === null && !leading) {
|
|
26
|
+
lastCallTime = now
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const remaining = wait - (now - (lastCallTime ?? 0))
|
|
30
|
+
lastArgs = args
|
|
31
|
+
|
|
32
|
+
if (remaining <= 0) {
|
|
33
|
+
if (timeout) {
|
|
34
|
+
clearTimeout(timeout)
|
|
35
|
+
timeout = null
|
|
36
|
+
}
|
|
37
|
+
invoke(now)
|
|
38
|
+
} else if (!timeout && trailing) {
|
|
39
|
+
timeout = setTimeout(() => {
|
|
40
|
+
timeout = null
|
|
41
|
+
if (trailing && lastArgs) {
|
|
42
|
+
invoke(Date.now())
|
|
43
|
+
}
|
|
44
|
+
}, remaining)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 防抖函数:触发后 wait 毫秒内不再触发则执行
|
|
51
|
+
* @param fn 要防抖的函数
|
|
52
|
+
* @param wait 延迟时间(默认 500ms)
|
|
53
|
+
* @param immediate 是否在第一次触发时立即执行
|
|
54
|
+
*/
|
|
55
|
+
function debounceFn<T extends (...args: any[]) => any>(
|
|
56
|
+
fn: T,
|
|
57
|
+
wait = 500,
|
|
58
|
+
immediate = false
|
|
59
|
+
): (...args: Parameters<T>) => void {
|
|
60
|
+
let timeout: ReturnType<typeof setTimeout> | null = null
|
|
61
|
+
|
|
62
|
+
return function (...args: Parameters<T>) {
|
|
63
|
+
const callNow = immediate && !timeout
|
|
64
|
+
|
|
65
|
+
if (timeout) {
|
|
66
|
+
clearTimeout(timeout)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
timeout = setTimeout(() => {
|
|
70
|
+
timeout = null
|
|
71
|
+
if (!immediate) {
|
|
72
|
+
fn(...args)
|
|
73
|
+
}
|
|
74
|
+
}, wait)
|
|
75
|
+
|
|
76
|
+
if (callNow) {
|
|
77
|
+
fn(...args)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 按需导出:支持 Tree Shaking
|
|
83
|
+
export { throttleFn as throttle, debounceFn as debounce }
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"lib": ["ES2020", "DOM"],
|
|
6
|
+
"moduleResolution": "bundler",
|
|
7
|
+
"resolveJsonModule": true,
|
|
8
|
+
"allowJs": true,
|
|
9
|
+
"checkJs": false,
|
|
10
|
+
"jsx": "react-jsx",
|
|
11
|
+
"declaration": true,
|
|
12
|
+
"declarationMap": true,
|
|
13
|
+
"sourceMap": true,
|
|
14
|
+
"outDir": "./dist",
|
|
15
|
+
"rootDir": "./src",
|
|
16
|
+
"removeComments": true,
|
|
17
|
+
"esModuleInterop": true,
|
|
18
|
+
"forceConsistentCasingInFileNames": true,
|
|
19
|
+
"strict": true,
|
|
20
|
+
"noUnusedLocals": true,
|
|
21
|
+
"noUnusedParameters": true,
|
|
22
|
+
"noFallthroughCasesInSwitch": true,
|
|
23
|
+
"skipLibCheck": true,
|
|
24
|
+
"allowSyntheticDefaultImports": true
|
|
25
|
+
},
|
|
26
|
+
"include": ["src/**/*"],
|
|
27
|
+
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
|
|
28
|
+
}
|