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