mazey 4.13.2 → 5.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 +63 -6
- package/README.zh-CN.md +1028 -193
- package/lib/global.d.ts +5 -9
- package/lib/index.cjs.js +2 -2
- package/lib/index.d.ts +96 -42
- package/lib/index.esm.js +2 -2
- package/lib/mazey.min.js +2 -2
- package/lib/typing.d.ts +2 -2
- package/package.json +22 -11
- package/scripts/README.md +0 -38
- package/scripts/build-helper.js +0 -76
- package/scripts/change-package-name.js +0 -15
- package/scripts/dev.js +0 -7
- package/scripts/git-helper.js +0 -164
- package/scripts/release.js +0 -9
- package/scripts/rollup.config.mjs +0 -139
package/README.zh-CN.md
CHANGED
|
@@ -1,269 +1,971 @@
|
|
|
1
|
-
|
|
1
|
+
[English](https://github.com/chengchuu/mazey/blob/main/README.md) | 简体中文
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# Mazey
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[![npm version][npm-image]][npm-url]
|
|
6
|
+
[![l][l-image]][l-url]
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
[npm-image]: https://img.shields.io/npm/v/mazey
|
|
9
|
+
[npm-url]: https://npmjs.org/package/mazey
|
|
10
|
+
[l-image]: https://img.shields.io/npm/l/mazey
|
|
11
|
+
[l-url]: https://github.com/chengchuu/mazey
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<!-- omit from toc -->
|
|
13
|
-
## 目录
|
|
14
|
-
|
|
15
|
-
- [安装](#安装)
|
|
16
|
-
- [使用](#使用)
|
|
17
|
-
- [加载资源](#加载资源)
|
|
18
|
-
- [存储数据](#存储数据)
|
|
19
|
-
- [操作 DOM](#操作-dom)
|
|
20
|
-
- [网站性能](#网站性能)
|
|
21
|
-
- [公式计算](#公式计算)
|
|
22
|
-
- [浏览器信息](#浏览器信息)
|
|
23
|
-
- [安全边际](#安全边际)
|
|
24
|
-
- [函数](#函数)
|
|
25
|
-
- [调试](#调试)
|
|
26
|
-
- [开发](#开发)
|
|
27
|
-
- [参考](#参考)
|
|
13
|
+
Mazey 是一个面向日常前端开发的函数工具库。前端生态已有许多优秀的库,但项目通常仍会创建 `utils.js` 或 `common.js`,用于存放通用函数。在多个项目之间重复复制相似函数既烦琐,也难以维护。因此,我创建了 Mazey,并会持续更新,为前端开发提供可靠的通用工具。
|
|
28
14
|
|
|
29
15
|
## 安装
|
|
30
16
|
|
|
31
|
-
|
|
17
|
+
通过 [npm](https://www.npmjs.com/package/mazey) 安装 Mazey。
|
|
32
18
|
|
|
33
19
|
```bash
|
|
34
|
-
npm install mazey
|
|
20
|
+
npm install mazey --save
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
通过内容分发网络 (Content Delivery Network,CDN) 使用 Mazey。
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<script src="https://cdn.jsdelivr.net/npm/mazey@latest/lib/mazey.min.js"></script>
|
|
35
27
|
```
|
|
36
28
|
|
|
29
|
+
你也可以下载 [jsdelivr/lib/mazey.min.js](https://cdn.jsdelivr.net/npm/mazey@latest/lib/mazey.min.js),并自行托管该文件。
|
|
30
|
+
|
|
37
31
|
## 使用
|
|
38
32
|
|
|
39
|
-
|
|
33
|
+
下面的示例使用一个函数,判断某个值是否适合参与常规计算和比较。
|
|
40
34
|
|
|
41
|
-
|
|
35
|
+
通过 [npm](https://www.npmjs.com/package/mazey) 导入。
|
|
42
36
|
|
|
43
37
|
```javascript
|
|
44
|
-
import {
|
|
38
|
+
import { isNumber } from "mazey";
|
|
39
|
+
|
|
40
|
+
const x = 123;
|
|
41
|
+
const y = "abc";
|
|
42
|
+
const z = Infinity;
|
|
43
|
+
isNumber(x); // 输出: true
|
|
44
|
+
isNumber(y); // 输出: false
|
|
45
|
+
isNumber(z, { isInfinityAsNumber: true }); // 输出: true
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
通过 CDN 导入。
|
|
49
|
+
|
|
50
|
+
```html
|
|
51
|
+
<script src="https://cdn.jsdelivr.net/npm/mazey@latest/lib/mazey.min.js"></script>
|
|
52
|
+
<script>
|
|
53
|
+
const x = 123;
|
|
54
|
+
mazey.isNumber(x); // 输出: true
|
|
55
|
+
</script>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## API 示例
|
|
59
|
+
|
|
60
|
+
下面列出一些手动维护的 API (应用程序编程接口) 示例。完整内容请查看
|
|
61
|
+
[完整 API 文档](https://chengchuu.github.io/mazey/api/)。
|
|
62
|
+
|
|
63
|
+
### 目录
|
|
64
|
+
|
|
65
|
+
<!-- toc - begin -->
|
|
66
|
+
- [加载资源](#加载资源)
|
|
67
|
+
- [loadScript](#loadscript)
|
|
68
|
+
- [loadScriptIfUndefined](#loadscriptifundefined)
|
|
69
|
+
- [loadCSS](#loadcss)
|
|
70
|
+
- [loadImage](#loadimage)
|
|
71
|
+
- [windowLoaded](#windowloaded)
|
|
72
|
+
- [通用工具](#通用工具)
|
|
73
|
+
- [isNumber](#isnumber)
|
|
74
|
+
- [isJSONString](#isjsonstring)
|
|
75
|
+
- [isValidData](#isvaliddata)
|
|
76
|
+
- [genRndNumString](#genrndnumstring)
|
|
77
|
+
- [formatDate](#formatdate)
|
|
78
|
+
- [isValidDate](#isvaliddate)
|
|
79
|
+
- [generateCalendarVersion](#generatecalendarversion)
|
|
80
|
+
- [getDateDifference](#getdatedifference)
|
|
81
|
+
- [formatDurationFromMs](#formatdurationfromms)
|
|
82
|
+
- [deepCopy](#deepcopy)
|
|
83
|
+
- [deepFreeze](#deepfreeze)
|
|
84
|
+
- [debounce](#debounce)
|
|
85
|
+
- [throttle](#throttle)
|
|
86
|
+
- [convertCamelToKebab](#convertcameltokebab)
|
|
87
|
+
- [convertCamelToUnder](#convertcameltounder)
|
|
88
|
+
- [URL](#url)
|
|
89
|
+
- [getQueryParam](#getqueryparam)
|
|
90
|
+
- [getUrlParam](#geturlparam)
|
|
91
|
+
- [getHashQueryParam](#gethashqueryparam)
|
|
92
|
+
- [getDomain](#getdomain)
|
|
93
|
+
- [updateQueryParam](#updatequeryparam)
|
|
94
|
+
- [isValidUrl](#isvalidurl)
|
|
95
|
+
- [isValidHttpUrl](#isvalidhttpurl)
|
|
96
|
+
- [存储](#存储)
|
|
97
|
+
- [Cookie 工具](#cookie-工具)
|
|
98
|
+
- [Storage 工具](#storage-工具)
|
|
99
|
+
- [DOM](#dom)
|
|
100
|
+
- [Class 工具](#class-工具)
|
|
101
|
+
- [addStyle](#addstyle)
|
|
102
|
+
- [genStyleString](#genstylestring)
|
|
103
|
+
- [newLine](#newline)
|
|
104
|
+
- [计算与公式](#计算与公式)
|
|
105
|
+
- [inRate](#inrate)
|
|
106
|
+
- [longestComSubstring](#longestcomsubstring)
|
|
107
|
+
- [longestComSubsequence](#longestcomsubsequence)
|
|
108
|
+
- [浏览器信息](#浏览器信息)
|
|
109
|
+
- [getBrowserInfo](#getbrowserinfo)
|
|
110
|
+
- [isSafePWAEnv](#issafepwaenv)
|
|
111
|
+
- [Web 性能](#web-性能)
|
|
112
|
+
- [getPerformance](#getperformance)
|
|
113
|
+
- [调试](#调试)
|
|
114
|
+
- [genCustomConsole](#gencustomconsole)
|
|
115
|
+
<!-- toc - end -->
|
|
116
|
+
|
|
117
|
+
### 加载资源
|
|
118
|
+
|
|
119
|
+
#### loadScript
|
|
120
|
+
|
|
121
|
+
从服务器加载并执行 JavaScript 文件。
|
|
45
122
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
123
|
+
用法:
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
loadScript(
|
|
127
|
+
"http://example.com/static/js/plugin-2.1.1.min.js",
|
|
128
|
+
{
|
|
129
|
+
id: "iamid", // 可选,script 的 ID,默认不设置
|
|
130
|
+
timeout: 5000, // 可选,超时时间,默认 `5000`
|
|
131
|
+
}
|
|
132
|
+
)
|
|
52
133
|
.then(
|
|
53
134
|
res => {
|
|
54
|
-
console.log(`加载 JavaScript
|
|
135
|
+
console.log(`加载 JavaScript 脚本: ${res}`);
|
|
55
136
|
}
|
|
56
137
|
)
|
|
57
138
|
.catch(
|
|
58
139
|
err => {
|
|
59
|
-
console.error(`加载 JavaScript
|
|
140
|
+
console.error(`加载 JavaScript 脚本: ${err.message}`);
|
|
60
141
|
}
|
|
61
142
|
);
|
|
62
143
|
```
|
|
63
144
|
|
|
64
|
-
|
|
145
|
+
输出:
|
|
146
|
+
|
|
147
|
+
```text
|
|
148
|
+
加载 JavaScript 脚本: loaded
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
#### loadScriptIfUndefined
|
|
152
|
+
|
|
153
|
+
当脚本尚未加载时,函数会通过指定 URL (统一资源定位符) 加载脚本。该函数使用 `window["attribute"]` 判断脚本是否已定义。
|
|
154
|
+
|
|
155
|
+
用法:
|
|
65
156
|
|
|
66
157
|
```javascript
|
|
67
|
-
|
|
158
|
+
loadScriptIfUndefined("xyz", "https://example.com/lib/xyz.min.js")
|
|
159
|
+
.then(() => {
|
|
160
|
+
console.log("xyz 已加载。");
|
|
161
|
+
})
|
|
162
|
+
.catch(err => {
|
|
163
|
+
console.log("xyz 加载失败。", err);
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
输出:
|
|
168
|
+
|
|
169
|
+
```text
|
|
170
|
+
xyz 已加载。
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
#### loadCSS
|
|
174
|
+
|
|
175
|
+
从服务器加载 CSS 文件。
|
|
68
176
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
177
|
+
用法:
|
|
178
|
+
|
|
179
|
+
```javascript
|
|
180
|
+
loadCSS(
|
|
181
|
+
"https://example.com/path/example.css",
|
|
182
|
+
{
|
|
183
|
+
id: "iamid", // 可选,link 的 ID,默认不设置
|
|
184
|
+
}
|
|
185
|
+
)
|
|
73
186
|
.then(
|
|
74
187
|
res => {
|
|
75
|
-
console.log(
|
|
188
|
+
console.log(`CSS 加载成功: ${res}`);
|
|
76
189
|
}
|
|
77
190
|
)
|
|
78
191
|
.catch(
|
|
79
192
|
err => {
|
|
80
|
-
console.error(
|
|
193
|
+
console.error(`CSS 加载失败: ${err.message}`)
|
|
81
194
|
}
|
|
82
195
|
);
|
|
83
196
|
```
|
|
84
197
|
|
|
85
|
-
|
|
198
|
+
输出:
|
|
199
|
+
|
|
200
|
+
```text
|
|
201
|
+
CSS 加载成功: loaded
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
#### loadImage
|
|
205
|
+
|
|
206
|
+
从指定 URL 加载图片。
|
|
207
|
+
|
|
208
|
+
目标图片会在后台加载。加载失败时,Promise (承诺对象) 会以错误对象进入 `reject` 状态。加载成功时,Promise 会以图片对象进入 `resolve` 状态。该方法适合预加载图片,也可以利用浏览器缓存实现图片懒加载。
|
|
209
|
+
|
|
210
|
+
该方法不会把图片添加到文档对象模型 (Document Object Model,DOM)。
|
|
211
|
+
|
|
212
|
+
用法:
|
|
86
213
|
|
|
87
214
|
```javascript
|
|
88
|
-
|
|
215
|
+
loadImage("https://example.com/example.png")
|
|
216
|
+
.then((img) => {
|
|
217
|
+
console.log(img);
|
|
218
|
+
})
|
|
219
|
+
.catch((err) => {
|
|
220
|
+
console.log(err);
|
|
221
|
+
});
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
#### windowLoaded
|
|
225
|
+
|
|
226
|
+
检查页面是否成功加载。即使浏览器已经触发 `load` 事件,该函数仍能正确处理。
|
|
227
|
+
|
|
228
|
+
用法:
|
|
89
229
|
|
|
90
|
-
|
|
230
|
+
```javascript
|
|
231
|
+
windowLoaded()
|
|
91
232
|
.then(res => {
|
|
92
|
-
console.log(
|
|
233
|
+
console.log(`加载成功: ${res}`);
|
|
93
234
|
})
|
|
94
235
|
.catch(err => {
|
|
95
|
-
console.log(
|
|
236
|
+
console.log(`加载超时或失败: ${err.message}`);
|
|
96
237
|
});
|
|
97
238
|
```
|
|
98
239
|
|
|
99
|
-
|
|
240
|
+
输出:
|
|
241
|
+
|
|
242
|
+
```text
|
|
243
|
+
加载成功: load
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### 通用工具
|
|
247
|
+
|
|
248
|
+
#### isNumber
|
|
249
|
+
|
|
250
|
+
判断某个值是否为有效数字。
|
|
100
251
|
|
|
101
|
-
|
|
252
|
+
用法:
|
|
102
253
|
|
|
103
254
|
```javascript
|
|
104
|
-
|
|
255
|
+
const ret1 = isNumber(123);
|
|
256
|
+
const ret2 = isNumber("123");
|
|
257
|
+
// 默认情况下,NaN 和 Infinity 不是有效数字
|
|
258
|
+
const ret3 = isNumber(Infinity);
|
|
259
|
+
const ret4 = isNumber(Infinity, { isInfinityAsNumber: true });
|
|
260
|
+
const ret5 = isNumber(NaN);
|
|
261
|
+
const ret6 = isNumber(NaN, { isNaNAsNumber: true, isInfinityAsNumber: true });
|
|
262
|
+
console.log(ret1, ret2, ret3, ret4, ret5, ret6);
|
|
263
|
+
```
|
|
105
264
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
265
|
+
输出:
|
|
266
|
+
|
|
267
|
+
```text
|
|
268
|
+
true false false true false true
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
#### isJSONString
|
|
272
|
+
|
|
273
|
+
判断字符串是否为有效的 JSON 字符串。
|
|
274
|
+
|
|
275
|
+
用法:
|
|
276
|
+
|
|
277
|
+
```javascript
|
|
278
|
+
const ret1 = isJSONString(`['a', 'b', 'c']`);
|
|
279
|
+
const ret2 = isJSONString(`["a", "b", "c"]`);
|
|
280
|
+
console.log(ret1);
|
|
281
|
+
console.log(ret2);
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
输出:
|
|
285
|
+
|
|
286
|
+
```text
|
|
287
|
+
false
|
|
288
|
+
true
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
#### isValidData
|
|
292
|
+
|
|
293
|
+
判断指定路径中的数据是否有效,并且是否等于预期值。
|
|
294
|
+
|
|
295
|
+
用法:
|
|
296
|
+
|
|
297
|
+
```javascript
|
|
298
|
+
const validData = {
|
|
299
|
+
a: {
|
|
300
|
+
b: {
|
|
301
|
+
c: 413
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
const isValidDataResA = isValidData(validData, ["a", "b", "c"], 2333);
|
|
306
|
+
const isValidDataResB = isValidData(validData, ["a", "b", "c"], 413);
|
|
307
|
+
const isValidDataResC = isValidData(validData, ["d", "d"], 413);
|
|
308
|
+
console.log("isValidDataResA:", isValidDataResA);
|
|
309
|
+
console.log("isValidDataResB:", isValidDataResB);
|
|
310
|
+
console.log("isValidDataResC:", isValidDataResC);
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
输出:
|
|
314
|
+
|
|
315
|
+
```text
|
|
316
|
+
isValidDataResA: false
|
|
317
|
+
isValidDataResB: true
|
|
318
|
+
isValidDataResC: false
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
#### genRndNumString
|
|
322
|
+
|
|
323
|
+
生成指定长度的随机数字字符串。例如,`genRndNumString(7)` 可能返回 `"7658495"`。
|
|
324
|
+
|
|
325
|
+
用法:
|
|
326
|
+
|
|
327
|
+
```javascript
|
|
328
|
+
const ret1 = genRndNumString(4);
|
|
329
|
+
const ret2 = genRndNumString(7);
|
|
330
|
+
console.log(ret1);
|
|
331
|
+
console.log(ret2);
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
输出:
|
|
335
|
+
|
|
336
|
+
```text
|
|
337
|
+
9730
|
|
338
|
+
2262490
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
#### formatDate
|
|
342
|
+
|
|
343
|
+
按照指定格式返回本地日期字符串。`HH` 表示 24 小时制,`hh` 表示 12 小时制,`a` 表示 `AM` 或 `PM`。
|
|
344
|
+
|
|
345
|
+
用法:
|
|
346
|
+
|
|
347
|
+
```javascript
|
|
348
|
+
const ret1 = formatDate();
|
|
349
|
+
const ret2 = formatDate("Tue Jan 11 2022 14:12:26 GMT+0800 (China Standard Time)", "yyyy-MM-dd hh:mm:ss a");
|
|
350
|
+
const ret3 = formatDate(1641881235000, "yyyy-MM-dd hh:mm:ss a");
|
|
351
|
+
const ret4 = formatDate(new Date(2014, 1, 11), "MM/dd/yyyy");
|
|
352
|
+
console.log("默认 formatDate 值:", ret1);
|
|
353
|
+
console.log("字符串 formatDate 值:", ret2);
|
|
354
|
+
console.log("数字 formatDate 值:", ret3);
|
|
355
|
+
console.log("Date formatDate 值:", ret4);
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
输出:
|
|
359
|
+
|
|
360
|
+
```text
|
|
361
|
+
默认 formatDate 值: 2023-01-11
|
|
362
|
+
字符串 formatDate 值: 2022-01-11 02:12:26 PM
|
|
363
|
+
数字 formatDate 值: 2022-01-11 02:07:15 PM
|
|
364
|
+
Date formatDate 值: 02/11/2014
|
|
110
365
|
```
|
|
111
366
|
|
|
112
|
-
|
|
367
|
+
#### isValidDate
|
|
368
|
+
|
|
369
|
+
检查未知值是否表示有效日期。函数接受 `Date` 实例、有限的毫秒时间戳、受支持的本地日期字符串,以及带有 `Z` 或数字时区偏移的 ISO 8601 字符串。
|
|
370
|
+
|
|
371
|
+
字符串格式包括 `YYYY-MM-DD`、`YYYY-MM-DD HH:mm[:ss]` 和 `YYYY-MM-DDTHH:mm[:ss]`。使用 `T` 分隔的日期时间还可以包含 `Z` 或 `+HH:mm`、`-HH:mm` 时区偏移。带时区的字符串可以包含 1~3 位毫秒数字。
|
|
372
|
+
|
|
373
|
+
函数会把结构化字符串解析为数字组件,并执行严格校验。因此,`"2020-02-30"` 等无效日历日期不会被转换为其他日期。
|
|
374
|
+
|
|
375
|
+
用法:
|
|
113
376
|
|
|
114
377
|
```javascript
|
|
115
|
-
|
|
378
|
+
const ret1 = isValidDate(1577877720000);
|
|
379
|
+
const ret2 = isValidDate("2020-01-01 11:22");
|
|
380
|
+
const ret3 = isValidDate("2020-02-30");
|
|
381
|
+
const ret4 = isValidDate(new Date("invalid"));
|
|
382
|
+
console.log(ret1, ret2, ret3, ret4);
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
输出:
|
|
116
386
|
|
|
117
|
-
|
|
118
|
-
|
|
387
|
+
```text
|
|
388
|
+
true true false false
|
|
119
389
|
```
|
|
120
390
|
|
|
121
|
-
|
|
391
|
+
#### generateCalendarVersion
|
|
392
|
+
|
|
393
|
+
按照本地时间生成日历版本字符串。其概念格式为 `yyyy.MMdd.HHmmss`。函数会删除每个数字段的前导零。处理后的结果兼容语义化版本 (SemVer)。
|
|
122
394
|
|
|
123
|
-
|
|
395
|
+
在系统时钟正常前进时,版本会随日期和时间递增。该函数有意使用本地时间。因此,手动回拨时钟或夏令时回退可能生成更小的版本。
|
|
396
|
+
|
|
397
|
+
用法:
|
|
124
398
|
|
|
125
399
|
```javascript
|
|
126
|
-
|
|
400
|
+
const version = generateCalendarVersion(
|
|
401
|
+
new Date(2026, 6, 11, 7, 40, 35)
|
|
402
|
+
);
|
|
403
|
+
console.log(version);
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
输出:
|
|
407
|
+
|
|
408
|
+
```text
|
|
409
|
+
2026.711.74035
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
#### getDateDifference
|
|
413
|
+
|
|
414
|
+
计算两个日期或时间戳之间的差值。默认返回完整秒数。`type: "d"` 返回完整天数,`type: "text"` 返回由天、小时、分钟和秒组成的英文文本。文本会省略值为 `0` 的单位。总时长为零时,函数返回 `"0 seconds"`。
|
|
415
|
+
|
|
416
|
+
`YYYY-MM-DD HH:mm:ss` 格式的字符串按本地时间解析。其他日期字符串使用运行环境原生的 `Date` 解析器。需要跨环境稳定解析时,请使用时间戳,或使用包含明确时区的 ISO 8601 字符串。结束时间早于开始时间,或任一日期无效时,函数返回空字符串。
|
|
417
|
+
|
|
418
|
+
用法:
|
|
419
|
+
|
|
420
|
+
```javascript
|
|
421
|
+
const days = getDateDifference(0, 90061000, { type: "d" });
|
|
422
|
+
const text = getDateDifference(0, 90061000, { type: "text" });
|
|
423
|
+
const compactText = getDateDifference(0, 90060000, { type: "text" });
|
|
424
|
+
const dateStringDays = getDateDifference(
|
|
425
|
+
"2020-03-28 00:09:27",
|
|
426
|
+
"2023-04-18 10:54:00",
|
|
427
|
+
{ type: "d" }
|
|
428
|
+
);
|
|
429
|
+
console.log(days);
|
|
430
|
+
console.log(text);
|
|
431
|
+
console.log(compactText);
|
|
432
|
+
console.log(dateStringDays);
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
输出:
|
|
436
|
+
|
|
437
|
+
```text
|
|
438
|
+
1
|
|
439
|
+
1 day 1 hour 1 minute 1 second
|
|
440
|
+
1 day 1 hour 1 minute
|
|
441
|
+
1116
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
`getFriendlyInterval` 是 `getDateDifference` 的兼容别名。新代码建议使用 `getDateDifference`。
|
|
445
|
+
|
|
446
|
+
#### formatDurationFromMs
|
|
447
|
+
|
|
448
|
+
将毫秒时长转换为适用的最大单位,包括秒、分钟、小时和天。结果最多保留 1 位小数。负数和非有限值返回 `"0 seconds"`。
|
|
449
|
+
|
|
450
|
+
用法:
|
|
451
|
+
|
|
452
|
+
```javascript
|
|
453
|
+
const ret1 = formatDurationFromMs(500);
|
|
454
|
+
const ret2 = formatDurationFromMs(90000);
|
|
455
|
+
const ret3 = formatDurationFromMs(3600000);
|
|
456
|
+
const ret4 = formatDurationFromMs(129600000);
|
|
457
|
+
console.log(ret1);
|
|
458
|
+
console.log(ret2);
|
|
459
|
+
console.log(ret3);
|
|
460
|
+
console.log(ret4);
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
输出:
|
|
464
|
+
|
|
465
|
+
```text
|
|
466
|
+
0.5 seconds
|
|
467
|
+
1.5 minutes
|
|
468
|
+
1 hour
|
|
469
|
+
1.5 days
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
#### deepCopy
|
|
473
|
+
|
|
474
|
+
深度复制或克隆对象。
|
|
475
|
+
|
|
476
|
+
用法:
|
|
477
|
+
|
|
478
|
+
```javascript
|
|
479
|
+
const ret1 = deepCopy(["a", "b", "c"]);
|
|
480
|
+
const ret2 = deepCopy("abc");
|
|
481
|
+
console.log(ret1);
|
|
482
|
+
console.log(ret2);
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
输出:
|
|
486
|
+
|
|
487
|
+
```text
|
|
488
|
+
["a", "b", "c"]
|
|
489
|
+
abc
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
#### deepFreeze
|
|
493
|
+
|
|
494
|
+
递归冻结对象及其可枚举嵌套值。原始值和已经冻结的对象会原样返回。函数支持包含循环引用的对象。
|
|
495
|
+
|
|
496
|
+
用法:
|
|
497
|
+
|
|
498
|
+
```javascript
|
|
499
|
+
const config = deepFreeze({
|
|
500
|
+
api: {
|
|
501
|
+
timeout: 5000,
|
|
502
|
+
},
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
console.log(Object.isFrozen(config));
|
|
506
|
+
console.log(Object.isFrozen(config.api));
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
输出:
|
|
510
|
+
|
|
511
|
+
```text
|
|
512
|
+
true
|
|
513
|
+
true
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
#### debounce
|
|
517
|
+
|
|
518
|
+
创建防抖函数。
|
|
519
|
+
|
|
520
|
+
用法:
|
|
521
|
+
|
|
522
|
+
```javascript
|
|
523
|
+
const foo = debounce(() => {
|
|
524
|
+
console.log("防抖函数会在 1,000 毫秒内仅执行一次,等待期间的其他调用不会生效。");
|
|
525
|
+
}, 1000, true);
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
#### throttle
|
|
529
|
+
|
|
530
|
+
创建节流函数。
|
|
531
|
+
|
|
532
|
+
用法:
|
|
533
|
+
|
|
534
|
+
```javascript
|
|
535
|
+
const foo = throttle(() => {
|
|
536
|
+
console.log("在每个 1,000 毫秒等待周期内,该函数最多执行一次。");
|
|
537
|
+
}, 1000, { leading: true });
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
参考资料: [Lodash](https://lodash.com/docs/4.17.15#throttle)
|
|
541
|
+
|
|
542
|
+
#### convertCamelToKebab
|
|
543
|
+
|
|
544
|
+
将驼峰命名转换为短横线命名。
|
|
545
|
+
|
|
546
|
+
用法:
|
|
547
|
+
|
|
548
|
+
```javascript
|
|
549
|
+
const ret1 = convertCamelToKebab("ABC");
|
|
550
|
+
const ret2 = convertCamelToKebab("aBC");
|
|
551
|
+
console.log(ret1);
|
|
552
|
+
console.log(ret2);
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
输出:
|
|
556
|
+
|
|
557
|
+
```text
|
|
558
|
+
a-b-c
|
|
559
|
+
a-b-c
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
#### convertCamelToUnder
|
|
563
|
+
|
|
564
|
+
将驼峰命名转换为下划线命名。
|
|
565
|
+
|
|
566
|
+
用法:
|
|
567
|
+
|
|
568
|
+
```javascript
|
|
569
|
+
const ret1 = convertCamelToUnder("ABC");
|
|
570
|
+
const ret2 = convertCamelToUnder("aBC");
|
|
571
|
+
console.log(ret1);
|
|
572
|
+
console.log(ret2);
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
输出:
|
|
576
|
+
|
|
577
|
+
```text
|
|
578
|
+
a_b_c
|
|
579
|
+
a_b_c
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
### URL
|
|
127
583
|
|
|
584
|
+
#### getQueryParam
|
|
585
|
+
|
|
586
|
+
从当前 Web URL 的查询字符串 (`location.search`) 中获取参数值。
|
|
587
|
+
|
|
588
|
+
用法:
|
|
589
|
+
|
|
590
|
+
```javascript
|
|
591
|
+
// http://example.com/?t1=1&t2=2&t3=3&t4=4#2333
|
|
592
|
+
// ?t1=1&t2=2&t3=3&t4=4
|
|
593
|
+
const p1 = getQueryParam("t3");
|
|
594
|
+
const p2 = getQueryParam("t4");
|
|
595
|
+
console.log(p1, p2);
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
输出:
|
|
599
|
+
|
|
600
|
+
```text
|
|
601
|
+
3 4
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
#### getUrlParam
|
|
605
|
+
|
|
606
|
+
从输入 URL 中获取指定查询参数的值。
|
|
607
|
+
|
|
608
|
+
用法:
|
|
609
|
+
|
|
610
|
+
```javascript
|
|
611
|
+
const p1 = getUrlParam("https://example.com/?t1=1&t2=2&t3=3&t4=4", "t3");
|
|
612
|
+
const p2 = getUrlParam("https://example.com/?t1=1&t2=2&t3=3&t4=4", "t4");
|
|
613
|
+
console.log(p1, p2);
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
输出:
|
|
617
|
+
|
|
618
|
+
```text
|
|
619
|
+
3 4
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
#### getHashQueryParam
|
|
623
|
+
|
|
624
|
+
从当前 Web URL 的哈希字符串 (`location.hash`) 中获取参数值。
|
|
625
|
+
|
|
626
|
+
用法:
|
|
627
|
+
|
|
628
|
+
```javascript
|
|
629
|
+
// http://example.com/?#2333?t1=1&t2=2&t3=3&t4=4
|
|
630
|
+
// #2333?t1=1&t2=2&t3=3&t4=4
|
|
631
|
+
const p1 = getHashQueryParam("t3");
|
|
632
|
+
const p2 = getHashQueryParam("t4");
|
|
633
|
+
console.log(p1, p2);
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
输出:
|
|
637
|
+
|
|
638
|
+
```text
|
|
639
|
+
3 4
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
#### getDomain
|
|
643
|
+
|
|
644
|
+
获取 URL 的域名,也可以组合返回其他部分。
|
|
645
|
+
|
|
646
|
+
用法:
|
|
647
|
+
|
|
648
|
+
```javascript
|
|
649
|
+
const ret1 = getDomain("http://example.com/?t1=1&t2=2&t3=3&t4=4");
|
|
650
|
+
const ret2 = getDomain("http://example.com/test/thanks?t1=1&t2=2&t3=3&t4=4", ["hostname", "pathname"]);
|
|
651
|
+
const ret3 = getDomain("http://example.com:7890/test/thanks", ["hostname"]);
|
|
652
|
+
const ret4 = getDomain("http://example.com:7890/test/thanks", ["host"]); // 包含端口
|
|
653
|
+
const ret5 = getDomain("http://example.com:7890/test/thanks", ["origin"]);
|
|
654
|
+
const ret6 = getDomain("http://example.com:7890/test/thanks?id=1", ["origin", "pathname", "search"]);
|
|
655
|
+
console.log(ret1);
|
|
656
|
+
console.log(ret2);
|
|
657
|
+
console.log(ret3);
|
|
658
|
+
console.log(ret4);
|
|
659
|
+
console.log(ret5);
|
|
660
|
+
console.log(ret6);
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
输出:
|
|
664
|
+
|
|
665
|
+
```text
|
|
666
|
+
example.com
|
|
667
|
+
example.com/test/thanks
|
|
668
|
+
example.com
|
|
669
|
+
example.com:7890
|
|
670
|
+
http://example.com:7890
|
|
671
|
+
http://example.com:7890/test/thanks?id=1
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
#### updateQueryParam
|
|
675
|
+
|
|
676
|
+
更新输入 URL 中的查询参数值。
|
|
677
|
+
|
|
678
|
+
用法:
|
|
679
|
+
|
|
680
|
+
```javascript
|
|
681
|
+
const ret1 = updateQueryParam("http://example.com/?t1=1&t2=2&t3=3&t4=4", "t3", "three");
|
|
682
|
+
const ret2 = updateQueryParam("http://example.com/?t1=1&t2=2&t3=3&t4=4", "t4", "four");
|
|
683
|
+
console.log(ret1);
|
|
684
|
+
console.log(ret2);
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
输出:
|
|
688
|
+
|
|
689
|
+
```text
|
|
690
|
+
http://example.com/?t1=1&t2=2&t3=three&t4=4
|
|
691
|
+
http://example.com/?t1=1&t2=2&t3=3&t4=four
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
#### isValidUrl
|
|
695
|
+
|
|
696
|
+
检查给定字符串是否为有效 URL,包括使用其他协议的 URL。
|
|
697
|
+
|
|
698
|
+
用法:
|
|
699
|
+
|
|
700
|
+
```javascript
|
|
701
|
+
const ret1 = isValidUrl("https://www.example.com");
|
|
702
|
+
const ret2 = isValidUrl("http://example.com/path/exx/ss");
|
|
703
|
+
const ret3 = isValidUrl("https://www.example.com/?q=hello&age=24#world");
|
|
704
|
+
const ret4 = isValidUrl("http://www.example.com/#world?id=9");
|
|
705
|
+
const ret5 = isValidUrl("ftp://example.com");
|
|
706
|
+
console.log(ret1, ret2, ret3, ret4, ret5);
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
输出:
|
|
710
|
+
|
|
711
|
+
```text
|
|
712
|
+
true true true true true
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
如果只需检查 HTTP 或 HTTPS URL,建议使用 `isValidHttpUrl`。`isValidUrl` 会匹配所有协议 URL,包括 FTP 和其他非 HTTP 协议。
|
|
716
|
+
|
|
717
|
+
#### isValidHttpUrl
|
|
718
|
+
|
|
719
|
+
检查给定字符串是否为有效的 HTTP 或 HTTPS URL。
|
|
720
|
+
|
|
721
|
+
用法:
|
|
722
|
+
|
|
723
|
+
```javascript
|
|
724
|
+
const ret1 = isValidHttpUrl("https://www.example.com");
|
|
725
|
+
const ret2 = isValidHttpUrl("http://example.com/path/exx/ss");
|
|
726
|
+
const ret3 = isValidHttpUrl("https://www.example.com/?q=hello&age=24#world");
|
|
727
|
+
const ret4 = isValidHttpUrl("http://www.example.com/#world?id=9");
|
|
728
|
+
const ret5 = isValidHttpUrl("ftp://example.com");
|
|
729
|
+
console.log(ret1, ret2, ret3, ret4, ret5);
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
输出:
|
|
733
|
+
|
|
734
|
+
```text
|
|
735
|
+
true true true true false
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
### 存储
|
|
739
|
+
|
|
740
|
+
#### Cookie 工具
|
|
741
|
+
|
|
742
|
+
操作 Cookie。
|
|
743
|
+
|
|
744
|
+
用法:
|
|
745
|
+
|
|
746
|
+
```javascript
|
|
747
|
+
setCookie("test", "123", 30, "example.com"); // 键、值、有效天数、域名
|
|
748
|
+
const ret = getCookie("test");
|
|
749
|
+
console.log(ret);
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
输出:
|
|
753
|
+
|
|
754
|
+
```text
|
|
755
|
+
123
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
#### Storage 工具
|
|
759
|
+
|
|
760
|
+
操作 Web Storage。函数适用于 JSON 数据,并会自动转换格式。
|
|
761
|
+
|
|
762
|
+
用法:
|
|
763
|
+
|
|
764
|
+
```javascript
|
|
765
|
+
setSessionStorage("test", "123");
|
|
766
|
+
const ret1 = getSessionStorage("test");
|
|
767
|
+
setLocalStorage("test", "123");
|
|
768
|
+
const ret2 = getLocalStorage("test");
|
|
769
|
+
console.log(ret1, ret2);
|
|
770
|
+
|
|
771
|
+
// 也可以按项目封装键名
|
|
772
|
+
const projectName = "mazey";
|
|
773
|
+
function mSetLocalStorage (key, value) {
|
|
774
|
+
return setLocalStorage(`${projectName}_${key}`, value);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
function mGetLocalStorage (key) {
|
|
778
|
+
return getLocalStorage(`${projectName}_${key}`);
|
|
779
|
+
}
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
输出:
|
|
783
|
+
|
|
784
|
+
```text
|
|
785
|
+
123 123
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
### DOM
|
|
789
|
+
|
|
790
|
+
#### Class 工具
|
|
791
|
+
|
|
792
|
+
操作元素的 `class`。
|
|
793
|
+
|
|
794
|
+
用法:
|
|
795
|
+
|
|
796
|
+
```javascript
|
|
128
797
|
const dom = document.querySelector("#box");
|
|
129
798
|
|
|
130
799
|
// 判断 class
|
|
131
800
|
hasClass(dom, "test");
|
|
132
|
-
//
|
|
801
|
+
// 添加 class
|
|
133
802
|
addClass(dom, "test");
|
|
134
803
|
// 删除 class
|
|
135
804
|
removeClass(dom, "test");
|
|
136
805
|
```
|
|
137
806
|
|
|
138
|
-
|
|
807
|
+
#### addStyle
|
|
808
|
+
|
|
809
|
+
在 `<head>` 中添加 `<style>` 元素。
|
|
810
|
+
|
|
811
|
+
用法:
|
|
812
|
+
|
|
813
|
+
示例 1: 添加带有 `id` 的 `<style>`。重复调用会更新内容,不会添加新元素。
|
|
139
814
|
|
|
140
815
|
```javascript
|
|
141
|
-
import {
|
|
816
|
+
import { addStyle } from "mazey";
|
|
142
817
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
// body {
|
|
154
|
-
// background-color: #333;
|
|
155
|
-
// }
|
|
156
|
-
// </style>
|
|
157
|
-
|
|
158
|
-
// 添加无 id 的内联样式,重复添加会新增内联样式
|
|
159
|
-
addInlineStyle({
|
|
160
|
-
inlineStyle: `
|
|
161
|
-
body {
|
|
162
|
-
background-color: #444;
|
|
163
|
-
}
|
|
164
|
-
`,
|
|
165
|
-
});
|
|
166
|
-
// <style>
|
|
167
|
-
// body {
|
|
168
|
-
// background-color: #444;
|
|
169
|
-
// }
|
|
170
|
-
// </style>
|
|
818
|
+
addStyle(
|
|
819
|
+
"body { background-color: #333; }",
|
|
820
|
+
{ id: "test" }
|
|
821
|
+
);
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
输出:
|
|
825
|
+
|
|
826
|
+
```html
|
|
827
|
+
<style id="test">body { background-color: #333; }</style>
|
|
171
828
|
```
|
|
172
829
|
|
|
173
|
-
|
|
830
|
+
示例 2: 添加不带 `id` 的 `<style>`。重复调用会添加新元素。
|
|
174
831
|
|
|
175
832
|
```javascript
|
|
176
|
-
import {
|
|
833
|
+
import { addStyle } from "mazey";
|
|
177
834
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
containerClassName: "i-am-container",
|
|
181
|
-
imgBoxClassName: "i-am-img-father-i-can-transform",
|
|
182
|
-
imgClassName: "i-am-img",
|
|
183
|
-
});
|
|
835
|
+
addStyle("body { background-color: #444; }");
|
|
836
|
+
```
|
|
184
837
|
|
|
185
|
-
|
|
186
|
-
customScrollBarForTransformEle({
|
|
187
|
-
containerClassName: "i-am-container",
|
|
188
|
-
imgBoxDom: document.querySelector(".i-am-img-father-i-can-transform"),
|
|
189
|
-
imgDom: document.querySelector(".i-am-img-father-i-can-transform"),
|
|
190
|
-
});
|
|
838
|
+
输出:
|
|
191
839
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
containerClassName: "i-am-container",
|
|
195
|
-
action: "hide",
|
|
196
|
-
});
|
|
840
|
+
```html
|
|
841
|
+
<style>body { background-color: #444; }</style>
|
|
197
842
|
```
|
|
198
843
|
|
|
199
|
-
|
|
844
|
+
示例 3: 组合使用 `genStyleString` 和 `addStyle`,一次添加多条样式。
|
|
200
845
|
|
|
201
846
|
```javascript
|
|
202
|
-
import {
|
|
847
|
+
import { genStyleString, addStyle } from "mazey";
|
|
848
|
+
|
|
849
|
+
const xStyle = genStyleString(
|
|
850
|
+
".footer>.x-wish>a:first-child" +
|
|
851
|
+
",div.wish-flex>a[href^='https://github.com/chengchuu']" +
|
|
852
|
+
",.m-hide",
|
|
853
|
+
[ "display: none" ]
|
|
854
|
+
);
|
|
855
|
+
const yStyle = genStyleString(
|
|
856
|
+
".footer>.y-wish:before",
|
|
857
|
+
[
|
|
858
|
+
`content: 'Copyright (c) chengchuu'`,
|
|
859
|
+
"color: inherit",
|
|
860
|
+
"padding-inline-start: var(--y-wish-1_5)",
|
|
861
|
+
"padding-inline-end: var(--y-wish-1_5)",
|
|
862
|
+
"padding-top: var(--y-wish-1)",
|
|
863
|
+
"padding-bottom: var(--y-wish-1)",
|
|
864
|
+
]
|
|
865
|
+
);
|
|
866
|
+
addStyle(xStyle + yStyle, { id: "z-style" });
|
|
867
|
+
```
|
|
203
868
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
869
|
+
输出:
|
|
870
|
+
|
|
871
|
+
```html
|
|
872
|
+
<style id="z-style">.footer>.x-wish>a:first-child,div.wish-flex>a[href^='https://github.com/chengchuu'],.m-hide{display: none;}.footer>.y-wish:before{content: 'Copyright (c) chengchuu';color: inherit;padding-inline-start: var(--y-wish-1_5);padding-inline-end: var(--y-wish-1_5);padding-top: var(--y-wish-1);padding-bottom: var(--y-wish-1);}</style>
|
|
207
873
|
```
|
|
208
874
|
|
|
209
|
-
|
|
875
|
+
#### genStyleString
|
|
210
876
|
|
|
211
|
-
|
|
877
|
+
根据参数生成样式字符串。第一个参数是查询选择器,第二个参数是样式数组。
|
|
212
878
|
|
|
213
|
-
|
|
214
|
-
import { getPerformance } from "mazey";
|
|
879
|
+
用法:
|
|
215
880
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
})
|
|
222
|
-
.catch(console.error);
|
|
881
|
+
```javascript
|
|
882
|
+
const ret1 = genStyleString(".a", [ "color:red" ]);
|
|
883
|
+
const ret2 = genStyleString("#b", [ "color:red", "font-size:12px" ]);
|
|
884
|
+
console.log(ret1);
|
|
885
|
+
console.log(ret2);
|
|
223
886
|
```
|
|
224
887
|
|
|
225
|
-
|
|
226
|
-
| --- | --- | --- |
|
|
227
|
-
| * DNS 查询时间 | dns_time | domainLookupEnd - domainLookupStart |
|
|
228
|
-
| * 服务器连接时间 | tcp_time | connectEnd - connectStart |
|
|
229
|
-
| * 服务器响应时间 | response_time | responseStart - requestStart |
|
|
230
|
-
| * ⽩屏时间 | white_time | responseStart - navigationStart |
|
|
231
|
-
| * DomReady 总时间 | domready_time | domContentLoadedEventStart - navigationStart |
|
|
232
|
-
| * 页面加载时间 | onload_time | loadEventStart - navigationStart |
|
|
233
|
-
| * EventEnd 总时间 | render_time | loadEventEnd -navigationStart |
|
|
234
|
-
| 上个⽂档卸载时间 | unload_time | unloadEventEnd - unloadEventStart |
|
|
235
|
-
| 重定向时间 | redirect_time | redirectEnd - redirectStart |
|
|
236
|
-
| 客户端⽩屏时间 | custom_white_time | renderTiming - navigationStart |
|
|
237
|
-
| SSL连接时间 | ssl_time | connectEnd - secureConnectionStart |
|
|
238
|
-
| ⽹⻚下载时间 | download_time | responseEnd - responseStart |
|
|
239
|
-
| FCP | first_contentful_paint_time | firstPaintTime |
|
|
888
|
+
输出:
|
|
240
889
|
|
|
241
|
-
|
|
890
|
+
```text
|
|
891
|
+
.a{color:red;}
|
|
892
|
+
#b{color:red;font-size:12px;}
|
|
893
|
+
```
|
|
242
894
|
|
|
243
|
-
|
|
895
|
+
下面的示例组合使用 `genStyleString` 和 `addStyle`,一次添加多条样式。
|
|
244
896
|
|
|
245
897
|
```javascript
|
|
246
|
-
import {
|
|
898
|
+
import { genStyleString, addStyle } from "mazey";
|
|
899
|
+
|
|
900
|
+
const xStyle = genStyleString(
|
|
901
|
+
".footer>.x-wish>a:first-child" +
|
|
902
|
+
",div.wish-flex>a[href^='https://github.com/chengchuu']" +
|
|
903
|
+
",.m-hide",
|
|
904
|
+
[ "display: none" ]
|
|
905
|
+
);
|
|
906
|
+
const yStyle = genStyleString(
|
|
907
|
+
".footer>.y-wish:before",
|
|
908
|
+
[
|
|
909
|
+
`content: 'Copyright (c) chengchuu'`,
|
|
910
|
+
"color: inherit",
|
|
911
|
+
"padding-inline-start: var(--y-wish-1_5)",
|
|
912
|
+
"padding-inline-end: var(--y-wish-1_5)",
|
|
913
|
+
"padding-top: var(--y-wish-1)",
|
|
914
|
+
"padding-bottom: var(--y-wish-1)",
|
|
915
|
+
]
|
|
916
|
+
);
|
|
917
|
+
addStyle(xStyle + yStyle, { id: "z-style" });
|
|
918
|
+
```
|
|
247
919
|
|
|
248
|
-
|
|
920
|
+
输出:
|
|
921
|
+
|
|
922
|
+
```html
|
|
923
|
+
<style id="z-style">.footer>.x-wish>a:first-child,div.wish-flex>a[href^='https://github.com/chengchuu'],.m-hide{display: none;}.footer>.y-wish:before{content: 'Copyright (c) chengchuu';color: inherit;padding-inline-start: var(--y-wish-1_5);padding-inline-end: var(--y-wish-1_5);padding-top: var(--y-wish-1);padding-bottom: var(--y-wish-1);}</style>
|
|
249
924
|
```
|
|
250
925
|
|
|
251
|
-
|
|
926
|
+
#### newLine
|
|
927
|
+
|
|
928
|
+
把文本中的换行符转换为 HTML 换行元素。
|
|
929
|
+
|
|
930
|
+
用法:
|
|
252
931
|
|
|
253
932
|
```javascript
|
|
254
|
-
|
|
933
|
+
const ret1 = newLine("a\nb\nc");
|
|
934
|
+
const ret2 = newLine("a\n\nbc");
|
|
935
|
+
console.log(ret1);
|
|
936
|
+
console.log(ret2);
|
|
937
|
+
```
|
|
938
|
+
|
|
939
|
+
输出:
|
|
255
940
|
|
|
256
|
-
|
|
941
|
+
```text
|
|
942
|
+
a<br />b<br />c
|
|
943
|
+
a<br /><br />bc
|
|
257
944
|
```
|
|
258
945
|
|
|
259
|
-
|
|
946
|
+
### 计算与公式
|
|
947
|
+
|
|
948
|
+
#### inRate
|
|
949
|
+
|
|
950
|
+
按照指定概率返回命中结果。有效概率范围为 1%~100%。
|
|
951
|
+
|
|
952
|
+
用法:
|
|
260
953
|
|
|
261
954
|
```javascript
|
|
262
|
-
|
|
955
|
+
const ret = inRate(0.5); // 0.01~1,返回 true 或 false
|
|
956
|
+
console.log(ret);
|
|
957
|
+
```
|
|
958
|
+
|
|
959
|
+
输出:
|
|
960
|
+
|
|
961
|
+
```text
|
|
962
|
+
true
|
|
963
|
+
```
|
|
263
964
|
|
|
264
|
-
|
|
965
|
+
下面的示例测试概率精度。
|
|
265
966
|
|
|
266
|
-
|
|
967
|
+
```javascript
|
|
968
|
+
// 测试
|
|
267
969
|
let trueCount = 0;
|
|
268
970
|
let falseCount = 0;
|
|
269
971
|
new Array(1000000).fill(0).forEach(() => {
|
|
@@ -276,88 +978,221 @@ new Array(1000000).fill(0).forEach(() => {
|
|
|
276
978
|
console.log(trueCount, falseCount); // 499994 500006
|
|
277
979
|
```
|
|
278
980
|
|
|
279
|
-
|
|
981
|
+
#### longestComSubstring
|
|
982
|
+
|
|
983
|
+
计算两个字符串的最长公共子串长度。
|
|
984
|
+
|
|
985
|
+
用法:
|
|
986
|
+
|
|
987
|
+
```javascript
|
|
988
|
+
const ret = longestComSubstring("fish", "finish");
|
|
989
|
+
console.log(ret);
|
|
990
|
+
```
|
|
991
|
+
|
|
992
|
+
输出:
|
|
993
|
+
|
|
994
|
+
```text
|
|
995
|
+
3
|
|
996
|
+
```
|
|
997
|
+
|
|
998
|
+
#### longestComSubsequence
|
|
999
|
+
|
|
1000
|
+
计算两个字符串的最长公共子序列长度。
|
|
1001
|
+
|
|
1002
|
+
用法:
|
|
280
1003
|
|
|
281
1004
|
```javascript
|
|
282
|
-
|
|
1005
|
+
const ret = longestComSubsequence("fish", "finish");
|
|
1006
|
+
console.log(ret);
|
|
1007
|
+
```
|
|
1008
|
+
|
|
1009
|
+
输出:
|
|
283
1010
|
|
|
284
|
-
|
|
285
|
-
|
|
1011
|
+
```text
|
|
1012
|
+
4
|
|
286
1013
|
```
|
|
287
1014
|
|
|
288
|
-
###
|
|
1015
|
+
### 浏览器信息
|
|
1016
|
+
|
|
1017
|
+
#### getBrowserInfo
|
|
1018
|
+
|
|
1019
|
+
获取浏览器信息。
|
|
289
1020
|
|
|
290
|
-
|
|
1021
|
+
用法:
|
|
291
1022
|
|
|
292
1023
|
```javascript
|
|
293
|
-
|
|
1024
|
+
const ret = getBrowserInfo();
|
|
1025
|
+
console.log(ret);
|
|
1026
|
+
```
|
|
294
1027
|
|
|
295
|
-
|
|
1028
|
+
输出:
|
|
1029
|
+
|
|
1030
|
+
```text
|
|
1031
|
+
{"engine":"webkit","engineVs":"537.36","platform":"desktop","supporter":"chrome","supporterVs":"85.0.4183.121","system":"windows","systemVs":"10"}
|
|
296
1032
|
```
|
|
297
1033
|
|
|
298
|
-
|
|
1034
|
+
返回字段:
|
|
1035
|
+
|
|
1036
|
+
| 字段 | 说明 | 类型 | 可选值 |
|
|
1037
|
+
| :--- | :--- | :--- | :--- |
|
|
1038
|
+
| **system** | 操作系统 | string | android、ios、windows、macos、linux |
|
|
1039
|
+
| systemVs | 操作系统版本 | string | Windows: 2000、xp、2003、vista、7、8、8.1、10;macOS: ⋯⋯ |
|
|
1040
|
+
| platform | 平台 | string | desktop、mobile |
|
|
1041
|
+
| engine | 浏览器引擎 | string | webkit、gecko、presto、trident |
|
|
1042
|
+
| engineVs | 浏览器引擎版本 | string | - |
|
|
1043
|
+
| supporter | 浏览器 | string | edge、opera、chrome、safari、firefox、iexplore |
|
|
1044
|
+
| supporterVs | 浏览器版本 | string | - |
|
|
1045
|
+
| shell | 浏览器外壳 | string | 可选: wechat、qq_browser、qq_app、uc、360、2345、sougou、liebao、maxthon、bilibili |
|
|
1046
|
+
| shellVs | 浏览器外壳版本 | string | 可选,例如 `20` |
|
|
1047
|
+
| appleType | Apple 设备类型 | string | 可选: ipad、iphone、ipod、iwatch |
|
|
299
1048
|
|
|
300
|
-
|
|
1049
|
+
下面的示例判断当前环境是否为移动版 QQ。
|
|
301
1050
|
|
|
302
1051
|
```javascript
|
|
303
|
-
|
|
1052
|
+
const { system, shell } = getBrowserInfo();
|
|
1053
|
+
const isMobileQQ = ["android", "ios"].includes(system) && ["qq_browser", "qq_app"].includes(shell);
|
|
1054
|
+
```
|
|
304
1055
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
1056
|
+
#### isSafePWAEnv
|
|
1057
|
+
|
|
1058
|
+
检查当前浏览器文档是否满足 PWA (渐进式 Web 应用) 的最低前提条件。这里只检查同步 JavaScript 能够识别的条件。函数会检查安全上下文和 Service Worker API 支持。文档还必须包含 Web App Manifest (Web 应用清单) 链接,而且 `href` 不能为空。
|
|
1059
|
+
|
|
1060
|
+
该检查不会验证或请求 Manifest。它也不会验证 Service Worker 是否注册成功。该函数无法判断应用是否已经安装,也不保证浏览器会提供安装提示。不同浏览器还可能执行额外的安装策略。
|
|
1061
|
+
|
|
1062
|
+
用法:
|
|
1063
|
+
|
|
1064
|
+
```javascript
|
|
1065
|
+
const ret = isSafePWAEnv();
|
|
1066
|
+
console.log(ret);
|
|
1067
|
+
```
|
|
1068
|
+
|
|
1069
|
+
输出:
|
|
1070
|
+
|
|
1071
|
+
```text
|
|
1072
|
+
true
|
|
308
1073
|
```
|
|
309
1074
|
|
|
310
|
-
|
|
1075
|
+
### Web 性能
|
|
1076
|
+
|
|
1077
|
+
#### getPerformance
|
|
1078
|
+
|
|
1079
|
+
获取页面加载时间 (`PerformanceNavigationTiming`)。
|
|
1080
|
+
|
|
1081
|
+
该函数使用 [`PerformanceNavigationTiming`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming) API 获取页面加载数据。与已弃用的 [`PerformanceTiming`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceTiming) API 相比,新 API 提供的数据更准确,也更详细。
|
|
1082
|
+
|
|
1083
|
+
用法:
|
|
311
1084
|
|
|
312
1085
|
```javascript
|
|
313
|
-
|
|
1086
|
+
// `camelCase: false` (默认值) 返回下划线格式 (`a_b`) 的数据
|
|
1087
|
+
// `camelCase: true` 返回驼峰格式 (`aB`) 的数据
|
|
1088
|
+
getPerformance()
|
|
1089
|
+
.then(res => {
|
|
1090
|
+
console.log(JSON.stringify(res));
|
|
1091
|
+
})
|
|
1092
|
+
.catch(console.error);
|
|
1093
|
+
```
|
|
1094
|
+
|
|
1095
|
+
输出:
|
|
314
1096
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
// 默认情况下 NaN、Infinity 不算有效数字
|
|
318
|
-
isNumber(Infinity); // false
|
|
319
|
-
isNumber(Infinity, { isUnFiniteAsNumber: true }); true
|
|
320
|
-
isNumber(NaN); // false
|
|
321
|
-
isNumber(NaN, { isNaNAsNumber: true, isUnFiniteAsNumber: true }); // true
|
|
1097
|
+
```text
|
|
1098
|
+
{"source":"PerformanceNavigationTiming","os":"others","os_version":"","device_type":"pc","network":"4g","screen_direction":"","unload_time":0,"redirect_time":0,"dns_time":0,"tcp_time":0,"ssl_time":0,"response_time":2,"download_time":2,"first_paint_time":288,"first_contentful_paint_time":288,"dom_ready_time":0,"onload_time":0,"white_time":0,"render_time":0,"decoded_body_size":718,"encoded_body_size":718}
|
|
322
1099
|
```
|
|
323
1100
|
|
|
1101
|
+
返回字段:
|
|
1102
|
+
|
|
1103
|
+
| 字段 | 说明 | 类型 | 计算方式 |
|
|
1104
|
+
| :--- | :--- | :--- | :--- |
|
|
1105
|
+
| dns_time | DNS 查询时间 | number | domainLookupEnd - domainLookupStart |
|
|
1106
|
+
| tcp_time | 连接协商时间 | number | connectEnd - connectStart |
|
|
1107
|
+
| response_time | 请求与响应时间 | number | responseStart - requestStart |
|
|
1108
|
+
| white_time | 白屏时间 | number | responseStart - navigationStart |
|
|
1109
|
+
| dom_ready_time | DOM 就绪时间 | number | domContentLoadedEventStart - navigationStart |
|
|
1110
|
+
| onload_time | 页面加载时间 | number | loadEventStart - navigationStart |
|
|
1111
|
+
| render_time | EventEnd 时间 | number | loadEventEnd - navigationStart |
|
|
1112
|
+
| unload_time | 页面卸载时间 | number | 可选: unloadEventEnd - unloadEventStart |
|
|
1113
|
+
| redirect_time | 重定向时间 | number | 可选: redirectEnd - redirectStart |
|
|
1114
|
+
| ssl_time | SSL 连接时间 | number | 可选: connectEnd - secureConnectionStart |
|
|
1115
|
+
| download_time | 下载时间 | number | 可选: responseEnd - responseStart |
|
|
1116
|
+
|
|
324
1117
|
### 调试
|
|
325
1118
|
|
|
326
|
-
|
|
1119
|
+
#### genCustomConsole
|
|
1120
|
+
|
|
1121
|
+
创建带有自定义前缀的控制台 (`console`) 输出对象。
|
|
1122
|
+
|
|
1123
|
+
用法:
|
|
327
1124
|
|
|
328
1125
|
```javascript
|
|
329
|
-
|
|
1126
|
+
const myConsole = genCustomConsole("MazeyLog:");
|
|
1127
|
+
myConsole.log("I am string.");
|
|
1128
|
+
myConsole.info("I am boolean.", true);
|
|
1129
|
+
myConsole.info("I am number.", 123, 456);
|
|
1130
|
+
myConsole.info("I am object.", { a: 123, b: 456});
|
|
1131
|
+
```
|
|
1132
|
+
|
|
1133
|
+
输出:
|
|
330
1134
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
1135
|
+
```text
|
|
1136
|
+
MazeyLog: I am string.
|
|
1137
|
+
MazeyLog: I am boolean. true
|
|
1138
|
+
MazeyLog: I am number. 123 456
|
|
1139
|
+
MazeyLog: I am object. {a: 123, b: 456}
|
|
336
1140
|
```
|
|
337
1141
|
|
|
338
|
-
|
|
1142
|
+
## 参与贡献
|
|
1143
|
+
|
|
1144
|
+
### 开发环境
|
|
339
1145
|
|
|
340
|
-
|
|
1146
|
+
| 依赖 | 版本 |
|
|
1147
|
+
| --- | --- |
|
|
1148
|
+
| Node.js | v22.21.1 |
|
|
1149
|
+
| TypeScript | v5.1.6 |
|
|
341
1150
|
|
|
342
|
-
|
|
1151
|
+
### 脚本
|
|
1152
|
+
|
|
1153
|
+
安装依赖:
|
|
1154
|
+
|
|
1155
|
+
```bash
|
|
1156
|
+
npm i
|
|
1157
|
+
```
|
|
1158
|
+
|
|
1159
|
+
启动开发环境:
|
|
343
1160
|
|
|
344
1161
|
```bash
|
|
345
1162
|
npm run dev
|
|
346
1163
|
```
|
|
347
1164
|
|
|
348
|
-
|
|
1165
|
+
构建:
|
|
349
1166
|
|
|
350
1167
|
```bash
|
|
351
1168
|
npm run build
|
|
352
1169
|
```
|
|
353
1170
|
|
|
354
|
-
|
|
1171
|
+
测试:
|
|
1172
|
+
|
|
1173
|
+
```bash
|
|
1174
|
+
npm run test
|
|
1175
|
+
```
|
|
1176
|
+
|
|
1177
|
+
生成文档:
|
|
355
1178
|
|
|
356
1179
|
```bash
|
|
357
1180
|
npm run docs
|
|
358
1181
|
```
|
|
359
1182
|
|
|
360
|
-
|
|
1183
|
+
### 返回值
|
|
1184
|
+
|
|
1185
|
+
| 值 | 说明 | 类型 |
|
|
1186
|
+
| :--- | :--- | :--- |
|
|
1187
|
+
| ok | 操作成功。 | string |
|
|
1188
|
+
| loaded | 资源已经加载。 | string |
|
|
1189
|
+
| failed | 发生错误。 | string |
|
|
1190
|
+
| defined | 值已定义。 | string |
|
|
1191
|
+
| undefined | 值未定义。 | string |
|
|
1192
|
+
| timeout | 操作超时。 | string |
|
|
1193
|
+
| true | 值为真。 | boolean |
|
|
1194
|
+
| false | 值为假。 | boolean |
|
|
1195
|
+
|
|
1196
|
+
## 许可证
|
|
361
1197
|
|
|
362
|
-
|
|
363
|
-
2. [@babel/plugin-transform-runtime](https://babeljs.io/docs/en/babel-plugin-transform-runtime)
|
|
1198
|
+
本软件按照 [MIT 许可证](https://github.com/chengchuu/mazey/blob/main/LICENSE) 发布。
|