-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path303649792.html
More file actions
1415 lines (1010 loc) · 214 KB
/
Copy path303649792.html
File metadata and controls
1415 lines (1010 loc) · 214 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en" data-default-color-scheme="auto">
<head>
<meta charset="UTF-8">
<link rel="apple-touch-icon" sizes="76x76" href="/img/fluid.png">
<link rel="icon" href="/img/fluid.png">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="theme-color" content="#2f4154">
<meta name="author" content="FangZhou">
<meta name="keywords" content="react,frontend,web">
<meta name="description" content="React框架学习笔记,涵盖组件、Hooks和状态管理等核心概念">
<meta property="og:type" content="article">
<meta property="og:title" content="React学习笔记">
<meta property="og:url" content="http://arkpln.github.io/303649792.html">
<meta property="og:site_name" content="Ark的技术博客">
<meta property="og:description" content="React框架学习笔记,涵盖组件、Hooks和状态管理等核心概念">
<meta property="og:locale" content="en_US">
<meta property="og:image" content="http://arkpln.github.io/images/React.webp">
<meta property="article:published_time" content="2025-02-06T07:59:34.000Z">
<meta property="article:modified_time" content="2026-01-26T04:00:28.125Z">
<meta property="article:author" content="FangZhou">
<meta property="article:tag" content="react">
<meta property="article:tag" content="hooks">
<meta property="article:tag" content="components">
<meta property="article:tag" content="state-management">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="http://arkpln.github.io/images/React.webp">
<title>React学习笔记 - Ark的技术博客</title>
<link rel="stylesheet" href="https://lib.baomitu.com/twitter-bootstrap/4.6.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://lib.baomitu.com/github-markdown-css/4.0.0/github-markdown.min.css">
<link rel="stylesheet" href="https://lib.baomitu.com/hint.css/2.7.0/hint.min.css">
<link rel="stylesheet" href="https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.css">
<!-- 主题依赖的图标库,不要自行修改 -->
<!-- Do not modify the link that theme dependent icons -->
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_1749284_5i9bdhy70f8.css">
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_1736178_k526ubmyhba.css">
<link rel="stylesheet" href="/css/main.css">
<link id="highlight-css" rel="stylesheet" href="/css/highlight.css">
<link id="highlight-css-dark" rel="stylesheet" href="/css/highlight-dark.css">
<script id="fluid-configs">
var Fluid = window.Fluid || {};
Fluid.ctx = Object.assign({}, Fluid.ctx)
var CONFIG = {"hostname":"arkpln.github.io","root":"/","version":"1.9.8","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false,"scope":[]},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"left","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"code_language":{"enable":true,"default":"TEXT"},"copy_btn":true,"image_caption":{"enable":true},"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"placement":"right","headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":true,"follow_dnt":true,"baidu":null,"google":{"measurement_id":null},"tencent":{"sid":null,"cid":null},"leancloud":{"app_id":"mEwkD7geCX7RWNO8srhDE2oP-gzGzoHsz","app_key":"4EF76hyiVA1QILHZThVbfoat","server_url":"https://mewkd7ge.lc-cn-n1-shared.com","path":"window.location.pathname","ignore_local":false},"umami":{"src":null,"website_id":null,"domains":null,"start_time":"2024-01-01T00:00:00.000Z","token":null,"api_server":null}},"search_path":"/local-search.xml","include_content_in_search":true};
if (CONFIG.web_analytics.follow_dnt) {
var dntVal = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
Fluid.ctx.dnt = dntVal && (dntVal.startsWith('1') || dntVal.startsWith('yes') || dntVal.startsWith('on'));
}
</script>
<script src="/js/utils.js"></script>
<script src="/js/color-schema.js"></script>
<meta name="google-site-verification" content="5KfTZvtlydmBIzY97rVo-caP5jljAfmD3Qs3sBzY2Go"><style>ins.adsbygoogle[data-ad-status="unfilled"] { display: none !important; }</style>
<meta name="generator" content="Hexo 7.3.0"></head>
<body>
<header>
<div class="header-inner" style="height: 70vh;">
<nav id="navbar" class="navbar fixed-top navbar-expand-lg navbar-dark scrolling-navbar">
<div class="container">
<a class="navbar-brand" href="/">
<strong>Ark的技术博客</strong>
</a>
<button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<div class="animated-icon"><span></span><span></span><span></span></div>
</button>
<!-- Collapsible content -->
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav ml-auto text-center">
<li class="nav-item">
<a class="nav-link" href="/" target="_self">
<i class="iconfont icon-home-fill"></i>
<span>快乐老家</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/archives/" target="_self">
<i class="iconfont icon-archive-fill"></i>
<span>笔岚档案</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/categories/" target="_self">
<i class="iconfont icon-category-fill"></i>
<span>文以类聚</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/tags/" target="_self">
<i class="iconfont icon-tags-fill"></i>
<span>按标签阅览</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/about/" target="_self">
<i class="iconfont icon-user-fill"></i>
<span>联系我</span>
</a>
</li>
<li class="nav-item" id="search-btn">
<a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
<i class="iconfont icon-search"></i>
</a>
</li>
<li class="nav-item" id="color-toggle-btn">
<a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">
<i class="iconfont icon-dark" id="color-toggle-icon"></i>
</a>
</li>
</ul>
</div>
</div>
</nav>
<div id="banner" class="banner" parallax="true" style="background: url('/images/React.webp') no-repeat center center; background-size: cover;">
<div class="full-bg-img">
<div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
<div class="banner-text text-center fade-in-up">
<div class="h2">
<span id="subtitle" data-typed-text="React学习笔记"></span>
</div>
<div class="mt-3">
<span class="post-meta">
<i class="iconfont icon-date-fill" aria-hidden="true"></i>
<time datetime="2025-02-06 15:59" pubdate>
February 6, 2025 pm
</time>
</span>
</div>
<div class="mt-1">
<span class="post-meta mr-2">
<i class="iconfont icon-chart"></i>
35k words
</span>
<span class="post-meta mr-2">
<i class="iconfont icon-clock-fill"></i>
291 mins
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</header>
<main>
<div class="container-fluid nopadding-x">
<div class="row nomargin-x">
<div class="side-col d-none d-lg-block col-lg-2">
<aside class="sidebar d-none d-xl-block" style="margin-right:-1rem;z-index:-1"><ins class="adsbygoogle" style="display:flex;justify-content:center;min-width:160px;max-width:300px;width:100%;height:600px;position:sticky;top:2rem" data-ad-client="ca-pub-3240358922862141" data-ad-slot="6522434837"></ins><script> (adsbygoogle = window.adsbygoogle || []).push({}); </script></aside>
</div>
<div class="col-lg-8 nopadding-x-md">
<div class="container nopadding-x-md" id="board-ctn">
<div id="board">
<article class="post-content mx-auto">
<h1 id="seo-header">React学习笔记</h1>
<div class="markdown-body">
<h1 id="1-React介绍"><a href="#1-React介绍" class="headerlink" title="1.React介绍"></a>1.React介绍</h1><p><strong>React</strong> 是一个用于构建用户界面的JavaScript库,它允许开发者以声明式的方式创建交互丰富的Web应用。React不是一个完整的框架,而是专注于构建组件化的UI层。它可以与其他库或框架(如Redux或Angular)配合使用,以构建复杂的应用程序。</p>
<h1 id="2-React创建环境(以Vite为例)"><a href="#2-React创建环境(以Vite为例)" class="headerlink" title="2.React创建环境(以Vite为例)"></a>2.React创建环境(以Vite为例)</h1><p>在Node环境下输入</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs npmignore">npm create vite@latest my-vite-app <br></code></pre></td></tr></table></figure>
<p>按要求选择React+JavaScript配置</p>
<p><strong>文件目录</strong></p>
<table>
<thead>
<tr>
<th>文件名</th>
<th>用途</th>
</tr>
</thead>
<tbody><tr>
<td>package.json</td>
<td>核心包,包含核心依赖和关键命令</td>
</tr>
<tr>
<td>.src</td>
<td>存放项目的源代码。</td>
</tr>
<tr>
<td>.src/index.js</td>
<td>项目入口文件</td>
</tr>
<tr>
<td>.src/App.js</td>
<td>项目根组件</td>
</tr>
</tbody></table>
<p>./src/main.jsx</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-comment">// ./src/main.jsx项目入口 从这里开始运行</span><br><br><span class="hljs-comment">//React项目核心导入</span><br><span class="hljs-keyword">import</span> { createRoot } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span><br><span class="hljs-comment">//导入项目根组件</span><br><span class="hljs-keyword">import</span> <span class="hljs-title class_">App</span> <span class="hljs-keyword">from</span> <span class="hljs-string">'./App.jsx'</span><br><span class="hljs-comment">//把App根组件渲染到id为'root'的节点</span><br><span class="hljs-title function_">createRoot</span>(<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">'root'</span>)).<span class="hljs-title function_">render</span>( <br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">App</span> /></span></span><br>)<br><br><br></code></pre></td></tr></table></figure>
<p>./src/App.jsx</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-comment">//项目的根组件</span><br><span class="hljs-comment">// App -> index.js -> index.html(root)</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br> <span class="hljs-keyword">return</span> (<br> <span class="language-xml"><span class="hljs-tag"><></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> This is an App. </span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><span class="language-xml"></span><br><span class="language-xml"> <span class="hljs-tag"></></span></span><br> )<br>}<br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-title class_">App</span><br><br><br></code></pre></td></tr></table></figure>
<h1 id="3-JSX基础"><a href="#3-JSX基础" class="headerlink" title="3.JSX基础"></a>3.JSX基础</h1><h2 id="JSX理论"><a href="#JSX理论" class="headerlink" title="JSX理论"></a>JSX理论</h2><p><strong>概念:</strong> <strong>JSX</strong>是<em>JavaScript</em>和<em>XML</em>的缩写,表示<strong>JS代码中编写HTML模板结构</strong>,是React中编写UI模板的方法。</p>
<p><strong>本质:</strong> <strong>JSX</strong>本质是对JS的语法扩展,需要借助<em>Babel</em>编译转化成正常的JS。</p>
<h2 id="JSX语法"><a href="#JSX语法" class="headerlink" title="JSX语法"></a>JSX语法</h2><h3 id="JSX使用JS表达式"><a href="#JSX使用JS表达式" class="headerlink" title="JSX使用JS表达式"></a>JSX使用JS表达式</h3><p>使用<code>{}</code>传递表达式</p>
<p><strong>1.传递字符串</strong></p>
<p><strong>2.传递JavaScript变量/对象/函数/方法</strong></p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br> <span class="hljs-keyword">return</span> (<br> <span class="language-xml"><span class="hljs-tag"><></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> This is an App. </span><br><span class="language-xml"> {'This is a message'}</span><br><span class="language-xml"> {/* 传字符串 */}</span><br><span class="language-xml"> {count}</span><br><span class="language-xml"> {/* 传JavaScript变量 */}</span><br><span class="language-xml"> {getName()}</span><br><span class="language-xml"> {/* 传函数调用 */}</span><br><span class="language-xml"> {new Date().getDate()}</span><br><span class="language-xml"> {/* 传方法调用 */}</span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{color:</span>"<span class="hljs-attr">red</span>"}}></span></span><br><span class="language-xml"> {/* 传js对象 */}</span><br><span class="language-xml"> This is a red div.</span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><span class="language-xml"></span><br><span class="language-xml"> <span class="hljs-tag"></></span></span><br> )<br>}<br></code></pre></td></tr></table></figure>
<p><strong>注意:if、Switch、变量声明属于语句而非表达式,因此不能出现在<code>{}</code>中。</strong></p>
<h3 id="JSX实现列表渲染"><a href="#JSX实现列表渲染" class="headerlink" title="JSX实现列表渲染"></a>JSX实现列表渲染</h3><p><strong>语法:</strong> 在JSX中可以使用原生JS中的<em>map方法</em>渲染遍历列表</p>
<p><strong><code>{targetList.map(item=> <dom key={item.key}> </dom>)}</code></strong></p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">const</span> list =[{<span class="hljs-attr">id</span>:<span class="hljs-number">101</span>,<span class="hljs-attr">name</span>:<span class="hljs-string">'Vue'</span>},<br> {<span class="hljs-attr">id</span>:<span class="hljs-number">102</span>,<span class="hljs-attr">name</span>:<span class="hljs-string">'React'</span>},<br> {<span class="hljs-attr">id</span>:<span class="hljs-number">103</span>,<span class="hljs-attr">name</span>:<span class="hljs-string">'Angular'</span>},<br><br>]<br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br> <span class="hljs-keyword">return</span> (<br> <span class="language-xml"><span class="hljs-tag"><></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">ul</span>></span></span><br><span class="language-xml"> {list.map(item => <span class="hljs-tag"><<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span>></span>{item.name}<span class="hljs-tag"></<span class="hljs-name">li</span>></span>)}</span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">ul</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><span class="language-xml"></span><br><span class="language-xml"> <span class="hljs-tag"></></span></span><br> )<br>}<br></code></pre></td></tr></table></figure>
<p><strong>注意:对应的DOM标签上必须绑定一个独一无二的key值,可以是字符串或number,常用id绑定</strong></p>
<h3 id="JSX中实现条件渲染"><a href="#JSX中实现条件渲染" class="headerlink" title="JSX中实现条件渲染"></a>JSX中实现条件渲染</h3><p><strong>语法:</strong> 逻辑运算符 <strong><code>&&</code></strong> 或三元表达式 <strong><code>?:</code></strong> 实现条件渲染。</p>
<p><strong><code>{flag && <DOM></DOM>}</code></strong></p>
<p><strong><code>{flag ? <DOM>A</DOM> : <DOM>B</DOM>}</code></strong></p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">const</span> isLogin = <span class="hljs-literal">false</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br> <span class="hljs-keyword">return</span> (<br> <span class="language-xml"><span class="hljs-tag"><></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> {isLogin && <span class="hljs-tag"><<span class="hljs-name">span</span>></span>This is a span.<span class="hljs-tag"></<span class="hljs-name">span</span>></span>}</span><br><span class="language-xml"> {isLogin ? <span class="hljs-tag"><<span class="hljs-name">span</span>></span>Welcome<span class="hljs-tag"></<span class="hljs-name">span</span>></span>:<span class="hljs-tag"><<span class="hljs-name">span</span>></span>Loading...<span class="hljs-tag"></<span class="hljs-name">span</span>></span>}</span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></></span></span><br> )<br>}<br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-title class_">App</span><br><br><br></code></pre></td></tr></table></figure>
<p><strong>对于复杂情况,可构造核心函数,根据不同类型返回不同的JSX模板</strong></p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">const</span> articleType = <span class="hljs-number">3</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">getArticleTem</span>(<span class="hljs-params"></span>){<br> <span class="hljs-keyword">if</span> (articleType === <span class="hljs-number">0</span>){<br> <span class="hljs-keyword">return</span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span>No image<span class="hljs-tag"></<span class="hljs-name">div</span>></span></span>}<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(articleType === <span class="hljs-number">1</span>){<br> <span class="hljs-keyword">return</span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span>Single image<span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br> } <span class="hljs-keyword">else</span>{<br> <span class="hljs-keyword">return</span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span>Triple Image<span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br> }<br>}<br><br><br>{<span class="hljs-title function_">getArticleTem</span>()}<br></code></pre></td></tr></table></figure>
<h1 id="4-React事件与组件"><a href="#4-React事件与组件" class="headerlink" title="4.React事件与组件"></a>4.React事件与组件</h1><h2 id="React事件"><a href="#React事件" class="headerlink" title="React事件"></a>React事件</h2><h3 id="React基础事件绑定"><a href="#React基础事件绑定" class="headerlink" title="React基础事件绑定"></a>React基础事件绑定</h3><p><strong>语法:</strong> <em><strong><code><DOM onEvent={function()}></DOM></code></strong></em></p>
<p>例如</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">handleClick</span> = (<span class="hljs-params"></span>) =>{<br> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">"button被点击了"</span>)<br><br>}<br><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>){<br><br> <span class="language-xml"><span class="hljs-tag"><></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span>></span>Click Me<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></></span></span><br><br>}<br></code></pre></td></tr></table></figure>
<h3 id="使用事件对象参数"><a href="#使用事件对象参数" class="headerlink" title="使用事件对象参数"></a>使用事件对象参数</h3><p><strong>语法:</strong> 在事件回调函数中设置形参 <strong><code>e</code></strong></p>
<p>注意在DOM中的格式 <code><DOM action={(e) => function(Args,e)}> </DOM> </code></p>
<p>其中,事件对象<code>e</code> 是可选项。</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">handleClick</span> = (<span class="hljs-params">name,e</span>) =>{<br> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">"button被点击了"</span>)<br><br>}<br><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>){<br><br> <span class="language-xml"><span class="hljs-tag"><></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{(e)</span> =></span> handleClick('jack'),e}>Click Me<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></></span></span><br><br>}<br></code></pre></td></tr></table></figure>
<h2 id="React组件"><a href="#React组件" class="headerlink" title="React组件"></a>React组件</h2><h3 id="React组件使用"><a href="#React组件使用" class="headerlink" title="React组件使用"></a>React组件使用</h3><p><strong>概念:</strong> 一个组件就是用户界面的一部分,可以有自己的逻辑和外观,组件之间可以互相嵌套和多次复用。</p>
<p>在React中,一个组件就是一个首字母大写的函数,内部存放了组件的逻辑和视图UI,渲染组件时,以标签的形式书写即可。</p>
<p><strong>创建组件的方法:</strong></p>
<p>1.定义组件</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">const</span> <span class="hljs-title function_">Button</span> = (<span class="hljs-params"></span>) => {<br> <span class="hljs-keyword">return</span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">button</span>></span>Click Me<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br>}<br></code></pre></td></tr></table></figure>
<p>2.使用组件</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>){<br> <span class="hljs-keyword">return</span>(<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Button</span>></span><span class="hljs-tag"></<span class="hljs-name">Button</span>></span></span><br>)<br>}<br></code></pre></td></tr></table></figure>
<h3 id="useState基础"><a href="#useState基础" class="headerlink" title="useState基础"></a>useState基础</h3><p>useState是一个React Hook,允许我们向组件中添加一个<strong>状态变量</strong>,从而控制影响组件的渲染结果</p>
<p>本质:和普通JS变量不同,状态变量一旦发生变化,组件的视图UI也会发生变化。<strong>(数据驱动视图)</strong></p>
<p>语法:<strong><code>const [Variable,setVariableFunction] = useState(initialValue)</code></strong></p>
<ol>
<li><p><strong>useState</strong>是一个函数,返回值是一个数组</p>
</li>
<li><p>数组中的第一个参数是状态变量,第二个参数是set函数,用来修改状态变量</p>
</li>
<li><p>useState的参数将作为count的初始量</p>
</li>
</ol>
<p><strong>注意:</strong> 1. 需要引用<code>import { useState } from "react"</code> </p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br> <span class="hljs-keyword">const</span> [count,setCount] = <span class="hljs-title function_">useState</span>(<span class="hljs-number">0</span>)<br> <span class="hljs-keyword">const</span> <span class="hljs-title function_">handleClick</span> = (<span class="hljs-params"></span>) =>{<br> <span class="hljs-title function_">setCount</span>(count + <span class="hljs-number">1</span>)<br> } <br> <button onClick={handleClick}>{count}</button><br><br><br>}<br></code></pre></td></tr></table></figure>
<ol start="2">
<li><p><strong>状态不可变</strong><br>在React中,状态被认为是只读的,因此始终要使用匹配的<code>setVariableFunction()</code> 来替换原状态变量,直接的修改状态并不能引发视图更新。</p>
</li>
<li><p><strong>修改对象状态</strong><br>对于对象类型的状态变量,应该始终要使用匹配的<code>setVariableFunction()</code> 来替换原状态对象。</p>
</li>
</ol>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>){<br> <span class="hljs-keyword">const</span> [form,setForm] = <span class="hljs-title function_">useState</span>({<span class="hljs-attr">name</span>:<span class="hljs-string">'jack'</span>})<br> <span class="hljs-keyword">const</span> <span class="hljs-title function_">changeForm</span> = (<span class="hljs-params"></span>) =>{<br> <span class="hljs-title function_">setForm</span>({<br> ...form,<br> <span class="hljs-attr">name</span>:<span class="hljs-string">'john'</span><br> })<br> <span class="hljs-keyword">return</span>(<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{changeForm}</span>></span>{form.name}<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><br>)<br>}<br></code></pre></td></tr></table></figure>
<p><em>注:</em></p>
<p><strong>扩展运算符(Spread Operator):”…”</strong></p>
<ul>
<li><p>用于数组或对象的展开。例如,在数组中:<br>JavaScript复制<br> let arr1 = [1, 2, 3];<br> let arr2 = [0, …arr1, 4];<br>这里“…arr1”将arr1数组中的元素1、2、3展开,最终arr2的值为[0, 1, 2, 3, 4]。它能够将一个数组的元素逐个添加到另一个数组中。</p>
</li>
<li><p>对于对象,可以用于复制对象的属性。例如:<br>JavaScript复制<br> let obj1 = {a: 1, b: 2};<br> let obj2 = {…obj1, c: 3};<br>“…obj1”将obj1对象的属性a和b复制到obj2中,obj2的结构为{a: 1, b: 2, c: 3}。它能够将一个对象的可枚举属性复制到另一个对象中。</p>
</li>
</ul>
<h3 id="组件样式控制"><a href="#组件样式控制" class="headerlink" title="组件样式控制"></a>组件样式控制</h3><ol>
<li><p>行内样式<br><code><DOM style={color:'red'}></DOM></code></p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-comment">//index.css</span><br>.<span class="hljs-property">foo</span>{<br> <span class="hljs-attr">color</span>:<span class="hljs-string">"red"</span>;<br> <span class="hljs-attr">fontSize</span>:<span class="hljs-string">"50px"</span><br>}<br><span class="hljs-comment">//App.jsx</span><br><span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>){<br> <span class="hljs-keyword">return</span>(<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">classname</span>=<span class="hljs-string">'foo'</span>></span><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br>)<br>}<br></code></pre></td></tr></table></figure>
<ol start="2">
<li>class类名控制<br><strong>语法:</strong> <code><DOM className=""></DOM></code></li>
</ol>
</li>
</ol>
<p><em>注:</em> </p>
<ol>
<li><p>写行内样式时,CSS属性名要使用驼峰命名法.</p>
</li>
<li><p>需在App.js下引用对应的CSS文件.</p>
</li>
</ol>
<p><strong>classname优化类名控制</strong></p>
<ol>
<li><p>安装</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs npmignore">npm install classnames<br></code></pre></td></tr></table></figure>
</li>
<li><p>引用</p>
</li>
</ol>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">const</span> classNames = <span class="hljs-built_in">require</span>(<span class="hljs-string">'classnames'</span>)<br><span class="hljs-comment">//ES6</span><br><span class="hljs-keyword">import</span> classNames <span class="hljs-keyword">from</span> <span class="hljs-string">'classnames'</span><br><span class="hljs-comment">//import</span><br></code></pre></td></tr></table></figure>
<ol start="3">
<li>使用<br>语法:<code>classNames('objclassName1','2...',{conditionalClassName:Condition})</code></li>
</ol>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span <br>{key=item.<span class="hljs-property">type</span>}<br>className={<span class="hljs-title function_">classNames</span>(<span class="hljs-string">'nav-item'</span>,{<span class="hljs-attr">active</span>:type === item.<span class="hljs-property">type</span>})}<br></code></pre></td></tr></table></figure>
<h3 id="受控表单绑定"><a href="#受控表单绑定" class="headerlink" title="受控表单绑定"></a>受控表单绑定</h3><p><strong>概念:</strong> 使用React组件的状态(useState)控制表单的状态,即双向绑定</p>
<p><a target="_blank" rel="external nofollow noopener noreferrer" href="https://imgse.com/i/pEkBICq"><img src="https://s21.ax1x.com/2025/01/19/pEkBICq.png" srcset="/img/loading.gif" lazyload alt="pEkBICq.png"></a></p>
<p><strong>步骤:</strong></p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">const</span> [value,setValue] = <span class="hljs-title function_">useState</span>(<span class="hljs-string">''</span>)<br><span class="hljs-comment">// 1.准备一个React状态值</span><br><input <br>type=<span class="hljs-string">"text"</span><br>value={value}<br><span class="hljs-comment">// 2.通过value属性绑定React状态变量</span><br>onChange={<span class="hljs-function">(<span class="hljs-params">e</span>) =></span> <span class="hljs-title function_">setValue</span>(e.<span class="hljs-property">target</span>.<span class="hljs-property">value</span>)}<br><span class="hljs-comment">// 3.绑定onChange事件 通过参数e拿到输入框的值 反向修改到React状态中</span><br>/><br></code></pre></td></tr></table></figure>
<h3 id="React中获取DOM"><a href="#React中获取DOM" class="headerlink" title="React中获取DOM"></a>React中获取DOM</h3><p><strong>概念:</strong> 在React组件中<strong>获取/操作</strong> DOM,需要使用<strong>useRef</strong> 钩子函数,分为两步:</p>
<ol>
<li><p>使用useRef创建Ref对象,并与JSX绑定</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">const</span> inputRef = <span class="hljs-title function_">useRef</span>(<span class="hljs-literal">null</span>)<br><input type=<span class="hljs-string">"text"</span> ref={inputRef} /><br></code></pre></td></tr></table></figure>
</li>
<li><p>在DOM可用时(组件渲染完毕),通过<code>inputRef.current</code>获取DOM对象</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(inputRef.<span class="hljs-property">current</span>)<br></code></pre></td></tr></table></figure></li>
</ol>
<h2 id="React组件通信"><a href="#React组件通信" class="headerlink" title="React组件通信"></a>React组件通信</h2><h3 id="理解组件通信"><a href="#理解组件通信" class="headerlink" title="理解组件通信"></a>理解组件通信</h3><p><strong>概念:</strong> 组件通信就是<em>组件之间的数据传递</em>,根据组件嵌套关系的不同,有着不同的通信方法.</p>
<h4 id="父传子-基础实现"><a href="#父传子-基础实现" class="headerlink" title="父传子-基础实现"></a>父传子-基础实现</h4><p><strong>实现步骤:</strong> </p>
<ol>
<li><p>父组件传递数据,在子组件标签上绑定属性</p>
</li>
<li><p>子组件接收数据,子组件通过<strong>props参数</strong> 接收数据</p>
</li>
</ol>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">const</span> name = <span class="hljs-string">'This is app name.'</span><br> <span class="hljs-keyword">function</span> <span class="hljs-title function_">Son</span>(<span class="hljs-params">props</span>){<br> <span class="hljs-comment">// props:对象里面包含了父组件传递过来的所有数据</span><br> <span class="hljs-comment">// eslint-disable-next-line react/prop-types</span><br><br> <span class="hljs-keyword">return</span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span>this is son {props.name}<span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br> }<br>{<span class="hljs-comment">/* 父传子通信 */</span>}<br> <div><br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Son</span> <span class="hljs-attr">name</span>=<span class="hljs-string">{name}</span>></span><span class="hljs-tag"></<span class="hljs-name">Son</span>></span></span><br> </div><br><br><br></code></pre></td></tr></table></figure>
<h4 id="父传子-props"><a href="#父传子-props" class="headerlink" title="父传子-props"></a>父传子-props</h4><ol>
<li><p>props可传递任意的数据<br>数字、字符串、布尔值、数组、对象、函数、JSX</p>
</li>
<li><p>props是<strong>只读对象</strong><br>子组件<strong>只能读取props中的数据</strong>,不能直接进行修改,父组件的数据只能由父组件修改</p>
</li>
</ol>
<h4 id="父传子-props-children"><a href="#父传子-props-children" class="headerlink" title="父传子-props children"></a>父传子-props children</h4><p>场景:当我们把内容嵌套在子组件中时,父组件会自动在名为prop.children属性中接收内容</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">function</span> <span class="hljs-title function_">Son</span>(<span class="hljs-params">props</span>){<br> <span class="hljs-comment">// props:对象里面包含了父组件传递过来的所有数据</span><br> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(props)<br> <span class="hljs-comment">// eslint-disable-next-line react/prop-types</span><br> <span class="hljs-keyword">return</span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span>this is son {props.children}<span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><br> }<br><br><br><br></code></pre></td></tr></table></figure>
<h4 id="父子组件通信-子传父"><a href="#父子组件通信-子传父" class="headerlink" title="父子组件通信-子传父"></a>父子组件通信-子传父</h4><p>核心思路:在子组件中调用父组件中的函数并传递数据</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">function</span> <span class="hljs-title function_">Son</span>(<span class="hljs-params">{onGetMsg}</span>){<br> <span class="hljs-keyword">const</span> sonMsg = <span class="hljs-string">"This is son msg."</span><br> <span class="hljs-keyword">return</span> (<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> {/* 在子组件中调用父组件的形参 */}</span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span>=></span>onGetMsg(sonMsg)}>send<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br> )<br>}<br><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br> <span class="hljs-keyword">const</span> <span class="hljs-title function_">getMsg</span> = (<span class="hljs-params">msg</span>) => <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(msg)<br><br> <span class="hljs-keyword">return</span> (<br> <span class="language-xml"><span class="hljs-tag"><></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">Son</span> <span class="hljs-attr">onGetMsg</span>=<span class="hljs-string">{getMsg}</span>></span><span class="hljs-tag"></<span class="hljs-name">Son</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></></span></span><br> )<br>}<br></code></pre></td></tr></table></figure>
<h4 id="使用状态提升实现兄弟组件通信"><a href="#使用状态提升实现兄弟组件通信" class="headerlink" title="使用状态提升实现兄弟组件通信"></a>使用状态提升实现兄弟组件通信</h4><p><strong>实现思路:</strong> 借助<em>状态提升</em> 机制,通过父组件进行兄弟组件之间的数据传递</p>
<ol>
<li><p>A组件先通过子传父的方式把数据传给父组件App</p>
</li>
<li><p>App拿到数据后通过父传子的方式传递给B组件</p>
</li>
</ol>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">function</span> <span class="hljs-title function_">A</span>(<span class="hljs-params">{ onGetAname }</span>){<br> <span class="hljs-comment">// {onGetAname}是组件A的参数解构,意味着函数接受同名函数作为props在组件内调用</span><br> <span class="hljs-keyword">const</span> name = <span class="hljs-string">'This is A name'</span><br> <span class="hljs-keyword">return</span>(<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> This is A component</span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =></span> onGetAname(name)}>Send<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><br> )<br>}<br><span class="hljs-keyword">function</span> <span class="hljs-title function_">B</span>(<span class="hljs-params">{name}</span>){<br> <span class="hljs-keyword">return</span>(<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> This is B component.</span><br><span class="language-xml"> {name}</span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><br> )<br>}<br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br> <span class="hljs-keyword">const</span> [name,setName] = <span class="hljs-title function_">useState</span>(<span class="hljs-string">''</span>)<br> <span class="hljs-keyword">const</span> <span class="hljs-title function_">getAname</span> = (<span class="hljs-params">name</span>) =>{<br> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(name)<br> <span class="hljs-title function_">setName</span>(name)<br> }<br> <span class="hljs-keyword">return</span>(<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> This is app.</span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">A</span> <span class="hljs-attr">onGetAname</span>=<span class="hljs-string">{getAname}/</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">B</span> <span class="hljs-attr">name</span>=<span class="hljs-string">{name}/</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><br> )<br>}<br></code></pre></td></tr></table></figure>
<h4 id="使用Context机制跨层级组件通信"><a href="#使用Context机制跨层级组件通信" class="headerlink" title="使用Context机制跨层级组件通信"></a>使用Context机制跨层级组件通信</h4><p><strong>实现步骤:</strong> </p>
<ol>
<li><p>使用<strong>createContext</strong>方法创建上下文对象Ctx</p>
</li>
<li><p>在顶层组件(App)中通过<strong>Ctx.Provider</strong>组件提供数据</p>
</li>
<li><p>在底层组件中通过<strong>useContext</strong>钩子函数获取数据</p>
</li>
</ol>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-comment">// 1.创建上下文对象</span><br><span class="hljs-keyword">const</span> <span class="hljs-title class_">MsgContext</span> = <span class="hljs-title function_">createContext</span>()<br><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">A</span>(<span class="hljs-params"></span>){<br><br> <span class="hljs-keyword">return</span>(<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> This is A component</span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">B</span>/></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><br> )<br>}<br><span class="hljs-keyword">function</span> <span class="hljs-title function_">B</span>(<span class="hljs-params"></span>){<br> <span class="hljs-comment">// 3.使用useContext钩子函数获取数据</span><br> <span class="hljs-keyword">const</span> msg = <span class="hljs-title function_">useContext</span>(<span class="hljs-title class_">MsgContext</span>)<br> <span class="hljs-keyword">return</span>(<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> This is B component.</span><br><span class="language-xml"> {msg}</span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><br> )<br>}<br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br> <span class="hljs-keyword">const</span> msg = <span class="hljs-string">"This is app msg."</span><br> <span class="hljs-keyword">return</span>(<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> {/* 2. 在顶层创建Ctx.Provider组件 */}</span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">MsgContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{msg}</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">A</span>/></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">MsgContext.Provider</span>></span></span><br><span class="language-xml"> This is app.</span><br><span class="language-xml"></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><br> )<br>}<br></code></pre></td></tr></table></figure>
<h3 id="useEffect"><a href="#useEffect" class="headerlink" title="useEffect"></a>useEffect</h3><h4 id="useEffect的使用"><a href="#useEffect的使用" class="headerlink" title="useEffect的使用"></a>useEffect的使用</h4><p>useEffect是一个React Hook函数,用于在React组件中创建<em>不是由于事件引起</em>而是<strong>渲染本身引起的操作</strong> ,例如<em>发送AJAX请求,更改DOM</em></p>
<p><strong>需求:</strong> 在组件渲染完毕后,立刻从服务器获取频道数据并显示到页面上</p>
<p><strong>语法:</strong></p>
<p><code>useEffect(() = {Function()},[Array])</code></p>
<p>参数1为<strong>副作用函数</strong> ,在函数内放置要执行的操作</p>
<p>参数2为数组(<em>可选</em>),数组内的依赖项会影响第一个参数函数的执行,若为空,<strong>副作用函数只会在组件渲染完毕后执行一次</strong></p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">const</span> <span class="hljs-variable constant_">URL</span> = <span class="hljs-string">"http://geek.itheima.net/v1_0/channels"</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br> <span class="hljs-keyword">const</span> [list,setList] = <span class="hljs-title function_">useState</span>([])<br> <span class="hljs-title function_">useEffect</span>(<span class="hljs-function">()=></span>{<br><span class="hljs-comment">// 获取频道列表</span><br> <span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">getList</span>(<span class="hljs-params"></span>){<br> <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> <span class="hljs-title function_">fetch</span>(<span class="hljs-variable constant_">URL</span>)<br> <span class="hljs-keyword">const</span> jsonRes = <span class="hljs-keyword">await</span> res.<span class="hljs-title function_">json</span>()<br> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(jsonRes)<br> <span class="hljs-title function_">setList</span>(jsonRes.<span class="hljs-property">data</span>.<span class="hljs-property">channels</span>)<br> }<br> <span class="hljs-title function_">getList</span>()<br> },[])<br> <span class="hljs-keyword">return</span>(<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">ul</span>></span></span><br><span class="language-xml"> {list.map(item => <span class="hljs-tag"><<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span>></span>{item.name} <span class="hljs-tag"></<span class="hljs-name">li</span>></span>)}</span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">ul</span>></span></span><br><span class="language-xml"></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br> )<br>}<br><br></code></pre></td></tr></table></figure>
<h4 id="useEffect依赖项参数"><a href="#useEffect依赖项参数" class="headerlink" title="useEffect依赖项参数"></a>useEffect依赖项参数</h4><table>
<thead>
<tr>
<th>依赖项</th>
<th>副作用函数执行时机</th>
</tr>
</thead>
<tbody><tr>
<td>没有依赖项</td>
<td>组件初始渲染+组件更新时执行</td>
</tr>
<tr>
<td>空数组依赖</td>
<td>只在初始渲染时执行一次</td>
</tr>
<tr>
<td>添加特定依赖项</td>
<td>组件初始渲染+特性依赖项变化时执行</td>
</tr>
</tbody></table>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><br><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span><br><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br> <span class="hljs-comment">// 无依赖项 初始+组件更新</span><br> <span class="hljs-keyword">const</span> [count,setCount] = <span class="hljs-title function_">useState</span>(<span class="hljs-number">0</span>)<br> <span class="hljs-title function_">useEffect</span>(<span class="hljs-function">()=></span>{<br> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">'副作用函数执行了'</span>)<br> })<br><br> <span class="hljs-comment">// 空数组依赖 仅在初始时执行一次</span><br> <span class="hljs-title function_">useEffect</span>(<span class="hljs-function">()=></span>{<br> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">'空数组依赖'</span>)<br> },[])<br> <span class="hljs-comment">// 传入特定依赖项 初始 + 依赖项变化时执行</span><br> <span class="hljs-title function_">useEffect</span>(<span class="hljs-function">()=></span>{<br> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">'含依赖项'</span>)<br> },[count])<br> <span class="hljs-keyword">return</span>(<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span>=></span> setCount(count+1)}>{count}<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br> )<br>}<br></code></pre></td></tr></table></figure>
<h4 id="useEffect-清除副作用"><a href="#useEffect-清除副作用" class="headerlink" title="useEffect-清除副作用"></a>useEffect-清除副作用</h4><p>在useEffect中编写的副作用操作,想在组件卸载时再清理掉,该过程即为<strong>清理副作用</strong></p>
<p><strong>语法:</strong> </p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-title function_">useEffect</span>(<span class="hljs-function">() =></span>{<br> <span class="hljs-comment">//实现副作用的操作</span><br> <span class="hljs-keyword">return</span> <span class="hljs-function">() =></span> {<br> <span class="hljs-comment">//清除副作用逻辑</span><br>}<br><br>},[])<br></code></pre></td></tr></table></figure>
<p>示例</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">function</span> <span class="hljs-title function_">Son</span>(<span class="hljs-params"></span>){<br> <span class="hljs-title function_">useEffect</span>(<span class="hljs-function">()=></span>{<br> <span class="hljs-keyword">const</span> timer = <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">()=></span>{<br> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">'定时器执行中'</span>)<br> },<span class="hljs-number">1000</span>)<br><br> <span class="hljs-keyword">return</span> <span class="hljs-function">()=></span>{<br> <span class="hljs-comment">// 清除副作用</span><br> <span class="hljs-built_in">clearInterval</span>(timer)<br> }<br> })<br> <span class="hljs-keyword">return</span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span>This is son<span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br>}<br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br> <span class="hljs-keyword">const</span> [show,setShow] = <span class="hljs-title function_">useState</span>(<span class="hljs-literal">true</span>)<br> <span class="hljs-keyword">return</span>(<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> {show && <span class="hljs-tag"><<span class="hljs-name">Son</span>/></span>}</span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span>=></span>setShow(false)}>卸载Son组件<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br> )<br>}<br><br></code></pre></td></tr></table></figure>
<h3 id="其他useHooks函数"><a href="#其他useHooks函数" class="headerlink" title="其他useHooks函数"></a>其他useHooks函数</h3><h4 id="useReducer"><a href="#useReducer" class="headerlink" title="useReducer"></a>useReducer</h4><p><strong>作用:</strong> 和useState类似,用于管理相对复杂的状态数据,对于需要复杂操作的状态变量,该函数比<code>useState</code>更具优势。</p>
<p><strong>语法:</strong></p>
<p>reducer函数:<code>reducer(state,action)</code></p>
<p>管理状态变量:<code>switch(action.type){case:...}</code></p>
<p>调起useHooks方法 注册状态变量:<code>const [state,dispatch] = useReducer(reducer,defaultValue)</code></p>
<p>使用dispatch方法操作状态变量:<code>dispatch({type:'ACTION'})</code></p>
<h6 id="useReducer-基础用法"><a href="#useReducer-基础用法" class="headerlink" title="useReducer-基础用法"></a>useReducer-基础用法</h6><ol>
<li><p>定义一个reducer函数(<em>根据不同的action返回不同的状态</em>)</p>
</li>
<li><p>在组件中调用useReducer,并传入reducer函数和状态的初始值</p>
</li>
<li><p>事件发生时,通过dispatch函数分派一个action对象(通知reducer要返回哪个新状态并渲染UI)</p>
</li>
</ol>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><br><span class="hljs-comment">// 1.定义reducer函数,根据不同的action返回不同的状态</span><br> <span class="hljs-keyword">function</span> <span class="hljs-title function_">reducer</span>(<span class="hljs-params">state,action</span>){<br> <span class="hljs-keyword">switch</span>(action.<span class="hljs-property">type</span>){<br> <span class="hljs-keyword">case</span> <span class="hljs-string">'INC'</span>:<br> <span class="hljs-keyword">return</span> state + <span class="hljs-number">1</span><br> <span class="hljs-keyword">case</span> <span class="hljs-string">'DEC'</span>:<br> <span class="hljs-keyword">return</span> state - <span class="hljs-number">1</span><br> <span class="hljs-attr">default</span>:<br> <span class="hljs-keyword">return</span> state<br> }<br><br>}<br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br><br> <span class="hljs-comment">// 2.组件中调用useReducer(reducer,0) =>[state,dispatch]</span><br> <span class="hljs-keyword">const</span> [state,dispatch] = <span class="hljs-title function_">useReducer</span>(reducer,<span class="hljs-number">0</span>)<br> <span class="hljs-comment">// 3.调用dispa tch({type:'INC'}) =>通知reducer产生新的状态来更新UI</span><br><br> <span class="hljs-keyword">return</span> (<br> <span class="language-xml"><span class="hljs-tag"><></span></span><br><span class="language-xml"></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card"</span>></span></span><br><span class="language-xml"></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span>=></span>{dispatch({ type:'INC' })}}></span><br><span class="language-xml"> count is {state}</span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span>=></span>{dispatch({ type:'DEC' })}}></span><br><span class="language-xml"> count is {state}</span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><span class="language-xml"></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></></span></span><br> )<br>}<br></code></pre></td></tr></table></figure>
<h5 id="useReducer-分派action时传参"><a href="#useReducer-分派action时传参" class="headerlink" title="useReducer-分派action时传参"></a>useReducer-分派action时传参</h5><p>在<code>dispatch({...,payload:value})</code>中传参时,需要在<code>reducer</code>函数中使用<code>action.payload</code>接收</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">function</span> <span class="hljs-title function_">reducer</span>(<span class="hljs-params">state,action</span>){<br> <span class="hljs-keyword">switch</span>(action.<span class="hljs-property">type</span>){<br> <span class="hljs-keyword">case</span> <span class="hljs-string">'SET'</span>:<br> <span class="hljs-keyword">return</span> action.<span class="hljs-property">payload</span><br> <span class="hljs-attr">default</span>:<br> <span class="hljs-keyword">return</span> state<br> }<br><span class="hljs-comment">// ...</span><br> <button onClick={<span class="hljs-function">()=></span>{<span class="hljs-title function_">dispatch</span>({ <span class="hljs-attr">type</span>:<span class="hljs-string">'SET'</span>,<span class="hljs-attr">payload</span>:<span class="hljs-number">100</span> })}}><br> <span class="hljs-title class_">Update</span> count to <span class="hljs-number">100</span><br> </button><br></code></pre></td></tr></table></figure>
<p><a target="_blank" rel="external nofollow noopener noreferrer" href="https://imgse.com/i/pE8R458"><img src="https://s21.ax1x.com/2025/03/01/pE8R458.png" srcset="/img/loading.gif" lazyload alt="pE8R458.png"></a></p>
<h4 id="useMemo"><a href="#useMemo" class="headerlink" title="useMemo"></a>useMemo</h4><p><strong>作用:</strong> 在组件每次重新渲染时<strong>缓存计算的结果</strong>,由此保证只有列表内的依赖项(即需要改变的状态变量)改变时再重新计算,从而避免不必要的组件重复渲染</p>
<p><strong>语法:</strong> <code>useMemo(()=>{},[state])</code></p>
<p><strong>备注:</strong> 消耗非常大的计算</p>
<h4 id="useCallback"><a href="#useCallback" class="headerlink" title="useCallback"></a>useCallback</h4><p><strong>作用:</strong> 在组件多次重新渲染的时候<em>缓存函数</em></p>
<p><strong>语法:</strong> <code>const changeHandler = useCallback((value) => console.log(),[])</code></p>
<p><strong>作用:</strong> 使用useCallback包裹函数后,函数可以保证在app<em>重新渲染时保持稳定</em></p>
<h3 id="自定义Hook函数"><a href="#自定义Hook函数" class="headerlink" title="自定义Hook函数"></a>自定义Hook函数</h3><h4 id="自定义Hook"><a href="#自定义Hook" class="headerlink" title="自定义Hook"></a>自定义Hook</h4><p><strong>概念:</strong> 自定义Hook是以<em>use</em> 打头的函数,通过自定义Hook函数可以实现逻辑的封装和复用</p>
<p><strong>思路:</strong></p>
<ol>
<li><p>声明一个以use打头的函数</p>
</li>
<li><p>在函数体内封装可复用的逻辑</p>
</li>
<li><p>把组件中用到的状态或者回调return出去</p>
</li>
<li><p>在哪个组件中要用到这个逻辑,就执行这个函数,解构出状态和相应的回调</p>
</li>
</ol>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span><br><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">useToggle</span>(<span class="hljs-params"></span>){<br> <span class="hljs-keyword">const</span> [value,setValue] = <span class="hljs-title function_">useState</span>(<span class="hljs-literal">true</span>)<br> <span class="hljs-keyword">const</span> <span class="hljs-title function_">toggle</span> = (<span class="hljs-params"></span>) => <span class="hljs-title function_">setValue</span>(!value)<br> <span class="hljs-comment">// 哪些状态和回调函数需要就在其他组件中使用return</span><br> <span class="hljs-keyword">return</span>{<br> value,toggle<br> }<br>}<br><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br> <span class="hljs-keyword">const</span> {value,toggle} = <span class="hljs-title function_">useToggle</span>()<br> <span class="hljs-keyword">return</span>(<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> {value && <span class="hljs-tag"><<span class="hljs-name">div</span>></span>This is div<span class="hljs-tag"></<span class="hljs-name">div</span>></span>}</span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{toggle}</span>></span>toggle<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br> )<br>}<br><br><br></code></pre></td></tr></table></figure>
<h4 id="React-Hooks函数使用规则"><a href="#React-Hooks函数使用规则" class="headerlink" title="React Hooks函数使用规则"></a>React Hooks函数使用规则</h4><ol>
<li><p>只能在组件中或者其他自定义Hook函数中调用</p>
</li>
<li><p>只能在组件的顶层调用,不能嵌套在if/for/其他函数等</p>
</li>
</ol>
<h2 id="React方法"><a href="#React方法" class="headerlink" title="React方法"></a>React方法</h2><h3 id="React-memo"><a href="#React-memo" class="headerlink" title="React.memo"></a>React.memo</h3><h4 id="React-memo-基本用法"><a href="#React-memo-基本用法" class="headerlink" title="React.memo-基本用法"></a>React.memo-基本用法</h4><p><strong>背景:</strong> React默认渲染机制,只要父组件重新渲染,子组件就会重新渲染</p>
<p><strong>作用:</strong> 经过memo函数包裹生产的缓存组件会在<strong>Props没有改变</strong>的情况下跳过渲染</p>
<p><strong>语法:</strong> <code>const MemoComponet = memo(function SomeComponent (props){...})</code></p>
<h4 id="React-memo-props的比较机制"><a href="#React-memo-props的比较机制" class="headerlink" title="React.memo-props的比较机制"></a>React.memo-props的比较机制</h4><p><strong>机制:</strong> React会对每一个prop使用<code>Object.is</code>比较新值和老值,返回true表示无变化</p>
<ul>
<li><p>props是简单类型<br><code>Object.is(3,3)=>true</code><br>没变化</p>
</li>
<li><p>props是引用类型(数组/对象)<br><code>Object.is([],[])=>false</code><br>有变化,当父组件的函数重新执行时,实际上形成的新的数组引用</p>
</li>
</ul>
<p>为了保证引用稳定,可以使用useMemo组件渲染过程中缓存一个值</p>
<h3 id="React-forwardRef"><a href="#React-forwardRef" class="headerlink" title="React.forwardRef"></a>React.forwardRef</h3><h4 id="React-fowardRef基本用法"><a href="#React-fowardRef基本用法" class="headerlink" title="React.fowardRef基本用法"></a>React.fowardRef基本用法</h4><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><br><span class="hljs-keyword">const</span> <span class="hljs-title class_">Input</span> = <span class="hljs-title function_">forwardRef</span>(<span class="hljs-function">(<span class="hljs-params">props,ref</span>) =></span> {<br> <span class="hljs-keyword">return</span> (<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{ref}</span> /></span></span><br> )<br>})<br><br><br><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br><br> <span class="hljs-comment">// 2.组件中调用useReducer(reducer,0) =>[state,dispatch]</span><br><br> <span class="hljs-comment">// 3.调用dispatch({type:'INC'}) =>通知reducer产生新的状态来更新UI</span><br> <span class="hljs-keyword">const</span> inputRef = <span class="hljs-title function_">useRef</span>(<span class="hljs-literal">null</span>)<br> <span class="hljs-keyword">const</span> <span class="hljs-title function_">showRef</span> = (<span class="hljs-params"></span>) =>{<br> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(inputRef) <br> }<br> <span class="hljs-keyword">return</span> (<br> <span class="language-xml"><span class="hljs-tag"><></span></span><br><span class="language-xml"></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card"</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">Input</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{inputRef}</span> /></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{showRef}</span>></span>获取ref<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></></span></span><br> )<br>}<br></code></pre></td></tr></table></figure>
<h4 id="React-useInperativeHandle"><a href="#React-useInperativeHandle" class="headerlink" title="React.useInperativeHandle"></a>React.useInperativeHandle</h4><p><strong>作用:</strong> 在子组件内部实现对ref方法的暴露,以便于调用</p>
<p><strong>语法:</strong> </p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-keyword">const</span> <span class="hljs-title class_">Input</span> = <span class="hljs-title function_">forwardRef</span>(<span class="hljs-function">(<span class="hljs-params">props,ref</span>)=></span><br>{<br> <span class="hljs-keyword">const</span> inputref = <span class="hljs-title function_">useRef</span>(<span class="hljs-literal">null</span>)<br> <span class="hljs-keyword">const</span> <span class="hljs-title function_">focusHandler</span> = (<span class="hljs-params"></span>) =>{<br> inputRef.<span class="hljs-property">current</span>.<span class="hljs-title function_">focus</span>()<br>}<br><br><span class="hljs-title function_">useImperativeHandle</span>(ref,<span class="hljs-function">() =></span>{<br> <span class="hljs-keyword">return</span> {<br> focusHandler<br>}<br>} )<br>}<br><span class="hljs-keyword">return</span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{inputRef}</span> /></span></span><br><br>})<br></code></pre></td></tr></table></figure>
<h1 id="5-Redux"><a href="#5-Redux" class="headerlink" title="5.Redux"></a>5.Redux</h1><h2 id="Redux上手"><a href="#Redux上手" class="headerlink" title="Redux上手"></a>Redux上手</h2><h3 id="Redux快速体验"><a href="#Redux快速体验" class="headerlink" title="Redux快速体验"></a>Redux快速体验</h3><p>Redux 是 JavaScript 应用的状态容器,提供可预测的状态管理。</p>
<p><a target="_blank" rel="external nofollow noopener noreferrer" href="https://imgse.com/i/pEAsEzq"><img src="https://s21.ax1x.com/2025/01/22/pEAsEzq.png" srcset="/img/loading.gif" lazyload alt="pEAsEzq.png"></a></p>
<p><strong>使用步骤:</strong></p>
<ol>
<li><p>定义一个<em>reducer函数</em>(根据当前想要做的修改返回一个新的状态)</p>
</li>
<li><p>使用createStore方法传入<em>reducer函数</em> 生成一个<em>reducer实例</em></p>
</li>
<li><p>使用<em>store实例</em>的<strong>subscribe方法</strong> 订阅数据的变化(数据一旦变化,可以得到通知)</p>
</li>
<li><p>使用<em>store实例</em>的<strong>dispatch方法提交action对象</strong> 触发数据变化(告诉<em>reducer</em> 你如何修改数据)</p>
</li>
<li><p>使用store实例的<strong>getState方法</strong> 获取最新的状态数据更新到视图中</p>
</li>
</ol>
<h3 id="Redux与React配套"><a href="#Redux与React配套" class="headerlink" title="Redux与React配套"></a>Redux与React配套</h3><h4 id="配套工具"><a href="#配套工具" class="headerlink" title="配套工具:"></a>配套工具:</h4><p>1.Redux Tookit</p>
<p>2.react-redux</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs npmignore"><br>npm install react-redux<br><br>npm install redux-toolkit<br></code></pre></td></tr></table></figure>
<p><strong>store目录</strong></p>
<ol>
<li><p>通常集中状态管理部分单独创建一个<code>store</code>目录</p>
</li>
<li><p>应用通常会有很多个子store模块,所以会创建一个<code>modules</code>目录,在文件夹内编写业务分类的子store</p>
</li>
<li><p>store中的入口文件<code>index.js</code>的作用是组合modules中的所有子模块,并导出store</p>
</li>
</ol>
<h3 id="Redux-React-实现counter"><a href="#Redux-React-实现counter" class="headerlink" title="Redux+React =>实现counter"></a>Redux+React =>实现counter</h3><h4 id="整体路径"><a href="#整体路径" class="headerlink" title="整体路径"></a>整体路径</h4><p><a target="_blank" rel="external nofollow noopener noreferrer" href="https://imgse.com/i/pEEuD1I"><img src="https://s21.ax1x.com/2025/01/24/pEEuD1I.png" srcset="/img/loading.gif" lazyload alt="pEEuD1I.png"></a></p>
<h4 id="创建Redux的store对象"><a href="#创建Redux的store对象" class="headerlink" title="创建Redux的store对象"></a>创建Redux的store对象</h4><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-comment">// ./modules/counterStore.js</span><br><span class="hljs-keyword">import</span> {createSlice} <span class="hljs-keyword">from</span> <span class="hljs-string">'@reduxjs/toolkit'</span><br><br><span class="hljs-keyword">const</span> counterStore = <span class="hljs-title function_">createSlice</span>({<br> <span class="hljs-attr">name</span>:<span class="hljs-string">'counter'</span>,<br> <span class="hljs-comment">// 初始状态数据</span><br> <span class="hljs-attr">initialState</span>:{<br> <span class="hljs-attr">count</span>:<span class="hljs-number">0</span><br> },<br> <span class="hljs-comment">// 修改数据同步的方法</span><br> <span class="hljs-attr">reducers</span>:{<br> <span class="hljs-title function_">increment</span>(<span class="hljs-params">state</span>){<br> state.<span class="hljs-property">count</span>++<br> },<br> <span class="hljs-title function_">decrement</span>(<span class="hljs-params">state</span>){<br> state.<span class="hljs-property">count</span>--<br> },<br> },<br><br>})<br><span class="hljs-comment">// 解构创建action对象的函数</span><br><span class="hljs-keyword">const</span> {increment,decrement} = counterStore.<span class="hljs-property">actions</span><br><span class="hljs-comment">// 获取reducer函数</span><br><span class="hljs-keyword">const</span> counterReducer = counterStore.<span class="hljs-property">reducer</span><br><span class="hljs-comment">// 导出action对象的函数和reducer函数</span><br><span class="hljs-keyword">export</span>{increment,decrement}<br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> counterReducer<br></code></pre></td></tr></table></figure>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-comment">// index.js</span><br><span class="hljs-keyword">import</span> { configureStore } <span class="hljs-keyword">from</span> <span class="hljs-string">"@reduxjs/toolkit"</span>;<br><span class="hljs-keyword">import</span> counterReducer <span class="hljs-keyword">from</span> <span class="hljs-string">"./modules/counterStore"</span>;<br><br><span class="hljs-keyword">const</span> store = <span class="hljs-title function_">configureStore</span>({<br> <span class="hljs-attr">reducer</span>:{<br> <span class="hljs-attr">counter</span>:counterReducer<br> }<br>})<br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> store<br></code></pre></td></tr></table></figure>
<h4 id="为React注入store"><a href="#为React注入store" class="headerlink" title="为React注入store"></a>为React注入store</h4><p>react-redux负责把Redux和React链接起来,内置的Provider组件通过store参数把创建好的store实例注入到应用程序中,链接正式建立</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><br><span class="hljs-keyword">import</span> { createRoot } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span><br><span class="hljs-keyword">import</span> <span class="hljs-title class_">App</span> <span class="hljs-keyword">from</span> <span class="hljs-string">'./App.jsx'</span><br><span class="hljs-keyword">import</span> store <span class="hljs-keyword">from</span> <span class="hljs-string">'./store/index.js'</span><br><span class="hljs-keyword">import</span> {<span class="hljs-title class_">Provider</span>} <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span><br><span class="hljs-title function_">createRoot</span>(<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">'root'</span>)).<span class="hljs-title function_">render</span>(<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Provider</span> <span class="hljs-attr">store</span>=<span class="hljs-string">{store}</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">App</span> /></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">Provider</span>></span></span><br> ,<br>)<br><br></code></pre></td></tr></table></figure>
<h4 id="React组件中使用store中的数据"><a href="#React组件中使用store中的数据" class="headerlink" title="React组件中使用store中的数据"></a>React组件中使用store中的数据</h4><p>在React组件中使用<code>store</code>中的数据,需要用到一个钩子函数<code>useSelector(state => state.Variable)</code></p>
<p><strong>作用:</strong> 将store中的数据映射到组件中</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-comment">//App.jsx</span><br><span class="hljs-keyword">import</span> { useSelector } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br> <span class="hljs-keyword">const</span> {count} = <span class="hljs-title function_">useSelector</span>(<span class="hljs-function"><span class="hljs-params">state</span> =></span> state.<span class="hljs-property">counter</span>)<br><br> <span class="hljs-keyword">return</span> (<br> <span class="language-xml"><span class="hljs-tag"><></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>></span></span><br><span class="language-xml"> {count}</span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></></span></span><br> )<br>}<br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-title class_">App</span><br><br></code></pre></td></tr></table></figure>
<p><em>注意:</em> 该例子中App.jsx中的counter实际定义在store中的入口,即<code>index.js</code></p>
<h4 id="React组件中修改store的数据"><a href="#React组件中修改store的数据" class="headerlink" title="React组件中修改store的数据"></a>React组件中修改store的数据</h4><p>React组件中修改store中的数据需要借助<code>useDispatch()</code>的hook函数</p>
<p><strong>作用:</strong> 生成提交<em>action对象</em>的函数</p>
<h3 id="Redux-React-提交action传参"><a href="#Redux-React-提交action传参" class="headerlink" title="Redux+React - 提交action传参"></a>Redux+React - 提交action传参</h3><h4 id="提交action传参实现需求"><a href="#提交action传参实现需求" class="headerlink" title="提交action传参实现需求"></a>提交action传参实现需求</h4><p>在reduers的同步修改方法中添加action对象参数,在调用<code>actionCreater</code>时传递参数,参数会被传递到<code>action</code>对象的<code>payload</code>属性上.</p>
<h3 id="Redux-React-异步状态管理"><a href="#Redux-React-异步状态管理" class="headerlink" title="Redux+React - 异步状态管理"></a>Redux+React - 异步状态管理</h3><h4 id="异步操作样板写法"><a href="#异步操作样板写法" class="headerlink" title="异步操作样板写法"></a>异步操作样板写法</h4><ol>
<li><p>创建store的写法保持不变,配置好同步修改状态的方法</p>
</li>
<li><p>单独封装一个函数,在函数内return一个新函数,在新函数中<br>2.1 封装异步请求获取数据<br>2.2 调用<strong>同步actionCreater</strong> 传入异步数据生成action对象,使用dispatch提交</p>
</li>
<li><p>组件中<code>dispatch</code>的写法不变</p>
</li>
</ol>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-comment">//chaannelStore.js</span><br><span class="hljs-keyword">import</span> { createSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">"@reduxjs/toolkit"</span>;<br><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span><br><span class="hljs-keyword">const</span> channelStore = <span class="hljs-title function_">createSlice</span>({<br> <span class="hljs-attr">name</span>:<span class="hljs-string">'channel'</span>,<br> <span class="hljs-attr">initialState</span>:{<br> <span class="hljs-attr">channelList</span>:[]<br> },<br> <span class="hljs-attr">reducers</span>:{<br> <span class="hljs-title function_">setChannels</span>(<span class="hljs-params">state,action</span>){<br> state.<span class="hljs-property">channelList</span> = action.<span class="hljs-property">payload</span><br> }<br> }<br>})<br><br><span class="hljs-comment">// 异步请求</span><br><span class="hljs-keyword">const</span> {setChannels} = channelStore.<span class="hljs-property">actions</span><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">fetchChannelList</span> = (<span class="hljs-params"></span>) =>{<br> <span class="hljs-keyword">return</span> <span class="hljs-title function_">async</span> (dispatch)=>{<br> <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> axios.<span class="hljs-title function_">get</span>(<span class="hljs-string">'http://geek.itheima.net/v1_0/channels'</span>)<br> <span class="hljs-title function_">dispatch</span>(<span class="hljs-title function_">setChannels</span>(res.<span class="hljs-property">data</span>.<span class="hljs-property">data</span>.<span class="hljs-property">channels</span>))<br> }<br>}<br><br><span class="hljs-keyword">export</span> {fetchChannelList,setChannels}<br><span class="hljs-keyword">const</span> channelReducer = channelStore.<span class="hljs-property">reducer</span><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> channelReducer<br></code></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">//index.js</span><br><span class="hljs-keyword">import</span> { configureStore } <span class="hljs-keyword">from</span> <span class="hljs-string">"@reduxjs/toolkit"</span>;<br><span class="hljs-keyword">import</span> counterReducer <span class="hljs-keyword">from</span> <span class="hljs-string">"./modules/counterStore"</span>;<br><span class="hljs-keyword">import</span> channelReducer <span class="hljs-keyword">from</span> <span class="hljs-string">"./modules/channelStore"</span>;<br><span class="hljs-keyword">const</span> store = <span class="hljs-title function_">configureStore</span>({<br> <span class="hljs-attr">reducer</span>:{<br> <span class="hljs-attr">counter</span>:counterReducer,<br> <span class="hljs-attr">channel</span>:channelReducer,<br> }<br>})<br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> store<br></code></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">//App.jsx</span><br><span class="hljs-keyword">import</span> { useDispatch, useSelector } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span><br><span class="hljs-keyword">import</span> { decrement, increment,addToNum} <span class="hljs-keyword">from</span> <span class="hljs-string">"./store/modules/counterStore"</span><br><span class="hljs-keyword">import</span> { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span><br><span class="hljs-keyword">import</span> { fetchChannelList } <span class="hljs-keyword">from</span> <span class="hljs-string">"./store/modules/channelStore"</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br> <span class="hljs-keyword">const</span> {count} = <span class="hljs-title function_">useSelector</span>(<span class="hljs-function"><span class="hljs-params">state</span> =></span> state.<span class="hljs-property">counter</span>)<br> <span class="hljs-keyword">const</span> {channelList} = <span class="hljs-title function_">useSelector</span>(<span class="hljs-function"><span class="hljs-params">state</span> =></span> state.<span class="hljs-property">channel</span>)<br> <span class="hljs-keyword">const</span> dispatch = <span class="hljs-title function_">useDispatch</span>()<br> <span class="hljs-comment">// 使用useEffect触发异步</span><br> <span class="hljs-title function_">useEffect</span>(<span class="hljs-function">()=></span>{<br> <span class="hljs-title function_">dispatch</span>(<span class="hljs-title function_">fetchChannelList</span>())<br> },[dispatch])<br> <span class="hljs-keyword">return</span> (<br> <span class="language-xml"><span class="hljs-tag"><></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span>=></span>dispatch(decrement())}>-<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><span class="language-xml"> {count}</span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span>=></span>dispatch(increment())}>+<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span>=></span>dispatch(addToNum(20))}>+20<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">ul</span>></span></span><br><span class="language-xml"> {channelList.map(item=> <span class="hljs-tag"><<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span>></span>{item.name}<span class="hljs-tag"></<span class="hljs-name">li</span>></span>)}</span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">ul</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></></span></span><br> )<br>}<br></code></pre></td></tr></table></figure>
<h1 id="6-ReactRouter"><a href="#6-ReactRouter" class="headerlink" title="6.ReactRouter"></a>6.ReactRouter</h1><h2 id="ReactRouter应用"><a href="#ReactRouter应用" class="headerlink" title="ReactRouter应用"></a>ReactRouter应用</h2><h3 id="快速开始"><a href="#快速开始" class="headerlink" title="快速开始"></a>快速开始</h3><p><strong>前端路由</strong>:一个path对应一个组件component,当我们在浏览器中访问一个path时,path对应的组件会在页面中进行渲染</p>
<h4 id="创建路由开发环境"><a href="#创建路由开发环境" class="headerlink" title="创建路由开发环境"></a>创建路由开发环境</h4><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs powershell">npm create vite@latest<br>...<br>npm i react<span class="hljs-literal">-router-dom</span><br>...<br>npm run dev<br></code></pre></td></tr></table></figure>
<h4 id="基本实现"><a href="#基本实现" class="headerlink" title="基本实现"></a>基本实现</h4><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-comment">// 调包</span><br><span class="hljs-keyword">import</span> {createBrowserRouter ,<span class="hljs-title class_">RouterProvider</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span><br><br><span class="hljs-comment">// 1.创建Router实例对象,配置路由对应关系</span><br><span class="hljs-keyword">const</span> router = <span class="hljs-title function_">createBrowserRouter</span>([<br> {<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'/login'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span>我是登录<span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br> },<br> {<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'/article'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span>我是文章页<span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br> }<br>])<br><span class="hljs-comment">// 2.在渲染DOM中通过RouterProvider组件的router属性传入router对象</span><br><span class="hljs-title function_">createRoot</span>(<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">'root'</span>)).<span class="hljs-title function_">render</span>(<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">StrictMode</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">RouterProvider</span> <span class="hljs-attr">router</span>=<span class="hljs-string">{router}</span>></span></span><br><span class="language-xml"></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">RouterProvider</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">StrictMode</span>></span></span>,<br>)<br><br><br></code></pre></td></tr></table></figure>
<h3 id="抽象路由模块"><a href="#抽象路由模块" class="headerlink" title="抽象路由模块"></a>抽象路由模块</h3><p><strong>在实际工程项目中的配置:</strong></p>
<p><a target="_blank" rel="external nofollow noopener noreferrer" href="https://imgse.com/i/pEelZ6J"><img src="https://s21.ax1x.com/2025/02/05/pEelZ6J.png" srcset="/img/loading.gif" lazyload alt="ReactRouter配置"></a></p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><br><span class="hljs-comment">// ./router/index.js</span><br><br><span class="hljs-keyword">import</span> <span class="hljs-title class_">Login</span> <span class="hljs-keyword">from</span> <span class="hljs-string">"../page/login"</span>;<br><span class="hljs-keyword">import</span> <span class="hljs-title class_">Article</span> <span class="hljs-keyword">from</span> <span class="hljs-string">"../page/article"</span>;<br><br><span class="hljs-keyword">import</span> {createBrowserRouter} <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span><br><br><span class="hljs-keyword">const</span> router = <span class="hljs-title function_">createBrowserRouter</span>([{<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'/login'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Login</span>/></span></span>,<br>},<br>{<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'/article'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Article</span>/></span></span>,<br>}<br>])<br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> router<br><br><br></code></pre></td></tr></table></figure>
<p><strong>注意:</strong> </p>
<p>在router注册组件时,<strong>组件名一定要首字母大写!!!</strong></p>
<h3 id="路由导航跳转"><a href="#路由导航跳转" class="headerlink" title="路由导航跳转"></a>路由导航跳转</h3><p><strong>概念:</strong> 路由系统中的多个路由之间需要进行<em>路由跳转</em>,并且在跳转的同时有可能需要传递参数进行通信.</p>
<h4 id="声明式导航"><a href="#声明式导航" class="headerlink" title="声明式导航"></a>声明式导航</h4><p>在模板中通过<code><Link to=""/></code>组件描述要跳转的路由.</p>
<p>其中,<code>to=''</code>属性指定要跳转的路由path,也可使用模板字符串拼接.</p>
<h4 id="命令式导航"><a href="#命令式导航" class="headerlink" title="命令式导航"></a>命令式导航</h4><p>在模板中通过<code>useNavigate()</code>的hooks函数绑定在需要的DOM事件上.</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-comment">// ./page/login/index.jsx</span><br><br><br><span class="hljs-keyword">import</span> {<span class="hljs-title class_">Link</span>,useNavigate} <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">Login</span> = (<span class="hljs-params"></span>)=>{<br> <span class="hljs-keyword">const</span> navigate = <span class="hljs-title function_">useNavigate</span>()<br> <span class="hljs-keyword">return</span> (<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> {/* 声明式写法 调用Link组件 编译为超链接 */}</span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/article"</span>></span> 跳转到文章页<span class="hljs-tag"></<span class="hljs-name">Link</span>></span></span><br><span class="language-xml"> {/* 命令式写法 调用useNavigate的hooks函数 绑定在DOM的事件上 */}</span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =></span> navigate('/article')}>跳转到文章页<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><br> )<br>}<br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-title class_">Login</span><br><br><br></code></pre></td></tr></table></figure>
<h3 id="路由导航传参"><a href="#路由导航传参" class="headerlink" title="路由导航传参"></a>路由导航传参</h3><h4 id="searchParams传参"><a href="#searchParams传参" class="headerlink" title="searchParams传参"></a>searchParams传参</h4><p><strong>格式:</strong><code>/router?id=111&name=222</code></p>
<p>取参函数:<code>useSearchParams()</code></p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-comment">// login.jsx</span><br><button onClick={<span class="hljs-function">() =></span> <span class="hljs-title function_">navigate</span>(<span class="hljs-string">'/article?id=1001&name=jack'</span>)}>searchParams传参</button><br><br><span class="hljs-comment">//article.jsx</span><br><span class="hljs-keyword">const</span> [params] = <span class="hljs-title function_">useSearchParams</span>()<br> <span class="hljs-keyword">const</span> id = params.<span class="hljs-title function_">get</span>(<span class="hljs-string">'id'</span>)<br> <span class="hljs-keyword">const</span> name = params.<span class="hljs-title function_">get</span>(<span class="hljs-string">'name'</span>)<br></code></pre></td></tr></table></figure>
<h4 id="Params传参"><a href="#Params传参" class="headerlink" title="Params传参"></a>Params传参</h4><p><strong>格式:</strong><code>/router/:id/:name</code></p>
<p>取参函数:<code>useParams()</code></p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><br><span class="hljs-comment">// ./router/index.jsx</span><br><br><span class="hljs-keyword">const</span> router = <span class="hljs-title function_">createBrowserRouter</span>([<br>{<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'/article/:id/:name'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Article</span>/></span></span>,<br>}<br>])<br><br><span class="hljs-comment">//login.jsx</span><br><br><button onClick={<span class="hljs-function">() =></span> <span class="hljs-title function_">navigate</span>(<span class="hljs-string">'/article/1001/jack'</span>)}><span class="hljs-title class_">Params</span>传参</button><br><br><br><span class="hljs-comment">//article.jsx</span><br><span class="hljs-keyword">const</span> params = <span class="hljs-title function_">useParams</span>()<br><span class="hljs-keyword">const</span> id = params.<span class="hljs-property">id</span><br><span class="hljs-keyword">const</span> name = params.<span class="hljs-property">name</span><br> <span class="hljs-keyword">return</span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span>我是文章{id}-{name}<span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br>}<br><br><br><br></code></pre></td></tr></table></figure>
<p><strong>注意:</strong> 使用Params传参时,需要预先在路由文件下指定好匹配的对象名</p>
<h3 id="嵌套路由"><a href="#嵌套路由" class="headerlink" title="嵌套路由"></a>嵌套路由</h3><h4 id="什么是嵌套路由"><a href="#什么是嵌套路由" class="headerlink" title="什么是嵌套路由"></a>什么是嵌套路由</h4><p>在一级路由中嵌套其他路由,这种关系叫做嵌套路由.嵌套至一级路由内的路由称作二级路由</p>
<h4 id="嵌套路由配置"><a href="#嵌套路由配置" class="headerlink" title="嵌套路由配置"></a>嵌套路由配置</h4><p><strong>实现步骤</strong></p>
<ol>
<li><p>使用<code>children</code>属性</p>
</li>
<li><p>使用<code><Outlet/></code> 组件渲染二级路由渲染位置</p>
</li>
</ol>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><br><span class="hljs-comment">// ./router/index.jsx</span><br><span class="hljs-comment">// react路由组件注册</span><br><br><br><span class="hljs-keyword">const</span> router = <span class="hljs-title function_">createBrowserRouter</span>([{<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'/login'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Login</span>/></span></span>,<br>},<br>{<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'/article/:id'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Article</span>/></span></span>,<br>},{<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'/'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Layout</span> /></span></span>,<br> <span class="hljs-attr">children</span>:[<br> {<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'board'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Board</span>/></span></span><br> },<br> {<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'about'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">About</span> /></span></span><br> }<br> ]<br>}<br>])<br><br><span class="hljs-comment">// ./page/Layout/index.jsx</span><br><br><span class="hljs-keyword">import</span> { <span class="hljs-title class_">Link</span>, <span class="hljs-title class_">Outlet</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span><br><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">Layout</span> = (<span class="hljs-params"></span>) =>{<br> <span class="hljs-keyword">return</span>(<br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="language-xml"> 瓦塔西一级路由Layout组件</span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/board"</span>></span>面板1<span class="hljs-tag"></<span class="hljs-name">Link</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/about"</span>></span>关于<span class="hljs-tag"></<span class="hljs-name">Link</span>></span></span><br><span class="language-xml"> {/* 二级路由出口 */}</span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">Outlet</span>/></span></span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br> )<br>}<br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-title class_">Layout</span><br></code></pre></td></tr></table></figure>
<h3 id="默认二级路由"><a href="#默认二级路由" class="headerlink" title="默认二级路由"></a>默认二级路由</h3><h4 id="配置方式"><a href="#配置方式" class="headerlink" title="配置方式"></a>配置方式</h4><p>在二级路由的位置去掉<code>path</code>,设置<code>index</code>属性为<code>true</code></p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-comment">// ./router/index.jsx</span><br><br><br><span class="hljs-keyword">const</span> router = <span class="hljs-title function_">createBrowserRouter</span>([{<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'/login'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Login</span>/></span></span>,<br>},<br>{<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'/article/:id'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Article</span>/></span></span>,<br>},{<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'/'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Layout</span> /></span></span>,<br> <span class="hljs-attr">children</span>:[<br> <span class="hljs-comment">// 设置为默认二级路由</span><br> {<br> <span class="hljs-attr">index</span>: <span class="hljs-literal">true</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Board</span>/></span></span><br> },<br> {<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'about'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">About</span> /></span></span><br> }<br> ]<br>}<br>])<br></code></pre></td></tr></table></figure>
<h3 id="404路由"><a href="#404路由" class="headerlink" title="404路由"></a>404路由</h3><p>场景:找不到对应path时,提示404页面</p>
<p><strong>实现步骤:</strong> </p>
<ol>
<li><p>准备NotFound组件</p>
</li>
<li><p>在路由表尾注册<code>*</code>为path的路由</p>
</li>
</ol>
<p>形如:</p>
<p>`{</p>
<p> path:’*’,</p>
<p> element:<notfound></notfound></p>
<p>}`</p>
<h3 id="两种路由模式"><a href="#两种路由模式" class="headerlink" title="两种路由模式"></a>两种路由模式</h3><p>主流框架常见的路由方式有两种,<strong>history模式和hash模式</strong>.</p>
<p>在React中分别由<code>createBrowerRoute</code>和<code>createHsahRouter</code>函数负责创建</p>
<table>
<thead>
<tr>
<th>路由模式</th>
<th>url表现</th>
<th>底层原理</th>
<th>是否需要后端支持</th>
</tr>
</thead>
<tbody><tr>
<td>history</td>
<td>url/login</td>
<td>history对象+pushState事件</td>
<td>需要</td>
</tr>
<tr>
<td>hash</td>
<td>url/#/login</td>
<td>监听hashChange事件</td>
<td>不需要</td>
</tr>
</tbody></table>
<h1 id="7-项目实战-记账本"><a href="#7-项目实战-记账本" class="headerlink" title="7.项目实战-记账本"></a>7.项目实战-记账本</h1><h2 id="项目初始化"><a href="#项目初始化" class="headerlink" title="项目初始化"></a>项目初始化</h2><h3 id="项目依赖安装"><a href="#项目依赖安装" class="headerlink" title="项目依赖安装"></a>项目依赖安装</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs npmignore">npm create vite@latest<br>...<br>npm i react-router-dom dayjs classnames antd-mobile axios<br></code></pre></td></tr></table></figure>
<h3 id="git提交"><a href="#git提交" class="headerlink" title="git提交"></a>git提交</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs git">git init<br>// 仓库初始化<br>git add .<br>// 仓库更新<br>git commit -m ""<br>// 仓库提交 -m后跟提交内容的备注<br></code></pre></td></tr></table></figure>
<h3 id="Vite实现配置别名路径"><a href="#Vite实现配置别名路径" class="headerlink" title="Vite实现配置别名路径"></a>Vite实现配置别名路径</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'vite'</span><br><span class="hljs-keyword">import</span> path <span class="hljs-keyword">from</span> <span class="hljs-string">'path'</span><br><span class="hljs-keyword">import</span> react <span class="hljs-keyword">from</span> <span class="hljs-string">'@vitejs/plugin-react'</span><br><br><span class="hljs-comment">// https://vite.dev/config/</span><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-title function_">defineConfig</span>({<br> <span class="hljs-attr">plugins</span>: [<span class="hljs-title function_">react</span>()],<br> <span class="hljs-attr">resolve</span>:{<br> <span class="hljs-attr">alias</span>:{<br> <span class="hljs-comment">// eslint-disable-next-line no-undef</span><br> <span class="hljs-string">'@'</span>: path.<span class="hljs-title function_">resolve</span>(__dirname,<span class="hljs-string">'src'</span>),<br> },<br> },<br>})<br><br></code></pre></td></tr></table></figure>
<h3 id="VS-Code配置别名路径高亮"><a href="#VS-Code配置别名路径高亮" class="headerlink" title="VS Code配置别名路径高亮"></a>VS Code配置别名路径高亮</h3><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-comment">// ./jsconfig.json</span><br><span class="hljs-punctuation">{</span><br> <span class="hljs-attr">"compilerOptions"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span><br> <span class="hljs-attr">"target"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"ES6"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">"jsx"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"react"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-comment">// 基础目录作为项目根目录, 这应该指向包含 `src` 目录的路径</span><br> <span class="hljs-attr">"baseUrl"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"./"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">"paths"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span><br> <span class="hljs-comment">// @ 作为 src目录别名</span><br> <span class="hljs-attr">"@/*"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"src/*"</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span> <span class="hljs-comment">// VS Code 将 `@` 解析为 `src` 目录</span><br><br> <span class="hljs-punctuation">}</span><br> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">"exclude"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"node_modules"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"dist"</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span> <span class="hljs-comment">// "...其他要排除的目录"</span><br> <span class="hljs-attr">"include"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"src/**/*"</span><span class="hljs-punctuation">]</span><br> <span class="hljs-punctuation">}</span><br><br></code></pre></td></tr></table></figure>
<h3 id="数据Mock"><a href="#数据Mock" class="headerlink" title="数据Mock"></a>数据Mock</h3><p>数据Mock是指通过模拟真实数据来测试系统功能,确保系统在无真实数据或无法获取真实数据时仍能正常运行。Mock数据通常用于开发、测试和演示,帮助开发者在早期阶段验证逻辑和接口。</p>
<h4 id="在前端开发中常见的数据Mock种类"><a href="#在前端开发中常见的数据Mock种类" class="headerlink" title="在前端开发中常见的数据Mock种类"></a>在前端开发中常见的数据Mock种类</h4><ol>
<li><p><strong>静态Mock数据</strong>:</p>
<ul>
<li><p>预先定义好的固定数据,通常存储在JSON、XML或CSV文件中。</p>
</li>
<li><p>适用于简单的测试场景。</p>
</li>
</ul>
</li>
<li><p><strong>动态Mock数据</strong>:</p>
<ul>
<li><p>在运行时生成的数据,模拟真实数据的动态变化。</p>
</li>
<li><p>适用于复杂场景,如模拟用户行为或实时数据流。</p>
</li>
</ul>
</li>
<li><p><strong>接口Mock</strong>:</p>
<ul>
<li><p>模拟API接口的响应,用于测试API调用。</p>
</li>
<li><p>适用于前后端分离开发或第三方API不可用时的测试。</p>
</li>
</ul>
</li>
</ol>
<h4 id="在前端开发中常见的Mock工具"><a href="#在前端开发中常见的Mock工具" class="headerlink" title="在前端开发中常见的Mock工具"></a>在前端开发中常见的Mock工具</h4><ol>
<li><p><strong>静态Mock数据工具</strong>:</p>
<ul>
<li><p><strong>JSON Server</strong>:基于JSON文件的REST API模拟工具,可以快速搭建一个本地的Mock服务器。</p>
</li>
<li><p><strong>Faker.js</strong>:生成虚假数据的JavaScript库,可以生成各种类型的虚假数据,如姓名、地址、电话号码等。</p>
</li>
</ul>
</li>
<li><p><strong>动态Mock数据工具</strong>:</p>
<ul>
<li><p><strong>Mock.js</strong>:生成随机数据的JavaScript库,支持生成各种类型的随机数据,并且可以定义数据模板。</p>
</li>
<li><p><strong>Faker</strong>(Python):生成虚假数据的Python库,适用于需要在Python环境中生成Mock数据的场景。</p>
</li>
</ul>
</li>
<li><p><strong>接口Mock工具</strong>:</p>
<ul>
<li><p><strong>Postman Mock Server</strong>:Postman提供的API模拟服务,可以快速创建Mock服务器并定义API响应。</p>
</li>
<li><p><strong>WireMock</strong>:用于HTTP API的模拟工具,支持Java,适用于需要在Java环境中进行API Mock的场景。</p>
</li>
</ul>
</li>
</ol>
<h4 id="配置json-server"><a href="#配置json-server" class="headerlink" title="配置json-server"></a>配置json-server</h4><ol>
<li><p><strong>在项目中安装json-server</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs npmignore">npm i -D json-server<br></code></pre></td></tr></table></figure>
</li>
<li><p>准备json文件</p>
</li>
<li><p>添加启动命令</p>
</li>
<li><p>访问接口并调试</p>
</li>
</ol>
<h3 id="整体路由设计"><a href="#整体路由设计" class="headerlink" title="整体路由设计"></a>整体路由设计</h3><p><a target="_blank" rel="external nofollow noopener noreferrer" href="https://imgse.com/i/pEnJsw4"><img src="https://s21.ax1x.com/2025/02/10/pEnJsw4.png" srcset="/img/loading.gif" lazyload alt="pEnJsw4.png"></a></p>
<ol>
<li><p>2个一级路由(Layout/New)</p>
</li>
<li><p>2个二级路由(Layout-month/year)</p>
</li>
</ol>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><span class="hljs-comment">// @/router/index.jsx</span><br><span class="hljs-comment">// 创建路由实例</span><br><br><span class="hljs-keyword">import</span> <span class="hljs-title class_">Layout</span> <span class="hljs-keyword">from</span> <span class="hljs-string">'@/pages/Layout/index'</span><br><span class="hljs-keyword">import</span> <span class="hljs-title class_">Month</span> <span class="hljs-keyword">from</span> <span class="hljs-string">'@/pages/Month/index'</span><br><span class="hljs-keyword">import</span> <span class="hljs-title class_">New</span> <span class="hljs-keyword">from</span> <span class="hljs-string">'@/pages/New/index'</span><br><span class="hljs-keyword">import</span> <span class="hljs-title class_">Year</span> <span class="hljs-keyword">from</span> <span class="hljs-string">'@/pages/Year/index'</span><br><span class="hljs-keyword">import</span> {createBrowserRouter} <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span><br><br><span class="hljs-keyword">const</span> router = <span class="hljs-title function_">createBrowserRouter</span>([{<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'/'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Layout</span>/></span></span>,<br> <span class="hljs-attr">children</span>:[<br> {<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'month'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Month</span>/></span></span><br> },<br> {<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'year'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Year</span>/></span></span><br> }<br> ]<br>},{<br> <span class="hljs-attr">path</span>:<span class="hljs-string">'/new'</span>,<br> <span class="hljs-attr">element</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">New</span>/></span></span><br>}<br>])<br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> router<br><br><br></code></pre></td></tr></table></figure>
<h3 id="antD-mobile主题定制"><a href="#antD-mobile主题定制" class="headerlink" title="antD-mobile主题定制"></a>antD-mobile主题定制</h3><p><strong>定制方案:</strong></p>
<ol>
<li><p>全局定制</p>
</li>
<li><p>局部定制</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><div className=<span class="hljs-string">"purple-theme"</span>><br> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Button</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"primary"</span>></span>局部测试<span class="hljs-tag"></<span class="hljs-name">Button</span>></span></span><br></div><br><span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Button</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"primary"</span>></span>测试<span class="hljs-tag"></<span class="hljs-name">Button</span>></span></span><br></code></pre></td></tr></table></figure></li>
</ol>
<h1 id="Zustand"><a href="#Zustand" class="headerlink" title="Zustand"></a>Zustand</h1><h2 id="Zustand快速上手"><a href="#Zustand快速上手" class="headerlink" title="Zustand快速上手"></a>Zustand快速上手</h2><h3 id="创建store"><a href="#创建store" class="headerlink" title="创建store"></a>创建store</h3><p><strong>语法:</strong> <code>const useStore = create((set)=>{return{...})</code></p>
<h3 id="创建状态方法:"><a href="#创建状态方法:" class="headerlink" title="创建状态方法:"></a>创建状态方法:</h3><p><strong>语法:</strong><code>action:()=>{set((state)=>({count:state.count + 1}))}</code></p>
<p><strong>注意:</strong></p>
<ol>
<li><p>函数参数必须返回一个对象 对象内部编写状态数据和方法</p>
</li>
<li><p>set是用来修改数据的专门方法,必须调用它来修改数据<br>语法1:参数是函数 需要使用老数据 需要用箭头函数的块内操作<br><code>set((state)=>({count:state.count + 1}))</code><br>语法2:参数直接是一个对象<br><code>set({count:100})</code></p>
</li>
</ol>
<h3 id="zustand-异步支持"><a href="#zustand-异步支持" class="headerlink" title="zustand-异步支持"></a>zustand-异步支持</h3><p>对于异步的支持不需要特殊的操作,直接在函数中编写异步逻辑,最后调用set方法传入新状态即可,记得解构并在主函数中使用useEffect调起该异步方法</p>
<h3 id="zustand-切片模式"><a href="#zustand-切片模式" class="headerlink" title="zustand-切片模式"></a>zustand-切片模式</h3><p>当单个store较大时,可以采用<strong>切片模式</strong>组合各个模块</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">createCounterStore</span> = (<span class="hljs-params">set</span>) => {<br> <span class="hljs-keyword">return</span> {<br> <span class="hljs-comment">// 状态数据</span><br> <span class="hljs-attr">count</span>: <span class="hljs-number">0</span>,<br> <span class="hljs-comment">// 修改状态数据的方法</span><br> <span class="hljs-attr">inc</span>: <span class="hljs-function">() =></span> {<br> <span class="hljs-title function_">set</span>(<span class="hljs-function">(<span class="hljs-params">state</span>) =></span> ({ <span class="hljs-attr">count</span>: state.<span class="hljs-property">count</span> + <span class="hljs-number">1</span> }))<br> },<br> }<br>}<br><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">createChannelStore</span> = (<span class="hljs-params">set</span>) => {<br> <span class="hljs-keyword">return</span> {<br> <span class="hljs-attr">channelList</span>: [],<br> <span class="hljs-attr">fetchGetList</span>: <span class="hljs-title function_">async</span> () => {<br> <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> <span class="hljs-title function_">fetch</span>(<span class="hljs-variable constant_">URL</span>)<br> <span class="hljs-keyword">const</span> jsonRes = <span class="hljs-keyword">await</span> res.<span class="hljs-title function_">json</span>()<br> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(jsonRes)<br> <span class="hljs-title function_">set</span>({<br> <span class="hljs-attr">channelList</span>: jsonRes.<span class="hljs-property">data</span>.<span class="hljs-property">channels</span><br> })<br> }<br> }<br>}<br><br><span class="hljs-keyword">const</span> useStore = <span class="hljs-title function_">create</span>(<span class="hljs-function">(<span class="hljs-params">...a</span>) =></span> {<br> <span class="hljs-keyword">return</span> {<br> ...<span class="hljs-title function_">createCounterStore</span>(...a),<br> ...<span class="hljs-title function_">createChannelStore</span>(...a)<br> }<br>})<br><br><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span> (<span class="hljs-params"></span>) {<br> <span class="hljs-comment">// 2. 组件使用</span><br> <span class="hljs-keyword">const</span> { count, inc, fetchGetList, channelList } = <span class="hljs-title function_">useStore</span>()<br> <span class="hljs-title function_">useEffect</span>(<span class="hljs-function">() =></span> {<br> <span class="hljs-title function_">fetchGetList</span>()<br> }, [fetchGetList])<br> <span class="hljs-keyword">return</span> (<br> <span class="language-xml"><span class="hljs-tag"><></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{inc}</span>></span>{count}<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">ul</span>></span></span><br><span class="language-xml"> {</span><br><span class="language-xml"> channelList.map(item => <span class="hljs-tag"><<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span>></span>{item.name}<span class="hljs-tag"></<span class="hljs-name">li</span>></span>)</span><br><span class="language-xml"> }</span><br><span class="language-xml"> <span class="hljs-tag"></<span class="hljs-name">ul</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></></span></span><br> )<br>}<br><br></code></pre></td></tr></table></figure>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs jsx"><br><br><span class="hljs-keyword">import</span> {create} <span class="hljs-keyword">from</span> <span class="hljs-string">'zustand'</span><br><span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span><br><span class="hljs-comment">// 创建store</span><br><span class="hljs-keyword">const</span> useStore = <span class="hljs-title function_">create</span>(<span class="hljs-function">(<span class="hljs-params">set</span>)=></span>{<br> <span class="hljs-keyword">return</span> {<br> <span class="hljs-attr">count</span>:<span class="hljs-number">0</span>,<br> <span class="hljs-attr">inc</span>:<span class="hljs-function">() =></span>{<br> <span class="hljs-title function_">set</span>(<span class="hljs-function">(<span class="hljs-params">state</span>)=></span>({<br> <span class="hljs-attr">count</span>: state.<span class="hljs-property">count</span> + <span class="hljs-number">1</span><br> }))<br> }<br> }<br>})<br><br><br><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br><br> <span class="hljs-keyword">const</span> {count,inc} = <span class="hljs-title function_">useStore</span>()<br> <span class="hljs-keyword">return</span> (<br> <span class="language-xml"><span class="hljs-tag"><></span></span><br><span class="language-xml"> This is app.</span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{inc}</span>></span>{count}<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></></span></span><br> )<br>}<br></code></pre></td></tr></table></figure>
<h1 id="React-TS"><a href="#React-TS" class="headerlink" title="React+TS"></a>React+TS</h1><h2 id="创建项目"><a href="#创建项目" class="headerlink" title="创建项目"></a>创建项目</h2><h3 id="使用Vite创建TS的React项目"><a href="#使用Vite创建TS的React项目" class="headerlink" title="使用Vite创建TS的React项目"></a>使用Vite创建TS的React项目</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm create vite@latest my-vue-app -- --template react-ts<br>npm install<br>npm run dev<br></code></pre></td></tr></table></figure>
<h2 id="useState与TS"><a href="#useState与TS" class="headerlink" title="useState与TS"></a>useState与TS</h2><h3 id="useState-自动推导"><a href="#useState-自动推导" class="headerlink" title="useState-自动推导"></a>useState-自动推导</h3><p>通常React会根据传入的useState的默认值来自动推导类型,并不需要显式标注类型</p>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><br><span class="hljs-keyword">const</span> [value,toogle] = <span class="hljs-title function_">useState</span>(<span class="hljs-literal">false</span>)<br><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">changeValue</span> = (<span class="hljs-params"></span>) =>{<br> <span class="hljs-title function_">toogle</span>(<span class="hljs-literal">true</span>)<br> }<br></code></pre></td></tr></table></figure>
<h3 id="useState-传递泛型参数"><a href="#useState-传递泛型参数" class="headerlink" title="useState- 传递泛型参数"></a>useState- 传递泛型参数</h3><p>useState本身是一个泛型函数,可以传入具体的自定义类型。</p>
<blockquote>
<p><strong>关于泛型的含义:</strong> <a target="_blank" rel="external nofollow noopener noreferrer" href="https://typescript.p6p.net/typescript-tutorial/generics.html">TypeScript 泛型</a></p>
<p><a target="_blank" rel="external nofollow noopener noreferrer" href="https://www.runoob.com/typescript/ts-generics.html">TypeScript 泛型 | 菜鸟教程</a></p>
<p><strong>简单来说:</strong> 泛型(Generics)是一种编程语言特性,允许在定义函数、类、接口等时使用占位符来表示类型,而不是具体的类型。</p>
<p><strong>泛型函数:</strong></p>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><span class="hljs-keyword">function</span> identity<T>(<span class="hljs-attr">arg</span>: T): T {<br> <span class="hljs-keyword">return</span> arg;<br>}<br><br><span class="hljs-comment">// 使用泛型函数</span><br><span class="hljs-keyword">let</span> result = identity<<span class="hljs-built_in">string</span>>(<span class="hljs-string">"Hello"</span>);<br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(result); <span class="hljs-comment">// 输出: Hello</span><br><br><span class="hljs-keyword">let</span> numberResult = identity<<span class="hljs-built_in">number</span>>(<span class="hljs-number">42</span>);<br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(numberResult); <span class="hljs-comment">// 输出: 42</span><br></code></pre></td></tr></table></figure>
<p><strong>泛型接口:</strong></p>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><span class="hljs-comment">// 基本语法</span><br><span class="hljs-keyword">interface</span> <span class="hljs-title class_">Pair</span><T, U> {<br> <span class="hljs-attr">first</span>: T;<br> <span class="hljs-attr">second</span>: U;<br>}<br><br><span class="hljs-comment">// 使用泛型接口</span><br><span class="hljs-keyword">let</span> <span class="hljs-attr">pair</span>: <span class="hljs-title class_">Pair</span><<span class="hljs-built_in">string</span>, <span class="hljs-built_in">number</span>> = { <span class="hljs-attr">first</span>: <span class="hljs-string">"hello"</span>, <span class="hljs-attr">second</span>: <span class="hljs-number">42</span> };<br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(pair); <span class="hljs-comment">// 输出: { first: 'hello', second: 42 }</span><br></code></pre></td></tr></table></figure>
<p><strong>泛型类:</strong></p>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><span class="hljs-comment">// 基本语法</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Box</span><T> {<br> <span class="hljs-keyword">private</span> <span class="hljs-attr">value</span>: T;<br><br> <span class="hljs-title function_">constructor</span>(<span class="hljs-params"><span class="hljs-attr">value</span>: T</span>) {<br> <span class="hljs-variable language_">this</span>.<span class="hljs-property">value</span> = value;<br> }<br><br> <span class="hljs-title function_">getValue</span>(): T {<br> <span class="hljs-keyword">return</span> <span class="hljs-variable language_">this</span>.<span class="hljs-property">value</span>;<br> }<br>}<br><br><span class="hljs-comment">// 使用泛型类</span><br><span class="hljs-keyword">let</span> stringBox = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Box</span><<span class="hljs-built_in">string</span>>(<span class="hljs-string">"TypeScript"</span>);<br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(stringBox.<span class="hljs-title function_">getValue</span>()); <span class="hljs-comment">// 输出: TypeScript</span><br></code></pre></td></tr></table></figure></blockquote>
<p><strong>说明:</strong></p>
<ol>
<li><p>限制useState函数参数的初始值类型必须满足<code>User | () => User</code></p>
</li>
<li><p>限制setUser函数的参数必须满足类型为<code>User | () => User | undefined</code></p>
</li>
<li><p>User状态数据必须具备User类型相关的类型提示</p>
</li>
<li><p>若不知道状态变量的初始值,可设置为null</p>
</li>
</ol>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><br><span class="hljs-keyword">type</span> <span class="hljs-title class_">User</span> = {<br> <span class="hljs-attr">name</span>:<span class="hljs-title class_">String</span><br> <span class="hljs-attr">age</span>:<span class="hljs-built_in">number</span><br> }<br><br> <span class="hljs-keyword">const</span> [user,setUser] = useState<<span class="hljs-title class_">User</span>>(<br> {<br> <span class="hljs-attr">name</span>:<span class="hljs-string">'Jack'</span>,<br> <span class="hljs-attr">age</span>:<span class="hljs-number">12</span><br> }<br> )<br> <span class="hljs-keyword">const</span> [users,setUsers] = useState<<span class="hljs-title class_">User</span>| <span class="hljs-literal">null</span>>(<span class="hljs-literal">null</span>)<br><br><br></code></pre></td></tr></table></figure>
<h2 id="props与TypeScript"><a href="#props与TypeScript" class="headerlink" title="props与TypeScript"></a>props与TypeScript</h2><h3 id="props-基础使用"><a href="#props-基础使用" class="headerlink" title="props - 基础使用"></a>props - 基础使用</h3><p>为组件prop添加类型,本质上是个函数的参数做<strong>类型注解</strong>,可以使用<strong>type</strong>对象类型或者<strong>interface</strong>接口来做注解</p>
<blockquote>
<p><strong>关于interface接口:</strong></p>
<p><a target="_blank" rel="external nofollow noopener noreferrer" href="https://www.runoob.com/typescript/ts-interface.html">TypeScript 接口 | 菜鸟教程</a></p>
<p><a target="_blank" rel="external nofollow noopener noreferrer" href="https://typescript.p6p.net/typescript-tutorial/interface.html">TypeScript 的 interface 接口 </a></p>
<p>interface 是对象的模板,可以看作是一种类型约定,中文译为“接口”。使用了某个模板的对象,就拥有了指定的类型结构。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">interface</span> <span class="hljs-title class_">Person</span> {<br> <span class="hljs-attr">firstName</span>: <span class="hljs-built_in">string</span>;<br> <span class="hljs-attr">lastName</span>: <span class="hljs-built_in">string</span>;<br> <span class="hljs-attr">age</span>: <span class="hljs-built_in">number</span>;<br>}<br></code></pre></td></tr></table></figure>
<p><strong>关于type类型:</strong></p>
<p><a target="_blank" rel="external nofollow noopener noreferrer" href="https://typescript.p6p.net/typescript-tutorial/types.html">TypeScript 的类型系统</a></p>
<p><code>type</code>命令用来定义一个类型的别名。别名可以让类型的名字变得更有意义,也能增加代码的可读性,还可以使复杂类型用起来更方便,便于以后修改变量的类型。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">type</span> <span class="hljs-title class_">Age</span> = <span class="hljs-built_in">number</span>;<br><span class="hljs-keyword">let</span> <span class="hljs-attr">age</span>: <span class="hljs-title class_">Age</span> = <span class="hljs-number">55</span>;<br></code></pre></td></tr></table></figure>
<p> 主要区别如下:</p>
<hr>
<h3 id="1-声明合并(Declaration-Merging)"><a href="#1-声明合并(Declaration-Merging)" class="headerlink" title="1. 声明合并(Declaration Merging)"></a>1. <strong>声明合并(Declaration Merging)</strong></h3><ul>
<li><p><strong><code>interface</code></strong>:支持声明合并。同一个名称的多个 <code>interface</code> 会自动合并。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">interface</span> <span class="hljs-title class_">User</span> { <span class="hljs-attr">name</span>: <span class="hljs-built_in">string</span>; }<br><span class="hljs-keyword">interface</span> <span class="hljs-title class_">User</span> { <span class="hljs-attr">age</span>: <span class="hljs-built_in">number</span>; }<br><span class="hljs-comment">// 合并为 { name: string; age: number; }</span><br></code></pre></td></tr></table></figure>
</li>
<li><p><strong><code>type</code></strong>:不支持声明合并。同名 <code>type</code> 会报错。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">type</span> <span class="hljs-title class_">User</span> = { <span class="hljs-attr">name</span>: <span class="hljs-built_in">string</span>; }; <br><span class="hljs-keyword">type</span> <span class="hljs-title class_">User</span> = { <span class="hljs-attr">age</span>: <span class="hljs-built_in">number</span>; }; <span class="hljs-comment">// Error: Duplicate identifier 'User'.</span><br></code></pre></td></tr></table></figure></li>
</ul>
<hr>
<h3 id="2-扩展方式"><a href="#2-扩展方式" class="headerlink" title="2. 扩展方式"></a>2. <strong>扩展方式</strong></h3><ul>
<li><p><strong><code>interface</code></strong>:用 <code>extends</code> 继承其他接口或对象类型。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">interface</span> A { <span class="hljs-attr">x</span>: <span class="hljs-built_in">number</span>; }<br><span class="hljs-keyword">interface</span> B <span class="hljs-keyword">extends</span> A { <span class="hljs-attr">y</span>: <span class="hljs-built_in">string</span>; }<br></code></pre></td></tr></table></figure>
</li>
<li><p><strong><code>type</code></strong>:用 <code>&</code> 交叉类型扩展。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">type</span> A = { <span class="hljs-attr">x</span>: <span class="hljs-built_in">number</span>; };<br><span class="hljs-keyword">type</span> B = A & { <span class="hljs-attr">y</span>: <span class="hljs-built_in">string</span>; };<br></code></pre></td></tr></table></figure></li>
</ul>
<hr>
<h3 id="3-灵活性"><a href="#3-灵活性" class="headerlink" title="3. 灵活性"></a>3. <strong>灵活性</strong></h3><ul>
<li><p><strong><code>interface</code></strong>:只能定义对象类型(包括函数、类等)。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">interface</span> <span class="hljs-title class_">User</span> { <span class="hljs-attr">name</span>: <span class="hljs-built_in">string</span>; }<br><span class="hljs-keyword">interface</span> <span class="hljs-title class_">Func</span> { (<span class="hljs-attr">x</span>: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">void</span>; }<br></code></pre></td></tr></table></figure>
</li>
<li><p><strong><code>type</code></strong>:可以定义任意类型,包括原始类型、联合类型、元组等。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">type</span> <span class="hljs-title class_">Name</span> = <span class="hljs-built_in">string</span>; <span class="hljs-comment">// 原始类型</span><br><span class="hljs-keyword">type</span> <span class="hljs-title class_">Value</span> = <span class="hljs-built_in">string</span> | <span class="hljs-built_in">number</span>; <span class="hljs-comment">// 联合类型</span><br><span class="hljs-keyword">type</span> <span class="hljs-title class_">Point</span> = [<span class="hljs-built_in">number</span>, <span class="hljs-built_in">number</span>]; <span class="hljs-comment">// 元组</span><br></code></pre></td></tr></table></figure></li>
</ul>
<hr>
<h3 id="4-性能与工具提示"><a href="#4-性能与工具提示" class="headerlink" title="4. 性能与工具提示"></a>4. <strong>性能与工具提示</strong></h3><ul>
<li><strong>工具提示(IntelliSense)</strong>:<br><code>interface</code> 在 VS Code 等工具中的提示更清晰(显示为 <code>interface</code>),而 <code>type</code> 会直接展开具体类型。</li>
<li><strong>性能</strong>:<br>对于复杂类型,<code>interface</code> 的检查可能略快(但实际差异很小)。</li>
</ul>
<hr>
<h3 id="5-类实现(implements)"><a href="#5-类实现(implements)" class="headerlink" title="5. 类实现(implements)"></a>5. <strong>类实现(<code>implements</code>)</strong></h3><ul>
<li><p><strong><code>interface</code></strong>:可以被类直接 <code>implements</code>。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">interface</span> <span class="hljs-title class_">IUser</span> { <span class="hljs-attr">name</span>: <span class="hljs-built_in">string</span>; }<br><span class="hljs-keyword">class</span> <span class="hljs-title class_">User</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">IUser</span> { <span class="hljs-attr">name</span>: <span class="hljs-built_in">string</span>; }<br></code></pre></td></tr></table></figure>
</li>
<li><p><strong><code>type</code></strong>:如果 <code>type</code> 是对象类型,类也可以实现它。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">type</span> <span class="hljs-title class_">TUser</span> = { <span class="hljs-attr">name</span>: <span class="hljs-built_in">string</span>; };<br><span class="hljs-keyword">class</span> <span class="hljs-title class_">User</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">TUser</span> { <span class="hljs-attr">name</span>: <span class="hljs-built_in">string</span>; }<br></code></pre></td></tr></table></figure></li>
</ul>
<hr>
<h3 id="何时用哪个?"><a href="#何时用哪个?" class="headerlink" title="何时用哪个?"></a>何时用哪个?</h3><ul>
<li><strong>用 <code>interface</code></strong>: <ul>
<li>需要声明合并(如扩展第三方库类型)。 </li>
<li>定义对象类型且需要清晰的工具提示。 </li>
<li>面向对象的类结构(<code>implements</code>)。</li>
</ul>
</li>
<li><strong>用 <code>type</code></strong>: <ul>
<li>需要联合类型、元组、映射类型等高级功能。 </li>
<li>定义非对象类型(如 <code>type Status = "open" | "closed"</code>)。</li>
</ul>
</li>
</ul>
<hr>
<h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>两者功能高度重叠,但 <code>interface</code> 更适合对象类型的扩展,而 <code>type</code> 更灵活。大型项目推荐优先用 <code>interface</code>,需要复杂类型时再用 <code>type</code>。</p>
</blockquote>
<p><strong>注意:</strong> 对于children这种比较特殊的prop,若需要传入多种不同的数据类型,可以通过内置的<code>React.ReactNode</code>类型注解</p>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br> <span class="hljs-keyword">type</span> <span class="hljs-title class_">Props</span> = {<br> className :<span class="hljs-built_in">string</span><br> <span class="hljs-attr">children</span>: <span class="hljs-title class_">React</span>.<span class="hljs-property">ReactNode</span><br> }<br><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">Button</span>(<span class="hljs-params"><span class="hljs-attr">props</span>:<span class="hljs-title class_">Props</span></span>)<br>{<br> <span class="hljs-keyword">const</span> {className,children} = props<br> <span class="hljs-keyword">return</span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{className}</span>></span>{children}<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br>}<br><br> <span class="hljs-keyword">return</span> (<br> <span class="language-xml"><span class="hljs-tag"><></span></span><br><span class="language-xml"> This is an app.</span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">Button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"Test"</span>></span>Click Me<span class="hljs-tag"></<span class="hljs-name">Button</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></></span></span><br> )<br>}<br><br></code></pre></td></tr></table></figure>
<h3 id="props-组件props注解"><a href="#props-组件props注解" class="headerlink" title="props - 组件props注解"></a>props - 组件props注解</h3><p>组件经常执行类型为函数的prop实现父传子,这类prop重点在于函数参数类型的注解</p>
<p>一般绑定事件时,事件函数的命名规范是 <strong>“on”+驼峰命名法</strong></p>
<p>在调用组件时,将触发事件绑定到组件的props上时,可以选择内联或函数的方式绑定,若单独定义函数,须对单独匹配参数类型。</p>
<p><strong>注意:</strong></p>
<ol>
<li><p>在组件内部调用时需要遵守类型约束,参数传递需要满足要求</p>
</li>
<li><p>绑定prop时如果绑定内联函数,可以直接推断出数据类型,否则需要单独注解匹配参数类型。</p>
</li>
</ol>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><span class="hljs-keyword">type</span> <span class="hljs-title class_">Props</span> = {<br> <span class="hljs-attr">className</span>?:<span class="hljs-built_in">string</span><br> <span class="hljs-attr">children</span>?: <span class="hljs-title class_">React</span>.<span class="hljs-property">ReactNode</span><br> <span class="hljs-attr">onGetMsg</span>?: <span class="hljs-function">(<span class="hljs-params"><span class="hljs-attr">msg</span>:<span class="hljs-built_in">string</span></span>)=></span><span class="hljs-built_in">void</span><br>}<br><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">Button</span>(<span class="hljs-params"><span class="hljs-attr">props</span>:<span class="hljs-title class_">Props</span></span>)<br>{<br> <span class="hljs-keyword">const</span> {className,children} = props<br> <span class="hljs-keyword">return</span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{className}</span>></span>{children}<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br>}<br><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">Son</span>(<span class="hljs-params"><span class="hljs-attr">props</span>:<span class="hljs-title class_">Props</span></span>){<br> <span class="hljs-keyword">const</span> {onGetMsg} = props<br> <span class="hljs-keyword">const</span> <span class="hljs-title function_">clickHandler</span> = (<span class="hljs-params"></span>) =>{<br> onGetMsg?.(<span class="hljs-string">'This is a msg'</span>)<br> }<br> <span class="hljs-keyword">return</span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{clickHandler}</span>></span>Click Me<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><br>}<br><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br> <span class="hljs-keyword">const</span> <span class="hljs-title function_">getMsgHandler</span> = (<span class="hljs-params"><span class="hljs-attr">msg</span>:<span class="hljs-built_in">string</span></span>) =>{<br> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(msg)<br> }<br><br> <span class="hljs-keyword">return</span> (<br> <span class="language-xml"><span class="hljs-tag"><></span></span><br><span class="language-xml"> This is an app.</span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">Button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"Test"</span>></span>Click Me<span class="hljs-tag"></<span class="hljs-name">Button</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">Son</span> <span class="hljs-attr">onGetMsg</span>=<span class="hljs-string">{getMsgHandler}</span> /></span></span><br><span class="language-xml"> <span class="hljs-tag"></></span></span><br> )<br>}<br><br></code></pre></td></tr></table></figure>
<h2 id="useRef与TypeScript"><a href="#useRef与TypeScript" class="headerlink" title="useRef与TypeScript"></a>useRef与TypeScript</h2><h3 id="useRef-获取DOM"><a href="#useRef-获取DOM" class="headerlink" title="useRef - 获取DOM"></a>useRef - 获取DOM</h3><p>获取dom的场景,可以直接把要获取的dom元素的类型当成泛型参数传递给useRef,可以推导出.current属性的类型</p>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) {<br><br> <span class="hljs-keyword">const</span> domRef = useRef<<span class="hljs-title class_">HTMLInputElement</span>>(<span class="hljs-literal">null</span>)<br><br> <span class="hljs-title function_">useEffect</span>(<span class="hljs-function">()=></span>{<br> <span class="hljs-comment">// 可选链 前面值不为空(null/ undefined)执行链式调用</span><br> domRef.<span class="hljs-property">current</span>?.<span class="hljs-title function_">focus</span>()<br> },[])<br><br> <span class="hljs-keyword">return</span> (<br> <span class="language-xml"><span class="hljs-tag"><></span></span><br><span class="language-xml"> This is an app.</span><br><span class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">input</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{domRef}</span>></span>Input<span class="hljs-tag"></<span class="hljs-name">input</span>></span></span><br><span class="language-xml"> <span class="hljs-tag"></></span></span><br> )<br>}<br></code></pre></td></tr></table></figure>
<h3 id="useRef-引用稳定的储存器"><a href="#useRef-引用稳定的储存器" class="headerlink" title="useRef - 引用稳定的储存器"></a>useRef - 引用稳定的储存器</h3><p>把useRef当成引用稳定的储存器使用的场景,可以通过泛型传入联合类型来做。</p>
<h1 id="React理论和设计思想"><a href="#React理论和设计思想" class="headerlink" title="React理论和设计思想"></a>React理论和设计思想</h1><h2 id="Babel-SWC"><a href="#Babel-SWC" class="headerlink" title="Babel & SWC"></a>Babel & SWC</h2><h3 id="使用babel编译JS-JSX代码"><a href="#使用babel编译JS-JSX代码" class="headerlink" title="使用babel编译JS JSX代码"></a>使用babel编译JS JSX代码</h3><p>Babel 是一个 JavaScript 编译器,提供了JavaScript的编译过程,能够将源代码转换为目标代码。</p>
<p>对于ES6+的新特性,可通过corejs引入的方式实现向下兼容</p>
<p>AST -> Transform -> Generate</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">// test.js</span><br><span class="hljs-comment">//语法</span><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">a</span> = (<span class="hljs-params">params = <span class="hljs-number">2</span></span>) => <span class="hljs-number">1</span> + params;<br><span class="hljs-keyword">const</span> b = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]<br><span class="hljs-keyword">const</span> c = [...b, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]<br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Babel</span> {<br><br>}<br><span class="hljs-keyword">new</span> <span class="hljs-title class_">Babel</span>()<br><span class="hljs-comment">//API</span><br><span class="hljs-keyword">const</span> x = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>].<span class="hljs-title function_">filter</span>(<span class="hljs-function">(<span class="hljs-params">x</span>) =></span> x % <span class="hljs-number">2</span> === <span class="hljs-number">0</span>)<br><span class="hljs-keyword">const</span> y = <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">assign</span>({}, { <span class="hljs-attr">name</span>: <span class="hljs-number">1</span> })<br><br><span class="hljs-comment">// index.js</span><br><span class="hljs-comment">// 记得设置package.json的type为module</span><br><span class="hljs-keyword">import</span> <span class="hljs-title class_">Babel</span> <span class="hljs-keyword">from</span> <span class="hljs-string">'@babel/core'</span><br><span class="hljs-keyword">import</span> presetEnv <span class="hljs-keyword">from</span> <span class="hljs-string">'@babel/preset-env'</span><br><span class="hljs-keyword">import</span> fs <span class="hljs-keyword">from</span> <span class="hljs-string">'node:fs'</span><br><span class="hljs-keyword">const</span> file = fs.<span class="hljs-title function_">readFileSync</span>(<span class="hljs-string">'./test.js'</span>, <span class="hljs-string">'utf8'</span>)<br><span class="hljs-keyword">const</span> result = <span class="hljs-title class_">Babel</span>.<span class="hljs-title function_">transform</span>(file, {<br> <span class="hljs-attr">presets</span>: [presetEnv]<br>})<br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(result.<span class="hljs-property">code</span>)<br><br></code></pre></td></tr></table></figure>
<h3 id="使用swc编译JS-JSX"><a href="#使用swc编译JS-JSX" class="headerlink" title="使用swc编译JS JSX"></a>使用swc编译JS JSX</h3><p>SWC 既可用于编译,也可用于打包。对于编译,它使用现代 JavaScript 功能获取 JavaScript / TypeScript 文件并输出所有主流浏览器支持的有效代码。</p>
<p><strong><code>SWC在单线程上比 Babel 快 20 倍,在四核上快 70 倍。</code></strong></p>
<p>简单点来说swc实现了和babel一样的功能,但是它比babel快。</p>
<p><em>唉唉,编程原神<code>rust</code>发力了</em></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">// index.js</span><br><span class="hljs-keyword">import</span> swc <span class="hljs-keyword">from</span> <span class="hljs-string">'@swc/core'</span><br><br><span class="hljs-keyword">const</span> result = swc.<span class="hljs-title function_">transformFileSync</span>(<span class="hljs-string">'./test.js'</span>, {<br> <span class="hljs-attr">jsc</span>: {<br> <span class="hljs-attr">target</span>: <span class="hljs-string">"es5"</span>, <span class="hljs-comment">//代码转换es5</span><br> <span class="hljs-attr">parser</span>: {<br> <span class="hljs-attr">syntax</span>: <span class="hljs-string">'ecmascript'</span><br> }<br> }<br>})<br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(result.<span class="hljs-property">code</span>)<br></code></pre></td></tr></table></figure>
<p><strong>swc转JSX</strong></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">import</span> swc <span class="hljs-keyword">from</span> <span class="hljs-string">'@swc/core'</span><br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">time</span>()<br><span class="hljs-keyword">const</span> result = swc.<span class="hljs-title function_">transformFileSync</span>(<span class="hljs-string">'./test.jsx'</span>, {<br> <span class="hljs-attr">jsc</span>: {<br> <span class="hljs-attr">target</span>: <span class="hljs-string">"es5"</span>, <span class="hljs-comment">//代码转换es5</span><br> <span class="hljs-attr">parser</span>: {<br> <span class="hljs-attr">syntax</span>: <span class="hljs-string">'ecmascript'</span>,<br> <span class="hljs-attr">jsx</span>: <span class="hljs-literal">true</span><br> },<br> <span class="hljs-attr">transform</span>:{<br> <span class="hljs-attr">react</span>: {<br> <span class="hljs-attr">runtime</span>: <span class="hljs-string">'automatic'</span><br> }<br> }<br> }<br>})<br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(result.<span class="hljs-property">code</span>)<br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">timeEnd</span>()<br></code></pre></td></tr></table></figure>
<h2 id="VDOM-虚拟DOM"><a href="#VDOM-虚拟DOM" class="headerlink" title="VDOM (虚拟DOM)"></a>VDOM (虚拟DOM)</h2><p>Virtual DOM 就是用JavaScript对象去描述一个DOM结构,虚拟DOM不是直接操作浏览器的真实DOM,而是首先对 UI 的更新在虚拟 DOM 中进行,再将变更高效地同步到真实 DOM 中。</p>
</div>
<hr>
<div>
<div class="post-metas my-3">
<div class="post-meta mr-3 d-flex align-items-center">
<i class="iconfont icon-category"></i>
<span class="category-chains">
<span class="category-chain">