@zcrkey/js-utils 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/util.js CHANGED
@@ -4,19 +4,21 @@ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" !=
4
4
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
5
5
  function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
6
6
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
7
- function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
8
7
  function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
9
8
  function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
10
- function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
11
9
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
12
10
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
13
11
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
12
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
13
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
14
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
14
15
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
15
16
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
16
17
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
17
18
  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
18
19
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
19
20
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
21
+ import { cloneDeep as _cloneDeep } from 'lodash';
20
22
  import Qs from 'qs';
21
23
  var CrUtil = /*#__PURE__*/function () {
22
24
  function CrUtil() {
@@ -125,6 +127,17 @@ var CrUtil = /*#__PURE__*/function () {
125
127
  return Object.prototype.toString.call(value) === '[object Boolean]';
126
128
  }
127
129
 
130
+ /**
131
+ * 判断是否为 Function
132
+ * @param value
133
+ * @returns boolean
134
+ */
135
+ }, {
136
+ key: "isFunction",
137
+ value: function isFunction(value) {
138
+ return typeof value === 'function';
139
+ }
140
+
128
141
  /**
129
142
  * 去掉字符串前后所有空格
130
143
  * @param str
@@ -157,9 +170,21 @@ var CrUtil = /*#__PURE__*/function () {
157
170
  return maxDimension + 1;
158
171
  }
159
172
 
173
+ /**
174
+ * 深拷贝
175
+ * @param value
176
+ * @returns
177
+ */
178
+ }, {
179
+ key: "cloneDeep",
180
+ value: function cloneDeep(value) {
181
+ return _cloneDeep(value);
182
+ }
183
+
160
184
  /**
161
185
  * 深拷贝
162
186
  * @param target
187
+ * @deprecated 即将移除,使用 {@link CrUtil.cloneDeep} 替代
163
188
  * @returns
164
189
  */
165
190
  }, {
@@ -194,6 +219,10 @@ var CrUtil = /*#__PURE__*/function () {
194
219
  * 列表数据转树型数据
195
220
  * @param listData
196
221
  * @param settings
222
+ * @param settings.idField 默认值 id
223
+ * @param settings.pidField 默认值 parentId
224
+ * @param settings.childrenField 默认值 children
225
+ * @deprecated 即将移除,使用 {@link CrObjUtil.listToTree} 替代
197
226
  * @returns
198
227
  */
199
228
  }, {
@@ -208,34 +237,102 @@ var CrUtil = /*#__PURE__*/function () {
208
237
  return item;
209
238
  }
210
239
  }, settings);
211
- if (options.isDeepCopy) {
240
+ var idField = options.idField,
241
+ pidField = options.pidField,
242
+ childrenField = options.childrenField,
243
+ isDeepCopy = options.isDeepCopy,
244
+ getData = options.getData;
245
+ if (isDeepCopy) {
212
246
  listData = CrUtil.deepCopy(listData);
213
247
  }
214
- var _listData = [];
215
- var itemMap = {};
216
- listData.forEach(function (item) {
217
- _listData.push(options.getData(item));
218
- itemMap[item[options.idField]] = item;
219
- });
220
- var treeData = _listData.filter(function (item) {
221
- // 获取子级数据
222
- var itemArray = _listData.filter(function (child) {
223
- return item[options.idField] == child[options.pidField];
248
+
249
+ // 构建索引
250
+ var pidMap = new Map();
251
+ var idMap = new Map();
252
+ var _iterator = _createForOfIteratorHelper(listData),
253
+ _step;
254
+ try {
255
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
256
+ var _item = _step.value;
257
+ var pid = _item[pidField];
258
+ var id = _item[idField];
259
+ if (!pidMap.has(pid)) {
260
+ pidMap.set(pid, []);
261
+ }
262
+ pidMap.get(pid).push(_item);
263
+ idMap.set(id, _item);
264
+ }
265
+
266
+ // 递归构建树 + 字段过滤
267
+ } catch (err) {
268
+ _iterator.e(err);
269
+ } finally {
270
+ _iterator.f();
271
+ }
272
+ var buildTree = function buildTree(pid) {
273
+ var children = pidMap.get(pid) || [];
274
+ return children.map(function (item) {
275
+ var rawChildren = buildTree(item[idField]);
276
+ var node = _objectSpread({}, getData(item));
277
+ if (rawChildren.length > 0) {
278
+ node[childrenField] = rawChildren;
279
+ }
280
+ return node;
224
281
  });
225
- if (itemArray != null && itemArray.length > 0) {
226
- // 如果存在子级,则给父级添加一个children属性,并赋值
227
- item[options.childrenField] = itemArray;
282
+ };
283
+
284
+ // 收集所有根节点 pid,去重
285
+ var rootPids = new Set();
286
+ var _iterator2 = _createForOfIteratorHelper(pidMap.keys()),
287
+ _step2;
288
+ try {
289
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
290
+ var _pid = _step2.value;
291
+ if (_pid === undefined || _pid === null || _pid === 0 || !idMap.has(_pid)) {
292
+ rootPids.add(_pid);
293
+ }
228
294
  }
229
- // 返回第一层
230
- return item[options.pidField] == 0 || item[options.pidField] == null || item[options.pidField] == undefined || !itemMap[item[options.pidField]];
231
- });
232
- return treeData;
295
+
296
+ // 构建最终树
297
+ } catch (err) {
298
+ _iterator2.e(err);
299
+ } finally {
300
+ _iterator2.f();
301
+ }
302
+ var tree = [];
303
+ var _iterator3 = _createForOfIteratorHelper(rootPids),
304
+ _step3;
305
+ try {
306
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
307
+ var _pid2 = _step3.value;
308
+ tree.push.apply(tree, _toConsumableArray(buildTree(_pid2)));
309
+ }
310
+
311
+ // 只构建根节点(pid 为 null / 0 / undefined / 不存在)
312
+ // const tree = buildTree(undefined)
313
+ // .concat(buildTree(null))
314
+ // .concat(buildTree(0))
315
+ // .concat(
316
+ // Array.from(pidMap.keys())
317
+ // .filter((pid) => !idMap.has(pid))
318
+ // .flatMap((pid) => buildTree(pid)),
319
+ // );
320
+ } catch (err) {
321
+ _iterator3.e(err);
322
+ } finally {
323
+ _iterator3.f();
324
+ }
325
+ return tree;
233
326
  }
234
327
 
235
328
  /**
236
329
  * 树型数据转列表数据
237
330
  * @param treeData
238
331
  * @param settings
332
+ * @param settings.idField 默认值 id
333
+ * @param settings.pidField 默认值 parentId
334
+ * @param settings.childrenField 默认值 children
335
+ * @deprecated 即将移除,使用 {@link CrObjUtil.treeToList} 替代
239
336
  * @returns
240
337
  */
241
338
  }, {
@@ -252,14 +349,14 @@ var CrUtil = /*#__PURE__*/function () {
252
349
  var listData = [];
253
350
  for (var i = 0; i < treeData.length; i++) {
254
351
  var node = treeData[i];
255
- var _item = _objectSpread({}, node);
256
- _item[options.pidField] = pid;
257
- delete _item[options.childrenField];
258
- listData.push(_item);
352
+ var _item2 = _objectSpread({}, node);
353
+ _item2[options.pidField] = pid;
354
+ delete _item2[options.childrenField];
355
+ listData.push(_item2);
259
356
  if (node[options.childrenField]) {
260
- var _listData2;
261
- var childrenList = this.treeDataToListData(node[options.childrenField], _item[options.idField], settings);
262
- (_listData2 = listData).push.apply(_listData2, _toConsumableArray(childrenList));
357
+ var _listData;
358
+ var childrenList = this.treeDataToListData(node[options.childrenField], _item2[options.idField], settings);
359
+ (_listData = listData).push.apply(_listData, _toConsumableArray(childrenList));
263
360
  }
264
361
  }
265
362
  if (options.isDeepCopy) {
@@ -273,6 +370,10 @@ var CrUtil = /*#__PURE__*/function () {
273
370
  * @param listData
274
371
  * @param value
275
372
  * @param settings
373
+ * @param settings.valueField 默认值 value
374
+ * @param settings.idField 默认值 id
375
+ * @param settings.pidField 默认值 parentId
376
+ * @deprecated 即将移除,使用 {@link CrObjUtil.getFlatParentDatas} 替代
276
377
  * @returns
277
378
  */
278
379
  }, {
@@ -326,12 +427,11 @@ var CrUtil = /*#__PURE__*/function () {
326
427
  isFilterNonNull: false
327
428
  }, settings);
328
429
  if (options.isFilterNonNull) {
329
- params = Object.fromEntries(Object.entries(params).filter(function (_ref) {
330
- var _ref2 = _slicedToArray(_ref, 2),
331
- k = _ref2[0],
332
- v = _ref2[1];
333
- return !(v === null || v === undefined || v === '');
334
- }));
430
+ Object.keys(params).forEach(function (key) {
431
+ if (params[key] === null || params[key] === undefined || params[key] === '') {
432
+ delete params[key];
433
+ }
434
+ });
335
435
  }
336
436
  return Qs.stringify(params);
337
437
  }
@@ -355,6 +455,72 @@ var CrUtil = /*#__PURE__*/function () {
355
455
  return obj;
356
456
  }
357
457
 
458
+ /**
459
+ * 获取 URL 参数
460
+ * @param {*} url
461
+ * @returns
462
+ * @example
463
+ * "https://example.com?foo=bar&baz=qux" => {"query":{"foo":"bar","baz":"qux"},"hash":{},"all":{"foo":"bar","baz":"qux"}}
464
+ * "https://example.com/page?foo=1#/?a=1&b=2" => {"query":{"foo":"1"},"hash":{"/":"","a":"1","b":"2"},"all":{"foo":"1","/":"","a":"1","b":"2"}},
465
+ */
466
+ }, {
467
+ key: "getQueryParams",
468
+ value: function getQueryParams(url) {
469
+ var query = {};
470
+ var hash = {};
471
+ var all = {};
472
+ var parse = function parse(queryString) {
473
+ if (!queryString) {
474
+ return {};
475
+ }
476
+ try {
477
+ return Qs.parse(queryString);
478
+ } catch (_unused) {
479
+ var result = {};
480
+ if (!queryString) return result;
481
+ queryString.split('&').forEach(function (pair) {
482
+ if (!pair) return;
483
+ var _pair$split = pair.split('='),
484
+ _pair$split2 = _slicedToArray(_pair$split, 2),
485
+ key = _pair$split2[0],
486
+ val = _pair$split2[1];
487
+ if (key) result[decodeURIComponent(key)] = decodeURIComponent(val || '');
488
+ });
489
+ return result;
490
+ }
491
+ };
492
+ try {
493
+ var _url$split = url.split('#'),
494
+ _url$split2 = _slicedToArray(_url$split, 2),
495
+ base = _url$split2[0],
496
+ hashPart = _url$split2[1];
497
+ var queryPart = base.split('?')[1];
498
+ Object.assign(query, parse(queryPart));
499
+ if (hashPart) {
500
+ var _iterator4 = _createForOfIteratorHelper(hashPart.split('?')),
501
+ _step4;
502
+ try {
503
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
504
+ var part = _step4.value;
505
+ Object.assign(hash, parse(part));
506
+ }
507
+ } catch (err) {
508
+ _iterator4.e(err);
509
+ } finally {
510
+ _iterator4.f();
511
+ }
512
+ }
513
+ Object.assign(all, query, hash);
514
+ } catch (error) {
515
+ console.error('getQueryParams:', error);
516
+ }
517
+ return {
518
+ query: query,
519
+ hash: hash,
520
+ all: all
521
+ };
522
+ }
523
+
358
524
  /**
359
525
  * 版本号比较
360
526
  * @param v1
@@ -504,6 +670,25 @@ var CrUtil = /*#__PURE__*/function () {
504
670
  compare('', data1, data2);
505
671
  return diffFieldSet;
506
672
  }
673
+
674
+ /**
675
+ * 格式化为千分位
676
+ * @param value
677
+ * @returns 12345.6789 => 12,345.6789
678
+ */
679
+ }, {
680
+ key: "fmtThousands",
681
+ value: function fmtThousands(value) {
682
+ if (value == undefined || value == null || isNaN(Number(value))) {
683
+ return String(value);
684
+ }
685
+ var _String$split = String(value).split('.'),
686
+ _String$split2 = _slicedToArray(_String$split, 2),
687
+ intPart = _String$split2[0],
688
+ decimalPart = _String$split2[1];
689
+ var formattedInt = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
690
+ return decimalPart ? "".concat(formattedInt, ".").concat(decimalPart) : formattedInt;
691
+ }
507
692
  }]);
508
693
  return CrUtil;
509
694
  }();
@@ -0,0 +1,34 @@
1
+ # CrEventCenter 事件发布订阅
2
+
3
+ 事件发布订阅
4
+
5
+ - 推荐仅在原生 javascript 中使用
6
+ - 不推荐中在三大框架中使用,而是使用各家框架的状态管理库(存在问题,闭包函数未能及时更新 useState 中的值)
7
+
8
+ 原生写法
9
+
10
+ ```
11
+ import { CrEventCenter } from '@zcrkey/js-utils';
12
+ import type { TSubscription } from '@zcrkey/js-utils';
13
+
14
+ // 订阅事件
15
+ const subscription: TSubscription = CrEventCenter.on('xxx_xxx', (params) => {
16
+ console.log('params',params)
17
+ });
18
+
19
+ // 发布事件
20
+ CrEventCenter.emit('xxx_xxx',{a:1,b:2})
21
+
22
+ // 移除订阅事件
23
+ subscription.remove()
24
+ // 或者
25
+ CrEventCenter.off(subscription);
26
+
27
+ // 查找订阅事件
28
+ const item = CrEventCenter.find('xxx_xxx')
29
+
30
+ // 清除所有订阅事件
31
+ CrEventCenter.clear()
32
+
33
+
34
+ ```
@@ -0,0 +1,5 @@
1
+ ---
2
+ order: -1
3
+ ---
4
+
5
+ # API 总览
@@ -0,0 +1,9 @@
1
+ # CrStorage 浏览器存储
2
+
3
+ 浏览器存储
4
+
5
+ - localStorage:大小(10mb)、访问(任何窗口)
6
+ - sessionStorage 大小(5mb)、访问(同一窗口)
7
+
8
+ <code src="./local.tsx"></code>
9
+ <code src="./session.tsx"></code>
@@ -0,0 +1,91 @@
1
+ /**
2
+ * title: localStorage
3
+ */
4
+
5
+ import { CrStorage } from '@zcrkey/js-utils';
6
+ import React, { useState } from 'react';
7
+
8
+ const LOGIN_USER = 'loginUser';
9
+
10
+ export default () => {
11
+ const [data, setData] = useState<any>();
12
+
13
+ const onSet = () => {
14
+ // CrStorage.setLocalItem(LOGIN_USER, null);
15
+ // CrStorage.setLocalItem(LOGIN_USER, -1);
16
+ // CrStorage.setLocalItem(LOGIN_USER, undefined);
17
+ // CrStorage.setLocalItem(LOGIN_USER, {});
18
+ // CrStorage.setLocalItem(LOGIN_USER, []);
19
+ CrStorage.setLocalItem(LOGIN_USER, {
20
+ name: 'zcr',
21
+ sex: '男',
22
+ age: 18,
23
+ });
24
+ };
25
+
26
+ const onGet = () => {
27
+ const data = CrStorage.getLocalItem(LOGIN_USER);
28
+ setData(data);
29
+ };
30
+
31
+ const onClear = () => {
32
+ CrStorage.removeLocalItem(LOGIN_USER);
33
+ setData('');
34
+ };
35
+
36
+ const onAllClear = () => {
37
+ CrStorage.clearLocal();
38
+ setData('');
39
+ };
40
+
41
+ return (
42
+ <>
43
+ <div className="flex flex-direction">
44
+ <div className="text-lg">CrUtil.setLocalItem</div>
45
+ <div>
46
+ <button
47
+ type="button"
48
+ className="cr-btn line-blue radius"
49
+ onClick={onSet}
50
+ >
51
+ 设置用户数据
52
+ </button>
53
+ </div>
54
+ <div className="text-lg">CrUtil.getLocalItem</div>
55
+ <div>
56
+ <button
57
+ type="button"
58
+ className="cr-btn line-blue radius"
59
+ onClick={onGet}
60
+ >
61
+ 获取用户数据
62
+ </button>
63
+ </div>
64
+ <div className="text-lg">CrUtil.removeLocalItem</div>
65
+ <div>
66
+ <button
67
+ type="button"
68
+ className="cr-btn line-blue radius"
69
+ onClick={onClear}
70
+ >
71
+ 清除用户数据
72
+ </button>
73
+ </div>
74
+ </div>
75
+ <div className="text-lg">CrUtil.clearLocal</div>
76
+ <div>
77
+ <button
78
+ type="button"
79
+ className="cr-btn line-blue radius"
80
+ onClick={onAllClear}
81
+ >
82
+ 清除全部
83
+ </button>
84
+ </div>
85
+
86
+ <div className="divider"></div>
87
+
88
+ <p>用户数据:{JSON.stringify(data)}</p>
89
+ </>
90
+ );
91
+ };
@@ -0,0 +1,85 @@
1
+ /**
2
+ * title: sessionStorage
3
+ */
4
+
5
+ import { CrStorage } from '@zcrkey/js-utils';
6
+ import React, { useState } from 'react';
7
+
8
+ const LOGIN_USER = 'loginUser';
9
+
10
+ export default () => {
11
+ const [data, setData] = useState<any>();
12
+
13
+ const onSet = () => {
14
+ CrStorage.setSessionItem(LOGIN_USER, {
15
+ name: 'zcr',
16
+ sex: '男',
17
+ age: 18,
18
+ });
19
+ };
20
+
21
+ const onGet = () => {
22
+ setData(CrStorage.getSessionItem(LOGIN_USER));
23
+ };
24
+
25
+ const onClear = () => {
26
+ CrStorage.removeSessionItem(LOGIN_USER);
27
+ setData('');
28
+ };
29
+
30
+ const onAllClear = () => {
31
+ CrStorage.clearSession();
32
+ setData('');
33
+ };
34
+
35
+ return (
36
+ <>
37
+ <div className="flex flex-direction">
38
+ <div className="text-lg">CrUtil.setSessionItem</div>
39
+ <div>
40
+ <button
41
+ type="button"
42
+ className="cr-btn line-blue radius"
43
+ onClick={onSet}
44
+ >
45
+ 设置用户数据
46
+ </button>
47
+ </div>
48
+ <div className="text-lg">CrUtil.getSessionItem</div>
49
+ <div>
50
+ <button
51
+ type="button"
52
+ className="cr-btn line-blue radius"
53
+ onClick={onGet}
54
+ >
55
+ 获取用户数据
56
+ </button>
57
+ </div>
58
+ <div className="text-lg">CrUtil.removeSessionItem</div>
59
+ <div>
60
+ <button
61
+ type="button"
62
+ className="cr-btn line-blue radius"
63
+ onClick={onClear}
64
+ >
65
+ 清除用户数据
66
+ </button>
67
+ </div>
68
+ </div>
69
+ <div className="text-lg">CrUtil.clearSession</div>
70
+ <div>
71
+ <button
72
+ type="button"
73
+ className="cr-btn line-blue radius"
74
+ onClick={onAllClear}
75
+ >
76
+ 清除全部
77
+ </button>
78
+ </div>
79
+
80
+ <div className="divider"></div>
81
+
82
+ <p>用户数据:{JSON.stringify(data)}</p>
83
+ </>
84
+ );
85
+ };
@@ -0,0 +1,5 @@
1
+ # CrTreeUtil 树工具类
2
+
3
+ 树工具类
4
+
5
+ <code src="./index.tsx"></code>