-
Notifications
You must be signed in to change notification settings - Fork 1
/
atom.xml
554 lines (286 loc) · 378 KB
/
atom.xml
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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Let's Code</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/atom.xml" rel="self"/>
<link href="https://github.com/Eva813/Eva813.github.io.git/"/>
<updated>2024-04-27T06:37:49.458Z</updated>
<id>https://github.com/Eva813/Eva813.github.io.git/</id>
<author>
<name>Eva Chan</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>vitest-i18n</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2024/04/27/vitest-i18n/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2024/04/27/vitest-i18n/</id>
<published>2024-04-27T05:12:36.000Z</published>
<updated>2024-04-27T06:37:49.458Z</updated>
<content type="html"><![CDATA[<p>最近嘗試在專案內加入測試,詢問朋友後建議先從 utils 中共用的邏輯函式開始,而在共用的邏輯函式中,會有幾個是 i18n 相關的函式。<br>因為頁面中常會用到將數值,轉換為顯示在畫面上的文字,如下:</p><figure class="highlight typescript"><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><span class="line"><span class="keyword">const</span> <span class="title function_">getType</span> = (<span class="params"><span class="keyword">type</span>: <span class="built_in">number</span></span>) => {</span><br><span class="line"> <span class="keyword">switch</span> (<span class="keyword">type</span>) {</span><br><span class="line"> <span class="keyword">case</span> <span class="number">0</span>:</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">t</span>(<span class="string">'Type.Auto'</span>)</span><br><span class="line"> <span class="keyword">case</span> <span class="number">1</span>:</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">t</span>(<span class="string">'Type.Manual'</span>)</span><br><span class="line"> <span class="keyword">case</span> <span class="number">2</span>:</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">t</span>(<span class="string">'Type.Mix'</span>)</span><br><span class="line"> <span class="attr">default</span>:</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>在進行測試時,總想說是否要先選定一語系,如中文\英文,然後確認他轉換的是否為該文字<br>但是經過嘗試後,覺得或許不應該是檢查轉換後的文字,應該要以對應 key 來檢查。<br>參考 <a href="https://stackoverflow.com/questions/72260793/how-to-mock-stub-vue-i18n">overflow</a></p><ul><li>因此專案是使用 quasar,所以在 i18n.t 方法,引入的位置是 boot/i18n.ts</li><li>在測試中,可以執行測試函式,帶入對應數值,並檢查是否回傳對應的 key</li></ul><figure class="highlight typescript"><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><span class="line"></span><br><span class="line"><span class="comment">// 在測試中覆寫模擬 i18n.t 方法</span></span><br><span class="line">vi.<span class="title function_">mock</span>(<span class="string">'../../../src/boot/i18n'</span>, <span class="function">() =></span> ({</span><br><span class="line"> <span class="attr">i18n</span>: {</span><br><span class="line"> <span class="attr">global</span>: {</span><br><span class="line"> <span class="attr">t</span>: <span class="function">(<span class="params">key: <span class="built_in">string</span></span>) =></span> key, <span class="comment">// 提供模擬的 t 函式</span></span><br><span class="line"> <span class="attr">locale</span>: <span class="string">'en'</span> <span class="comment">// 假設默認的 locale 值</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}))</span><br><span class="line"></span><br><span class="line"><span class="title function_">describe</span>(<span class="string">'getType'</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">it</span>(<span class="string">'should return the correct string for type 0'</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">expect</span>(<span class="title function_">getTradingType</span>(<span class="number">0</span>)).<span class="title function_">toBe</span>(<span class="string">'Type.Auto'</span>)</span><br><span class="line"> })</span><br><span class="line"></span><br><span class="line"> <span class="title function_">it</span>(<span class="string">'should return the correct string for type 1'</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">expect</span>(<span class="title function_">getTradingType</span>(<span class="number">1</span>)).<span class="title function_">toBe</span>(<span class="string">'Type.Manual'</span>)</span><br><span class="line"> })</span><br><span class="line"></span><br><span class="line"> <span class="title function_">it</span>(<span class="string">'should return the correct string for type 2'</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">expect</span>(<span class="title function_">getTradingType</span>(<span class="number">2</span>)).<span class="title function_">toBe</span>(<span class="string">'Type.Mix'</span>)</span><br><span class="line"> })</span><br><span class="line"> <span class="title function_">it</span>(<span class="string">'should return null for an unknown type'</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">expect</span>(<span class="title function_">getTradingType</span>(<span class="number">999</span>)).<span class="title function_">toBeNull</span>()</span><br><span class="line"> })</span><br><span class="line">})</span><br></pre></td></tr></table></figure><h3 id="小結上述方式:"><a href="#小結上述方式:" class="headerlink" title="小結上述方式:"></a>小結上述方式:</h3><p>使用全局模擬,vi.mock 全局模擬 i18n.t 方法,並提供模擬的 t 函式,這樣就可以在測試中,直接檢查是否回傳對應的 key,而不用檢查轉換後的文字。</p><p>另外,在跨頁面也會有共用的下拉選單,將此下拉選單的選項,也提取出來,並進行測試。</p><figure class="highlight typescript"><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><span class="line"></span><br><span class="line"><span class="keyword">const</span> directionOpt = <span class="title function_">computed</span>(<span class="function">() =></span> ([</span><br><span class="line"> { <span class="attr">label</span>: <span class="title function_">t</span>(<span class="string">'Shared.right'</span>), <span class="attr">value</span>: <span class="number">0</span> },</span><br><span class="line"> { <span class="attr">label</span>: <span class="title function_">t</span>(<span class="string">'Shared.wrong'</span>), <span class="attr">value</span>: <span class="number">1</span> }</span><br><span class="line">]))</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>原本也想是否直接檢查 key 是否正確即可。但基於困惑,就嘗試丟 chatGpt 詢問</p><span id="more"></span><ul><li>給予 mockT 方法,並提供對應的 key,並檢查是否有被呼叫</li><li>定義 directionOpt,並檢查是否回傳對應的 key</li><li>但此方式卻 directionOpt 撰寫於測試檔案中</li></ul><figure class="highlight typescript"><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><span class="line"><span class="keyword">const</span> mockT = vi.<span class="title function_">fn</span>(<span class="function">(<span class="params">key</span>) =></span> {</span><br><span class="line"> <span class="keyword">const</span> translations = {</span><br><span class="line"> <span class="string">'Shared.right'</span>: <span class="string">'正確'</span>,</span><br><span class="line"> <span class="string">'Shared.wrong'</span>: <span class="string">'錯誤'</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> translations[key]</span><br><span class="line">})</span><br><span class="line"><span class="comment">// 定義 directionOpt</span></span><br><span class="line"><span class="keyword">const</span> directionOpt = <span class="title function_">computed</span>(<span class="function">() =></span> ([</span><br><span class="line"> { <span class="attr">label</span>: <span class="title function_">mockT</span>(<span class="string">'Shared.right'</span>), <span class="attr">value</span>: <span class="number">0</span> },</span><br><span class="line"> { <span class="attr">label</span>: <span class="title function_">mockT</span>(<span class="string">'Shared.wrong'</span>), <span class="attr">value</span>: <span class="number">1</span> }</span><br><span class="line">]))</span><br><span class="line"><span class="title function_">describe</span>(<span class="string">'directionOpt'</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">it</span>(<span class="string">'should return the correct options'</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> options = directionOpt.<span class="property">value</span></span><br><span class="line"></span><br><span class="line"> <span class="title function_">expect</span>(options).<span class="title function_">toEqual</span>([</span><br><span class="line"> { <span class="attr">label</span>: <span class="string">'正確'</span>, <span class="attr">value</span>: <span class="number">0</span> },</span><br><span class="line"> { <span class="attr">label</span>: <span class="string">'錯誤'</span>, <span class="attr">value</span>: <span class="number">1</span> }</span><br><span class="line"> ])</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 确保模拟的 t 函数被正确调用</span></span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'mock'</span>, mockT)</span><br><span class="line"> <span class="title function_">expect</span>(mockT).<span class="title function_">toHaveBeenCalledWith</span>(<span class="string">'Shared.right'</span>)</span><br><span class="line"> <span class="title function_">expect</span>(mockT).<span class="title function_">toHaveBeenCalledWith</span>(<span class="string">'Shared.wrong'</span>)</span><br><span class="line"> })</span><br><span class="line">})</span><br></pre></td></tr></table></figure><p>後來,我回歸我想測試的目標在於,原函式 computed 是否使用這些 key,因此,就以以下方式進行測試</p><figure class="highlight typescript"><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><span class="line"><span class="title function_">describe</span>(<span class="string">"directionOpt"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">it</span>(<span class="string">"should return the correct options"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="keyword">const</span> options = directionOpt.<span class="property">value</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// t 函式直接反回 key 值,驗證 computed 是否使用这些 key</span></span><br><span class="line"> <span class="title function_">expect</span>(options).<span class="title function_">toEqual</span>([</span><br><span class="line"> { <span class="attr">label</span>: <span class="string">"Shared.right"</span>, <span class="attr">value</span>: <span class="number">0</span> },</span><br><span class="line"> { <span class="attr">label</span>: <span class="string">"Shared.wrong"</span>, <span class="attr">value</span>: <span class="number">1</span> },</span><br><span class="line"> ]);</span><br><span class="line"> });</span><br><span class="line">});</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><p>最近嘗試在專案內加入測試,詢問朋友後建議先從 utils 中共用的邏輯函式開始,而在共用的邏輯函式中,會有幾個是 i18n 相關的函式。<br>因為頁面中常會用到將數值,轉換為顯示在畫面上的文字,如下:</p>
<figure class="highlight typescript"><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><span class="line"><span class="keyword">const</span> <span class="title function_">getType</span> = (<span class="params"><span class="keyword">type</span>: <span class="built_in">number</span></span>) =&gt; &#123;</span><br><span class="line"> <span class="keyword">switch</span> (<span class="keyword">type</span>) &#123;</span><br><span class="line"> <span class="keyword">case</span> <span class="number">0</span>:</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">t</span>(<span class="string">&#x27;Type.Auto&#x27;</span>)</span><br><span class="line"> <span class="keyword">case</span> <span class="number">1</span>:</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">t</span>(<span class="string">&#x27;Type.Manual&#x27;</span>)</span><br><span class="line"> <span class="keyword">case</span> <span class="number">2</span>:</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">t</span>(<span class="string">&#x27;Type.Mix&#x27;</span>)</span><br><span class="line"> <span class="attr">default</span>:</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在進行測試時,總想說是否要先選定一語系,如中文\英文,然後確認他轉換的是否為該文字<br>但是經過嘗試後,覺得或許不應該是檢查轉換後的文字,應該要以對應 key 來檢查。<br>參考 <a href="https://stackoverflow.com/questions/72260793/how-to-mock-stub-vue-i18n">overflow</a></p>
<ul>
<li>因此專案是使用 quasar,所以在 i18n.t 方法,引入的位置是 boot/i18n.ts</li>
<li>在測試中,可以執行測試函式,帶入對應數值,並檢查是否回傳對應的 key</li>
</ul>
<figure class="highlight typescript"><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><span class="line"></span><br><span class="line"><span class="comment">// 在測試中覆寫模擬 i18n.t 方法</span></span><br><span class="line">vi.<span class="title function_">mock</span>(<span class="string">&#x27;../../../src/boot/i18n&#x27;</span>, <span class="function">() =&gt;</span> (&#123;</span><br><span class="line"> <span class="attr">i18n</span>: &#123;</span><br><span class="line"> <span class="attr">global</span>: &#123;</span><br><span class="line"> <span class="attr">t</span>: <span class="function">(<span class="params">key: <span class="built_in">string</span></span>) =&gt;</span> key, <span class="comment">// 提供模擬的 t 函式</span></span><br><span class="line"> <span class="attr">locale</span>: <span class="string">&#x27;en&#x27;</span> <span class="comment">// 假設默認的 locale 值</span></span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;))</span><br><span class="line"></span><br><span class="line"><span class="title function_">describe</span>(<span class="string">&#x27;getType&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line"> <span class="title function_">it</span>(<span class="string">&#x27;should return the correct string for type 0&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line"> <span class="title function_">expect</span>(<span class="title function_">getTradingType</span>(<span class="number">0</span>)).<span class="title function_">toBe</span>(<span class="string">&#x27;Type.Auto&#x27;</span>)</span><br><span class="line"> &#125;)</span><br><span class="line"></span><br><span class="line"> <span class="title function_">it</span>(<span class="string">&#x27;should return the correct string for type 1&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line"> <span class="title function_">expect</span>(<span class="title function_">getTradingType</span>(<span class="number">1</span>)).<span class="title function_">toBe</span>(<span class="string">&#x27;Type.Manual&#x27;</span>)</span><br><span class="line"> &#125;)</span><br><span class="line"></span><br><span class="line"> <span class="title function_">it</span>(<span class="string">&#x27;should return the correct string for type 2&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line"> <span class="title function_">expect</span>(<span class="title function_">getTradingType</span>(<span class="number">2</span>)).<span class="title function_">toBe</span>(<span class="string">&#x27;Type.Mix&#x27;</span>)</span><br><span class="line"> &#125;)</span><br><span class="line"> <span class="title function_">it</span>(<span class="string">&#x27;should return null for an unknown type&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line"> <span class="title function_">expect</span>(<span class="title function_">getTradingType</span>(<span class="number">999</span>)).<span class="title function_">toBeNull</span>()</span><br><span class="line"> &#125;)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<h3 id="小結上述方式:"><a href="#小結上述方式:" class="headerlink" title="小結上述方式:"></a>小結上述方式:</h3><p>使用全局模擬,vi.mock 全局模擬 i18n.t 方法,並提供模擬的 t 函式,這樣就可以在測試中,直接檢查是否回傳對應的 key,而不用檢查轉換後的文字。</p>
<p>另外,在跨頁面也會有共用的下拉選單,將此下拉選單的選項,也提取出來,並進行測試。</p>
<figure class="highlight typescript"><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><span class="line"></span><br><span class="line"><span class="keyword">const</span> directionOpt = <span class="title function_">computed</span>(<span class="function">() =&gt;</span> ([</span><br><span class="line"> &#123; <span class="attr">label</span>: <span class="title function_">t</span>(<span class="string">&#x27;Shared.right&#x27;</span>), <span class="attr">value</span>: <span class="number">0</span> &#125;,</span><br><span class="line"> &#123; <span class="attr">label</span>: <span class="title function_">t</span>(<span class="string">&#x27;Shared.wrong&#x27;</span>), <span class="attr">value</span>: <span class="number">1</span> &#125;</span><br><span class="line">]))</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>原本也想是否直接檢查 key 是否正確即可。但基於困惑,就嘗試丟 chatGpt 詢問</p></summary>
<category term="Test" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/Test/"/>
<category term="Test" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/Test/"/>
</entry>
<entry>
<title>css-grid</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2024/01/06/css-grid/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2024/01/06/css-grid/</id>
<published>2024-01-06T04:15:17.000Z</published>
<updated>2024-01-06T05:37:19.469Z</updated>
<content type="html"><![CDATA[<p>在 Youtube 看到 Kevin Powell 介紹使用 grid 來作為 wrapper,以自適應網頁的縮放。</p><p>首先基本常用 grid 方式</p><ul><li>創建一個包含三欄等寬的網格布局</li></ul><figure class="highlight css"><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><span class="line"><span class="selector-class">.content-grid</span> {</span><br><span class="line"> <span class="attribute">display</span>: grid;</span><br><span class="line"> <span class="attribute">grid-template-columns</span>: <span class="number">1</span>fr <span class="number">1</span>fr <span class="number">1</span>fr;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>加入使用 using named grid lines,定義出欄的 content 範圍</p><figure class="highlight css"><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><span class="line"><span class="selector-class">.content-grid</span> {</span><br><span class="line"> <span class="attribute">display</span>: grid;</span><br><span class="line"> <span class="attribute">grid-template-columns</span>: <span class="number">1</span>fr [content-start] <span class="number">1</span>fr [content-end] <span class="number">1</span>fr;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>設計一個 class 給他,如果在 content-grid 以下的元素,會將以下的元素放在 content 之間</p><ul><li>應用到 <code>.content-grid</code> 內部的每一個直接子元素</li></ul><figure class="highlight css"><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></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.content-grid</span> {</span><br><span class="line"> <span class="attribute">display</span>: grid;</span><br><span class="line"> <span class="attribute">grid-template-columns</span>: <span class="number">1</span>fr [content-start] <span class="number">1</span>fr [content- end] <span class="number">1</span>fr;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.content-grid</span> > * {</span><br><span class="line"> <span class="attribute">grid-column</span>: content;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="Layout-grid-可以先設置:"><a href="#Layout-grid-可以先設置:" class="headerlink" title="Layout grid 可以先設置:"></a>Layout grid 可以先設置:</h3><ul><li>就可以看到 content 範圍<br><img src="https://hackmd.io/_uploads/HyCjULL_p.png" alt="image"><br><img src="https://hackmd.io/_uploads/HkJWv8UO6.png" alt="image"></li></ul><span id="more"></span><h2 id="設置-breakout"><a href="#設置-breakout" class="headerlink" title="設置 breakout"></a>設置 breakout</h2><figure class="highlight css"><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><span class="line"><span class="selector-class">.content-grid</span> {</span><br><span class="line"> <span class="attribute">display</span>: grid;</span><br><span class="line"> <span class="attribute">grid-template-columns</span>: <span class="number">100px</span> [breakout-start] <span class="number">100px</span> [content-start] <span class="number">1</span>fr [content-end] <span class="number">100px</span> [breakout-end] <span class="number">100px</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.content-grid</span> > * {</span><br><span class="line"> <span class="attribute">grid-column</span>: content;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.content-grid</span> > <span class="selector-class">.breakout</span> {</span><br><span class="line"> <span class="attribute">grid-column</span>: breakout;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="https://hackmd.io/_uploads/HycvDLIO6.png" alt="image"></p><h2 id="不可缺的-full-width"><a href="#不可缺的-full-width" class="headerlink" title="不可缺的 full-width"></a>不可缺的 full-width</h2><ul><li>利用網格線的 最左側以及最右側 grid line</li></ul><figure class="highlight css"><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><span class="line"><span class="selector-class">.content-grid</span> {</span><br><span class="line"> <span class="attribute">display</span>: grid;</span><br><span class="line"> <span class="attribute">grid-template-columns</span>: [full-width-start] <span class="number">100px</span> [breakout-start] <span class="number">100px</span> [content-start] <span class="number">1</span>fr [content-end] <span class="number">100px</span> [breakout-end] <span class="number">100px</span> [full-width-end];</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.content-grid</span> > * {</span><br><span class="line"> <span class="attribute">grid-column</span>: content;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.content-grid</span> > <span class="selector-class">.breakout</span> {</span><br><span class="line"> <span class="attribute">grid-column</span>: breakout;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.content-grid</span> > <span class="selector-class">.full-width</span> {</span><br><span class="line"> <span class="attribute">grid-column</span>: full-width;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>希望區塊的背景可以 full-with 但內容符合文章(content)寬度<br><code>.content-grid > .full-width</code></li></ul><figure class="highlight css"><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><span class="line"><span class="selector-class">.content-grid</span> {</span><br><span class="line"> <span class="attribute">display</span>: grid;</span><br><span class="line"></span><br><span class="line"> <span class="attribute">grid-template-columns</span>: [full-width-start] <span class="number">100px</span> [breakout-start] <span class="number">100px</span> [content-start] <span class="number">1</span>fr [content-end] <span class="number">100px</span> [breakout-end] <span class="number">100px</span> [full-width-end];</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.content-grid</span> > <span class="selector-pseudo">:not</span>(<span class="selector-class">.breakout</span>, <span class="selector-class">.full-width</span>),</span><br><span class="line"><span class="selector-class">.full-width</span> > <span class="selector-pseudo">:not</span>(<span class="selector-class">.breakout</span>, <span class="selector-class">.full-width</span>) {</span><br><span class="line"> <span class="attribute">grid-column</span>: content;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.content-grid</span> > <span class="selector-class">.breakout</span> {</span><br><span class="line"> <span class="attribute">grid-column</span>: breakout;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.content-grid</span> > <span class="selector-class">.full-width</span> {</span><br><span class="line"> <span class="attribute">grid-column</span>: full-width;</span><br><span class="line"> <span class="attribute">display</span>: grid;</span><br><span class="line"> <span class="attribute">grid-template-columns</span>: inherit;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="更細微的調整,設置變數以符合-responsive"><a href="#更細微的調整,設置變數以符合-responsive" class="headerlink" title="更細微的調整,設置變數以符合 responsive"></a>更細微的調整,設置變數以符合 responsive</h2><figure class="highlight css"><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><span class="line"><span class="selector-class">.content-grid</span>{</span><br><span class="line"> <span class="attr">--padding-inline</span>: <span class="number">2rem</span> ;</span><br><span class="line"> <span class="attr">--content-max-width</span>: <span class="number">70ch</span>;</span><br><span class="line"> <span class="attr">--breakout-max-width</span>: <span class="number">85ch</span></span><br><span class="line">--breakout-size: <span class="built_in">calc</span>(</span><br><span class="line">(<span class="built_in">var</span>(--breakout-max-width) - <span class="built_in">var</span>(--content-max-width)) / <span class="number">2</span></span><br><span class="line">);</span><br><span class="line"><span class="attribute">display</span>: grid;</span><br><span class="line"></span><br><span class="line"><span class="attribute">grid-template-columns</span>:</span><br><span class="line">[full-width-start] <span class="built_in">minmax</span>(<span class="built_in">var</span>(--padding-inline), <span class="number">1</span>fr)</span><br><span class="line">[breakout-start] <span class="built_in">minmax</span>(<span class="number">0</span>, <span class="built_in">var</span>(--breakout-size))</span><br><span class="line">[content-start] <span class="built_in">min</span>(<span class="number">100%</span> - (<span class="built_in">var</span>(--padding-inline) * <span class="number">2</span> ), <span class="built_in">var</span>(--content-max-width)) [content-end] <span class="built_in">minmax</span>(<span class="number">0</span>, <span class="built_in">var</span>(--breakout-size)) [breakout-end]</span><br><span class="line"><span class="built_in">minmax</span>(<span class="built_in">var</span>(--padding-inline), <span class="number">1</span>fr) [full-width-end];</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol><li>–padding-inline : 設計整體頁面 padding</li><li>ch:CSS3 加入了 ch 這個單位,廣義來說就是『一個字元』,相當於用來呈現的字體裡『0』這個字形的步進度量 (advance measure)</li></ol><ul><li>這裡,70ch 意味著最大寬度是當前字體「0」字符寬度的 70 倍。</li></ul><ol start="3"><li>breakout-size: 計算為 breakout 的最大寬與 content 最大寬度 之差的一半,用來設定邊界</li><li>整體 grid-template-columns 的設計</li></ol><ul><li>full-width-start 網格的起始</li><li>minmax(var(–padding-inline), 1fr) : 設置到 full-width 最大大小為 1fr, 最小則會保有 padding-inline 間距</li><li>[breakout-start] 是下一個網格線的名稱: 大小設置為從 0 到 var(–breakout-size)</li><li><code>[content-start] min(100% - (var(--padding-inline) * 2 ), var(--content-max-width)) [content-end]</code>: 標記了內容區域的開始和結束,–content-max-width 是 70ch , 如果寬度小於 70ch ,就會使用<code>100% - (var(--padding-inline) * 2</code>, 如果大於 70ch , 就會使用 content-max-width</li></ul><ol start="5"><li>在 content 後,接續 breakout-end, full-width-end 同樣相對 start 的區間</li></ol><h3 id="小結"><a href="#小結" class="headerlink" title="小結"></a>小結</h3><p>在未來可以嘗試應用此 grid template 作為整體網頁 layout 設計,且套用方式可以修改以下變數即可彈性變動整體的寬度以及斷點。</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></pre></td><td class="code"><pre><span class="line">--padding-inline: 2rem;</span><br><span class="line">--content-max-width: 70ch;</span><br><span class="line">--breakout-max-width: 85ch;</span><br></pre></td></tr></table></figure><h3 id="補充介紹-min-minmax"><a href="#補充介紹-min-minmax" class="headerlink" title="補充介紹 min(), minmax()"></a>補充介紹 <code>min()</code>, <code>minmax()</code></h3><p><code>minmax()</code><br>minmax() 函數在 CSS Grid 布局中常用來定義網格軌道(列或行)的大小範圍。這個函數接受兩個參數:最小值和最大值,用來設置一個軌道的最小和最大大小。當網格容器調整大小時,這個軌道的實際大小會在這個範圍內變化。</p><p>例如:</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">grid-template-columns</span>: <span class="built_in">minmax</span>(<span class="number">100px</span>, <span class="number">1</span>fr);</span><br></pre></td></tr></table></figure><p>這裡,該列的最小寬度設為 100 像素,最大寬度設為 1fr(即可用空間的一個分數單位)。如果容器的寬度大於 100 像素,該列將擴展以佔用更多可用空間,但不會小於 100 像素。</p><p><code>min()</code><br>min() 函數在 CSS 中用於選擇一組值中的最小值。在網格佈局中,它可以用來確保某個軌道的大小不會超過一系列可能值中的最小值。</p><p>例如:</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">grid-template-columns</span>: <span class="built_in">min</span>(<span class="number">100%</span>, <span class="number">500px</span>);</span><br></pre></td></tr></table></figure><p>這裡,該列的寬度將被設置為 100% 和 500 像素中的較小值。這意味著,如果容器的寬度超過 500 像素,該列的寬度將被限制在 500 像素;如果容器的寬度小於 500 像素,則該列的寬度將等於容器的寬度。</p><p><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout/Grid_layout_using_named_grid_lines">MDN-Grid layout</a></p>]]></content>
<summary type="html"><p>在 Youtube 看到 Kevin Powell 介紹使用 grid 來作為 wrapper,以自適應網頁的縮放。</p>
<p>首先基本常用 grid 方式</p>
<ul>
<li>創建一個包含三欄等寬的網格布局</li>
</ul>
<figure class="highlight css"><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><span class="line"><span class="selector-class">.content-grid</span> &#123;</span><br><span class="line"> <span class="attribute">display</span>: grid;</span><br><span class="line"> <span class="attribute">grid-template-columns</span>: <span class="number">1</span>fr <span class="number">1</span>fr <span class="number">1</span>fr;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>加入使用 using named grid lines,定義出欄的 content 範圍</p>
<figure class="highlight css"><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><span class="line"><span class="selector-class">.content-grid</span> &#123;</span><br><span class="line"> <span class="attribute">display</span>: grid;</span><br><span class="line"> <span class="attribute">grid-template-columns</span>: <span class="number">1</span>fr [content-start] <span class="number">1</span>fr [content-end] <span class="number">1</span>fr;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>設計一個 class 給他,如果在 content-grid 以下的元素,會將以下的元素放在 content 之間</p>
<ul>
<li>應用到 <code>.content-grid</code> 內部的每一個直接子元素</li>
</ul>
<figure class="highlight css"><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></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.content-grid</span> &#123;</span><br><span class="line"> <span class="attribute">display</span>: grid;</span><br><span class="line"> <span class="attribute">grid-template-columns</span>: <span class="number">1</span>fr [content-start] <span class="number">1</span>fr [content- end] <span class="number">1</span>fr;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.content-grid</span> &gt; * &#123;</span><br><span class="line"> <span class="attribute">grid-column</span>: content;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="Layout-grid-可以先設置:"><a href="#Layout-grid-可以先設置:" class="headerlink" title="Layout grid 可以先設置:"></a>Layout grid 可以先設置:</h3><ul>
<li>就可以看到 content 範圍<br><img src="https://hackmd.io/_uploads/HyCjULL_p.png" alt="image"><br><img src="https://hackmd.io/_uploads/HkJWv8UO6.png" alt="image"></li>
</ul></summary>
<category term="css" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/css/"/>
</entry>
<entry>
<title>製作簽名面板元件</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2023/12/23/signaturePad-component/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2023/12/23/signaturePad-component/</id>
<published>2023-12-23T04:49:11.000Z</published>
<updated>2024-01-06T04:14:02.993Z</updated>
<content type="html"><![CDATA[<p>因工作需求需要製作簽名面板,查看套件使用度較高 <a href="https://www.npmjs.com/package/signature_pad">signature_pad</a></p><ol><li>在專案內安裝 signature_pad 套件 <code>npm i signature_pad</code></li><li>嘗試將引入的簽名套件包成可以重複使用的元件。</li></ol><p>initializeSignaturePad : 進行初始化,如尺寸大小、筆的顏色、畫布背景色等。這邊將這些設置放在 props 讓使用時可以保有一些彈性空間。<br>resizeCanvas : 用於調整畫布的大小,目的是確保畫布的大小能夠適應不同的設備和螢幕解析度。<br>saveSignature\ clearSignature: 顧名思義就是儲存、清除簽名<br>注意:因為將簽名功能包成元件,使用 emit 將儲存的簽名傳到外層。</p><figure class="highlight javascript"><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><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br></pre></td><td class="code"><pre><span class="line"><template></span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">div</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">class</span>=<span class="string">"signature-pad"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">:style</span>=<span class="string">"{ width: props.width, height: props.height }"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> ></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">canvas</span> <span class="attr">ref</span>=<span class="string">"canvas"</span>></span><span class="tag"></<span class="name">canvas</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">slot</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"clearSignature"</span>></span>清除簽名<span class="tag"></<span class="name">button</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"saveSignature"</span>></span>儲存簽名<span class="tag"></<span class="name">button</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">slot</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"></template></span><br><span class="line"></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">script</span> <span class="attr">setup</span>></span><span class="language-javascript"></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="keyword">import</span> { onMounted, ref, watch, onUnmounted } <span class="keyword">from</span> <span class="string">"vue"</span>;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="keyword">import</span> <span class="title class_">SignaturePad</span> <span class="keyword">from</span> <span class="string">"signature_pad"</span>;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="keyword">const</span> props = <span class="title function_">defineProps</span>({</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="attr">width</span>: { <span class="attr">type</span>: <span class="title class_">String</span>, <span class="attr">default</span>: <span class="string">"100%"</span> },</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="attr">height</span>: { <span class="attr">type</span>: <span class="title class_">String</span>, <span class="attr">default</span>: <span class="string">"300px"</span> },</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="attr">penColor</span>: { <span class="attr">type</span>: <span class="title class_">String</span>, <span class="attr">default</span>: <span class="string">"black"</span> },</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="attr">backgroundColor</span>: { <span class="attr">type</span>: <span class="title class_">String</span>, <span class="attr">default</span>: <span class="string">"white"</span> },</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="attr">options</span>: { <span class="attr">type</span>: <span class="title class_">Object</span>, <span class="attr">default</span>: <span class="function">() =></span> ({}) },</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">});</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="keyword">const</span> canvas = <span class="title function_">ref</span>(<span class="literal">null</span>);</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="keyword">let</span> signaturePad = <span class="literal">null</span>;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="keyword">const</span> <span class="title function_">initializeSignaturePad</span> = (<span class="params"></span>) => {</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="keyword">if</span> (canvas.<span class="property">value</span>) {</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> signaturePad = <span class="keyword">new</span> <span class="title class_">SignaturePad</span>(canvas.<span class="property">value</span>, {</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> ...props.<span class="property">options</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="attr">penColor</span>: props.<span class="property">penColor</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="attr">backgroundColor</span>: props.<span class="property">backgroundColor</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> });</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> }</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">};</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="keyword">const</span> <span class="title function_">resizeCanvas</span> = (<span class="params"></span>) => {</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="comment">//window.devicePixelRatio 來獲取設備的像素密度,如果無法獲取到,則將ratio設為1。</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="keyword">const</span> ratio = <span class="title class_">Math</span>.<span class="title function_">max</span>(<span class="variable language_">window</span>.<span class="property">devicePixelRatio</span> || <span class="number">1</span>, <span class="number">1</span>);</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="comment">//根據畫布元素的寬度和高度,乘以ratio,來設定畫布的寬度和高度。為了確保畫布在高像素密度的設備上顯示正確。</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> canvas.<span class="property">value</span>.<span class="property">width</span> = canvas.<span class="property">value</span>.<span class="property">offsetWidth</span> * ratio;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> canvas.<span class="property">value</span>.<span class="property">height</span> = canvas.<span class="property">value</span>.<span class="property">offsetHeight</span> * ratio;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="comment">//獲取畫布的2D繪圖上下文,並使用scale方法將繪圖上下文的縮放比例設為ratio。</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> canvas.<span class="property">value</span>.<span class="title function_">getContext</span>(<span class="string">"2d"</span>).<span class="title function_">scale</span>(ratio, ratio);</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> signaturePad.<span class="title function_">clear</span>(); <span class="comment">// Clears any existing drawing</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">};</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="keyword">const</span> emit = <span class="title function_">defineEmits</span>([<span class="string">"clear"</span>, <span class="string">"save"</span>]);</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="keyword">const</span> <span class="title function_">saveSignature</span> = (<span class="params"></span>) => {</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="keyword">if</span> (signaturePad) {</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="keyword">const</span> signatureImage = signaturePad.<span class="title function_">toDataURL</span>();</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="title function_">emit</span>(<span class="string">"save"</span>, signatureImage);</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> }</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="keyword">return</span> <span class="literal">null</span>;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">};</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="keyword">const</span> <span class="title function_">clearSignature</span> = (<span class="params"></span>) => {</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="keyword">if</span> (signaturePad) {</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> signaturePad.<span class="title function_">clear</span>();</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="title function_">emit</span>(<span class="string">"clear"</span>); <span class="comment">// 發射清除事件</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> }</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">};</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="comment">// Initialize and resize canvas</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="title function_">onMounted</span>(<span class="function">() =></span> {</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="title function_">initializeSignaturePad</span>();</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">"resize"</span>, resizeCanvas);</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="title function_">resizeCanvas</span>();</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">});</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="title function_">onUnmounted</span>(<span class="function">() =></span> {</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="variable language_">window</span>.<span class="title function_">removeEventListener</span>(<span class="string">"resize"</span>, resizeCanvas);</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">});</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="comment">// Watch for prop changes</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="title function_">watch</span>(</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="function">() =></span> [props.<span class="property">penColor</span>, props.<span class="property">backgroundColor</span>, props.<span class="property">options</span>],</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="function">() =></span> {</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="title function_">initializeSignaturePad</span>();</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> },</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> { <span class="attr">deep</span>: <span class="literal">true</span> }</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">);</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"></span><span class="tag"></<span class="name">script</span>></span></span></span><br></pre></td></tr></table></figure><h3 id="參考資料:"><a href="#參考資料:" class="headerlink" title="參考資料:"></a>參考資料:</h3><p><a href="https://github.com/WangShayne/vue3-signature">https://github.com/WangShayne/vue3-signature</a></p>]]></content>
<summary type="html"><p>因工作需求需要製作簽名面板,查看套件使用度較高 <a href="https://www.npmjs.com/package/signature_pad">signature_pad</a></p>
<ol>
<li>在專案內安裝 signature_pad 套件 <cod</summary>
<category term="Vue" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/Vue/"/>
</entry>
<entry>
<title>vueTest - Vue test util (2)</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2023/08/05/vueTest-3/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2023/08/05/vueTest-3/</id>
<published>2023-08-05T04:31:08.000Z</published>
<updated>2023-12-23T04:47:18.895Z</updated>
<content type="html"><![CDATA[<p>延續上次介紹常用的 Vue test util 語法,今天要再多介紹幾個。</p><h2 id="text-與-html"><a href="#text-與-html" class="headerlink" title=".text() 與 .html()"></a><code>.text()</code> 與 <code>.html()</code></h2><figure class="highlight javascript"><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><span class="line"><template></span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"hello"</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> For a guide and recipes on how to configure / customize this project,<span class="tag"><<span class="name">br</span> /></span></span></span><br><span class="line"><span class="language-xml"> check out the</span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"https://cli.vuejs.org"</span> <span class="attr">target</span>=<span class="string">"_blank"</span> <span class="attr">rel</span>=<span class="string">"noopener"</span>></span></span></span><br><span class="line"><span class="language-xml"> vue-cli documentation</span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">a</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"></template></span><br></pre></td></tr></table></figure><p>使用 <code>html</code> 若直接 console 出會將 template 呈現出來</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></pre></td><td class="code"><pre><span class="line">html=> <div class="hello"></span><br><span class="line"> <p> For a guide and recipes on how to configure / customize this project,<br> check out the <a href="https://cli.vuejs.org" target="_blank" rel="noopener"> vue-cli documentation </a></p></span><br><span class="line"> </div></span><br></pre></td></tr></table></figure><p>在測試當中,可以直接抓取該斷落的內容進行比對</p><ol><li>取得該段的 html</li><li>取得該 DOM 元素,並進行 html 的比對</li></ol><figure class="highlight javascript"><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><span class="line"><span class="keyword">import</span> { shallowMount } <span class="keyword">from</span> <span class="string">"@vue/test-utils"</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">HelloWorld</span> <span class="keyword">from</span> <span class="string">"./HelloWorld.vue"</span>;</span><br><span class="line"></span><br><span class="line"><span class="title function_">describe</span>(<span class="string">"HelloWorld.vue"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">it</span>(<span class="string">"html & text"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="keyword">const</span> wrapper = <span class="title function_">shallowMount</span>(<span class="title class_">HelloWorld</span>);</span><br><span class="line"> <span class="comment">// console.log("html=>", wrapper.html());</span></span><br><span class="line"> <span class="comment">// console.log("text=>", wrapper.text());</span></span><br><span class="line"> <span class="title function_">expect</span>(wrapper.<span class="title function_">html</span>()).<span class="title function_">toMatch</span>(</span><br><span class="line"> <span class="string">`<a href="https://cli.vuejs.org" target="_blank" rel="noopener"> vue-cli documentation </a>`</span>);</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">"aLink_>"</span>, wrapper.<span class="title function_">find</span>(<span class="string">'a'</span>).<span class="title function_">html</span>())</span><br><span class="line"> <span class="title function_">expect</span>(wrapper.<span class="title function_">find</span>(<span class="string">'a'</span>).<span class="title function_">html</span>()).<span class="title function_">toMatch</span>(</span><br><span class="line"> <span class="string">`<a href="https://cli.vuejs.org" target="_blank" rel="noopener"> vue-cli documentation </a>`</span>);</span><br><span class="line"> });</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h2 id="component-的簡易測試"><a href="#component-的簡易測試" class="headerlink" title="component 的簡易測試"></a>component 的簡易測試</h2><p>如課程範例為一個卡片,裡面有一個圖片元件(ImageBox)、內文元件(Content)</p><p><img src="https://hackmd.io/_uploads/ryWgDUjoh.png" alt=""></p><figure class="highlight javascript"><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><span class="line"><template></span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"CardBox"</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">ImageBox</span> /></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">Content</span> <span class="attr">v-if</span>=<span class="string">"isOpenContent"</span> /></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"></template></span><br></pre></td></tr></table></figure><p>test goal: 檢查 component 是否有隨狀態而成功渲染與否。</p><h3 id="findComponent"><a href="#findComponent" class="headerlink" title="findComponent"></a>findComponent</h3><p>判斷 component 是否有存在<br>首先要如何抓元件?</p><ol><li>因頁面中是掛載組件,所以這邊使用 mount</li></ol><figure class="highlight javascript"><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><span class="line"><span class="keyword">import</span> { mount } <span class="keyword">from</span> <span class="string">"@vue/test-utils"</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">CardBox</span> <span class="keyword">from</span> <span class="string">"./index.vue"</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">ImageBox</span> <span class="keyword">from</span> <span class="string">"./ImageBox.vue"</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Content</span> <span class="keyword">from</span> <span class="string">"./Content.vue"</span>;</span><br><span class="line"></span><br><span class="line"><span class="title function_">describe</span>(<span class="string">"CardBox.vue"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">it</span>(<span class="string">"findComponent function test"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="keyword">const</span> wrapper = <span class="title function_">mount</span>(<span class="title class_">CardBox</span>);</span><br><span class="line"></span><br><span class="line"> <span class="title function_">expect</span>(wrapper.<span class="title function_">findComponent</span>(<span class="title class_">ImageBox</span>).<span class="title function_">exists</span>()).<span class="title function_">toBe</span>(<span class="literal">true</span>);</span><br><span class="line"> <span class="title function_">expect</span>(wrapper.<span class="title function_">findComponent</span>(<span class="title class_">Content</span>).<span class="title function_">exists</span>()).<span class="title function_">toBe</span>(<span class="literal">true</span>);</span><br><span class="line"> });</span><br><span class="line">});</span><br><span class="line"></span><br></pre></td></tr></table></figure><ul><li>findComponent(‘.class’)</li><li>findComponent({name: a}) 組建名稱</li><li>findComponent({ref: ‘ref’}) 組件實體:綁在 DOM 上的 ref</li><li>findComponent(component) 取得組件:抓取導入的組件</li></ul><h3 id="findAllComponents"><a href="#findAllComponents" class="headerlink" title="findAllComponents"></a>findAllComponents</h3><ul><li>此方式是會回傳陣列,要使用 <code>at()</code></li><li>不支援 ref 查找</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">expect</span>(wrapper.<span class="title function_">findAllComponents</span>(<span class="title class_">ImageBox</span>).<span class="title function_">at</span>(<span class="number">0</span>).<span class="title function_">exists</span>()).<span class="title function_">toBe</span>(<span class="literal">true</span>);</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Using find to search for a Component is deprecated and will be removed. Use findComponent instead. The find method will continue to work for finding elements using any valid selector(tag selectors (div, foo, bar), attribute selectors ([foo], [foo="bar"])...).</span><br></pre></td></tr></table></figure><h2 id="測試-class-and-attribute"><a href="#測試-class-and-attribute" class="headerlink" title="測試 class and attribute"></a>測試 class and attribute</h2><p>可以使用在狀態的切換或是驗證資料的對錯,可以用 class 存在與否驗證。</p><h3 id="attribute"><a href="#attribute" class="headerlink" title="attribute"></a>attribute</h3><ul><li>資料在渲染的時候,是否有正確的塞入到 attribute。</li><li>在做資料的渲然,將拿到的內容塞入 attribute 中,如 a link 的 href, img src</li></ul><p>範例題目延續上述使用得內文元件(Content)</p><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line"><script></span><br><span class="line"><span class="keyword">import</span> { ref } <span class="keyword">from</span> <span class="string">"@vue/reactivity"</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> {</span><br><span class="line"> <span class="attr">props</span>: {</span><br><span class="line"> <span class="attr">styleColor</span>: {</span><br><span class="line"> <span class="attr">type</span>: <span class="title class_">String</span>,</span><br><span class="line"> <span class="attr">default</span>: <span class="string">"red"</span>,</span><br><span class="line"> },</span><br><span class="line"> },</span><br><span class="line"> <span class="title function_">setup</span>(<span class="params">props</span>) {</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> props,</span><br><span class="line"> };</span><br><span class="line"> },</span><br><span class="line">};</span><br><span class="line"></script></span><br><span class="line"></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">template</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"content"</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">h1</span> <span class="attr">:class</span>=<span class="string">"['card_title', props.styleColor]"</span>></span></span></span><br><span class="line"><span class="language-xml"> Vue vue-test-utils</span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">h1</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"javascript:;"</span>></span>click<span class="tag"></<span class="name">a</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">p</span> <span class="attr">class</span>=<span class="string">"card_text"</span>></span></span></span><br><span class="line"><span class="language-xml"> Vue Test Utils (VTU) is a set of utility functions aimed to simplify testing Vue.js components. It provides some methods to mount and interact with Vue components in an isolated manner!</span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">template</span>></span></span></span><br></pre></td></tr></table></figure><p>test goal: 測試 <code><h1></code> 有沒有存在 styleColor</p><ul><li>使用 <code>class()</code> 帶入參數,就會去檢查該 class 是否存在<br>測試架構:</li></ul><ol><li>先確定該元件有被渲染出來</li><li>找到 h1 tag 並查看是否有 styleColor 傳入</li><li>元件內的 a link 放入 href</li></ol><figure class="highlight javascript"><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><span class="line"><span class="keyword">import</span> { shallowMount } <span class="keyword">from</span> <span class="string">"@vue/test-utils"</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Content</span> <span class="keyword">from</span> <span class="string">"./Content.vue"</span>;</span><br><span class="line"></span><br><span class="line"><span class="title function_">describe</span>(<span class="string">"Content.vue"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">it</span>(<span class="string">"find component"</span>,<span class="function">()=></span>{</span><br><span class="line"> <span class="keyword">const</span> wrapper = <span class="title function_">shallowMount</span>(<span class="title class_">Content</span>);</span><br><span class="line"></span><br><span class="line"> <span class="title function_">expect</span>(wrapper.<span class="title function_">find</span>(<span class="string">'.card_title'</span>).<span class="title function_">exists</span>()).<span class="title function_">toBe</span>(<span class="literal">true</span>)</span><br><span class="line"> })</span><br><span class="line"> <span class="title function_">it</span>(<span class="string">"check h1 tag have red class"</span>, <span class="function">()=></span>{</span><br><span class="line"> <span class="keyword">const</span> wrapper = <span class="title function_">shallowMount</span>(<span class="title class_">Content</span>);</span><br><span class="line"></span><br><span class="line"> <span class="title function_">expect</span>(wrapper.<span class="title function_">find</span>(<span class="string">'h1'</span>).<span class="title function_">classes</span>(<span class="string">'red'</span>)).<span class="title function_">toBe</span>(<span class="literal">true</span>);</span><br><span class="line"> })</span><br><span class="line"> <span class="title function_">it</span>(<span class="string">"button is disabled attr"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="keyword">const</span> wrapper = <span class="title function_">shallowMount</span>(<span class="title class_">Content</span>);</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'red'</span>, wrapper.<span class="title function_">find</span>(<span class="string">'a'</span>).<span class="title function_">attributes</span>(<span class="string">"href"</span>))</span><br><span class="line"> <span class="title function_">expect</span>(wrapper.<span class="title function_">find</span>(<span class="string">'a'</span>).<span class="title function_">attributes</span>(<span class="string">"href"</span>)).<span class="title function_">toBe</span>(<span class="string">"javascript:;"</span>);</span><br><span class="line"> })</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>練習方式,聽完講師分享的操作之後,寫下測試目標的結構,就可以嘗試自己撰寫看看!</p><h2 id="檢查是否可見-isVisible-amp-exists"><a href="#檢查是否可見-isVisible-amp-exists" class="headerlink" title="檢查是否可見 isVisible & exists"></a>檢查是否可見 isVisible & exists</h2><p>前面的範例練習,就可以看檔有使用 exists<br>在 vue template 中,有使用 <code>v-if</code>, <code>v-show</code> 來處理 div 顯示與否。<br><code>v-show</code> 會存在於 DOM 上。</p><figure class="highlight javascript"><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><span class="line"><span class="keyword">import</span> { shallowMount } <span class="keyword">from</span> <span class="string">"@vue/test-utils"</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">PhotoItem</span> <span class="keyword">from</span> <span class="string">"./index.vue"</span>;</span><br><span class="line"></span><br><span class="line"><span class="title function_">describe</span>(<span class="string">"PhotoItem.vue"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">it</span>(<span class="string">"DOM is v-if or v-show hide"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="keyword">const</span> wrapper = <span class="title function_">shallowMount</span>(<span class="title class_">PhotoItem</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// exists 用來查看是否存在</span></span><br><span class="line"> <span class="title function_">expect</span>(wrapper.<span class="title function_">find</span>(<span class="string">"#box1"</span>).<span class="title function_">exists</span>()).<span class="title function_">toBe</span>(<span class="literal">false</span>);</span><br><span class="line"> <span class="comment">// isVisible 用來判斷DOM是否給 v-show 隱藏起來</span></span><br><span class="line"> <span class="title function_">expect</span>(wrapper.<span class="title function_">find</span>(<span class="string">"#box2"</span>).<span class="title function_">isVisible</span>()).<span class="title function_">toBe</span>(<span class="literal">false</span>);</span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line">});</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><p>延續上次介紹常用的 Vue test util 語法,今天要再多介紹幾個。</p>
<h2 id="text-與-html"><a href="#text-與-html" class="headerlink" title=".text() 與 .html()"></a><c</summary>
<category term="test" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/test/"/>
<category term="test" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/test/"/>
</entry>
<entry>
<title>vue-isComponent</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2023/08/03/vue-isComponent/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2023/08/03/vue-isComponent/</id>
<published>2023-08-03T06:59:34.000Z</published>
<updated>2023-08-05T04:16:10.937Z</updated>
<content type="html"><![CDATA[<p>因工作需求研究 Tab 切換,要使用 router 或是 製作組件 <code>v-if</code>, <code>v-else</code> 切換。<br>這裡的範例,建議可以使用 <code>isComponent</code> 方式,透過點擊頁籤按鈕執行元件的改變,並且使用 <code>keep-alive</code> 儲存資料</p><p>資料來源:<a href="https://dev.to/reynoldadade/dynamic-components-a-vuejs-superpower-2olk">https://dev.to/reynoldadade/dynamic-components-a-vuejs-superpower-2olk</a></p>]]></content>
<summary type="html"><p>因工作需求研究 Tab 切換,要使用 router 或是 製作組件 <code>v-if</code>, <code>v-else</code> 切換。<br>這裡的範例,建議可以使用 <code>isComponent</code> 方式,透過點擊頁籤按鈕執行元件的改變,</summary>
<category term="Vue" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/Vue/"/>
<category term="Vue" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/Vue/"/>
</entry>
<entry>
<title>cypress 學習筆記 - Assertion</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2023/06/03/assert/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2023/06/03/assert/</id>
<published>2023-06-03T11:12:32.000Z</published>
<updated>2023-06-14T12:03:46.282Z</updated>
<content type="html"><![CDATA[<h2 id="implicit-assertion(隱含斷言)"><a href="#implicit-assertion(隱含斷言)" class="headerlink" title="implicit assertion(隱含斷言)"></a>implicit assertion(隱含斷言)</h2><p>常用的 <code>should</code> 關鍵字:</p><ol><li><code>be.visible</code>:確保元素在畫面上可見。</li><li><code>be.hidden</code>:確保元素在畫面上隱藏。</li><li><code>be.checked</code>:確保複選框或單選框元素被選中。</li><li><code>be.disabled</code>:確保元素被禁用。</li><li><code>have.text</code>:檢查元素的文字內容是否符合預期。</li><li><code>have.value</code>:檢查輸入元素的值是否符合預期。</li><li><code>have.attr</code>:檢查元素的特定屬性值是否符合預期。</li><li><code>have.class</code>:檢查元素是否具有特定的類名。</li><li><code>contain</code>:檢查元素是否包含指定的文字內容。</li></ol><p>可根據具體需求進行選擇和使用<br><a href="https://docs.cypress.io/guides/references/assertions">keywords</a></p><h3 id="這裡的練習範例,驗證當前網址(URL)的斷言方法。"><a href="#這裡的練習範例,驗證當前網址(URL)的斷言方法。" class="headerlink" title="這裡的練習範例,驗證當前網址(URL)的斷言方法。"></a>這裡的練習範例,驗證當前網址(URL)的斷言方法。</h3><p>include:確保當前網址包含特定的子字串。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cy.<span class="title function_">url</span>().<span class="title function_">should</span>(<span class="string">'include'</span>, <span class="string">'/login'</span>);</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>eq:確保當前網址與預期值完全相等。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cy.<span class="title function_">url</span>().<span class="title function_">should</span>(<span class="string">'eq'</span>, <span class="string">'https://example.com/dashboard'</span>);</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>contain:檢查當前網址是否包含特定的字串。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cy.<span class="title function_">url</span>().<span class="title function_">should</span>(<span class="string">'contain'</span>, <span class="string">'example.com'</span>);</span><br></pre></td></tr></table></figure><p>這些斷言方法可用於驗證當前網址是否符合預期,從而確保導航或操作正確導致了預期的網址變化。</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></pre></td><td class="code"><pre><span class="line"><span class="title function_">describe</span>(<span class="string">"Assertion practice"</span>,<span class="function">()=></span>{</span><br><span class="line"></span><br><span class="line"><span class="title function_">it</span>(<span class="string">"explicit"</span>, <span class="function">()=></span>{</span><br><span class="line"></span><br><span class="line">cy.<span class="title function_">visit</span>(<span class="string">'https://opensource-demo.orangehrmlive.com/web/index.php/auth/login'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">//should + keyword end</span></span><br><span class="line"></span><br><span class="line">cy.<span class="title function_">url</span>().<span class="title function_">should</span>(<span class="string">'include'</span>, <span class="string">'orangehrmlive.com'</span>)</span><br><span class="line"></span><br><span class="line">cy.<span class="title function_">url</span>().<span class="title function_">should</span>(<span class="string">'eq'</span>, <span class="string">'https://opensource-demo.orangehrmlive.com/web/index.php/auth/login'</span>)</span><br><span class="line"></span><br><span class="line">cy.<span class="title function_">url</span>().<span class="title function_">should</span>(<span class="string">'contain'</span>, <span class="string">'orangehrmlive'</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line">})</span><br><span class="line"></span><br></pre></td></tr></table></figure><ul><li>可以看到上述,有連續使用到 <code>url()</code></li></ul><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></pre></td><td class="code"><pre><span class="line">cy.<span class="title function_">url</span>().<span class="title function_">should</span>(<span class="string">'include'</span>, <span class="string">'orangehrmlive.com'</span>)</span><br><span class="line"></span><br><span class="line">.<span class="title function_">should</span>(<span class="string">'eq'</span>, <span class="string">'https://opensource-demo.orangehrmlive.com/web/index.php/auth/login'</span>)</span><br><span class="line"></span><br><span class="line">.<span class="title function_">should</span>(<span class="string">'contain'</span>, <span class="string">'orangehrmlive'</span>)</span><br></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></pre></td><td class="code"><pre><span class="line">cy.<span class="title function_">url</span>().<span class="title function_">should</span>(<span class="string">'include'</span>, <span class="string">'orangehrmlive.com'</span>)</span><br><span class="line"></span><br><span class="line">.<span class="title function_">and</span>(<span class="string">'eq'</span>, <span class="string">'https://opensource-demo.orangehrmlive.com/web/index.php/auth/login'</span>)</span><br><span class="line"></span><br><span class="line">.<span class="title function_">and</span>(<span class="string">'contain'</span>, <span class="string">'orangehrmlive'</span>)</span><br></pre></td></tr></table></figure><p>另外可以檢查進到頁面 logo 圖示的顯示</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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="title function_">describe</span>(<span class="string">"Assertion practice"</span>,<span class="function">()=></span>{</span><br><span class="line"> <span class="title function_">it</span>(<span class="string">"explicit"</span>, <span class="function">()=></span>{</span><br><span class="line"> cy.<span class="title function_">visit</span>(<span class="string">'https://opensource-demo.orangehrmlive.com/web/index.php/auth/login'</span>)</span><br><span class="line"> <span class="comment">//check logo 呈現與否</span></span><br><span class="line"> cy.<span class="title function_">get</span>(<span class="string">'.orangehrm-login-branding > img'</span>).<span class="title function_">should</span>(<span class="string">'be.visible'</span>)</span><br><span class="line"> .<span class="title function_">and</span>(<span class="string">'exist'</span>)</span><br><span class="line"> })</span><br><span class="line">})</span><br><span class="line"></span><br></pre></td></tr></table></figure><ul><li>使用者輸入框</li></ul><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="title function_">describe</span>(<span class="string">"Assertion practice"</span>,<span class="function">()=></span>{</span><br><span class="line"> <span class="title function_">it</span>(<span class="string">"explicit"</span>, <span class="function">()=></span>{</span><br><span class="line"> cy.<span class="title function_">visit</span>(<span class="string">'https://opensource-demo.orangehrmlive.com/web/index.php/auth/login'</span>)</span><br><span class="line"> </span><br><span class="line"> <span class="comment">//檢查 username 得輸入</span></span><br><span class="line"> <span class="comment">//取得 username 的輸入框,並且確保輸入的值</span></span><br><span class="line"> cy.<span class="title function_">get</span>(<span class="string">"input[placeholder='Username']"</span>).<span class="title function_">type</span>(<span class="string">"Admin"</span>)</span><br><span class="line"> cy.<span class="title function_">get</span>(<span class="string">"input[placeholder='Username']"</span>).<span class="title function_">should</span>(<span class="string">"have.value"</span>, <span class="string">"Admin"</span>)</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"> })</span><br><span class="line">})</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="explicit-assertion"><a href="#explicit-assertion" class="headerlink" title="explicit assertion"></a>explicit assertion</h2><p>(顯式斷言)」是指明確使用斷言方法來檢查特定的條件或預期結果。<br>與隱含斷言不同,顯式斷言需要您明確指定斷言方法來進行驗證。</p>]]></content>
<summary type="html"><h2 id="implicit-assertion(隱含斷言)"><a href="#implicit-assertion(隱含斷言)" class="headerlink" title="implicit assertion(隱含斷言)"></a>implicit asser</summary>
<category term="E2E" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/E2E/"/>
<category term="test" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/test/"/>
<category term="cypress" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/cypress/"/>
</entry>
<entry>
<title>cypress 學習筆記 - css Locator</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2023/06/03/cypress-2/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2023/06/03/cypress-2/</id>
<published>2023-06-03T01:48:47.000Z</published>
<updated>2023-06-03T02:16:41.005Z</updated>
<content type="html"><![CDATA[<p>有空就找找實作影片來練習一下~</p><p>而今天的實作練習,訪問 momoshop 取得搜尋框元素 -> 輸入搜尋的關鍵字(“雨傘”) -> 點擊搜尋 -><br>查看搜尋後的項目是否包含關鍵字。</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><span class="line"><span class="title function_">describe</span>(<span class="string">'CSSLocators'</span>,<span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">it</span>(<span class="string">"csslocators"</span>, <span class="function">()=></span>{</span><br><span class="line"> cy.<span class="title function_">visit</span>(<span class="string">"https://www.momoshop.com.tw/main/Main.jsp?momo=1&gclid=CjwKCAjwpuajBhBpEiwA_ZtfhU9MqvxnVs7Kh8LTNDbmKzFsmDxY16QIaP7lci98eVgfRoNz8ychuRoCao0QAvD_BwE"</span>)</span><br><span class="line"> </span><br><span class="line"> <span class="comment">//尋找某些關鍵字</span></span><br><span class="line"> cy.<span class="title function_">get</span>(<span class="string">'[name="keyword"]'</span>).<span class="title function_">type</span>(<span class="string">"雨傘"</span>)</span><br><span class="line"> <span class="comment">//點擊搜尋按鈕</span></span><br><span class="line"> cy.<span class="title function_">get</span>(<span class="string">"[title = '搜尋']"</span>).<span class="title function_">click</span>() <span class="comment">//attribute</span></span><br><span class="line"> cy.<span class="title function_">get</span>(<span class="string">'.prdName'</span>).<span class="title function_">contains</span>(<span class="string">'傘'</span>)</span><br><span class="line"> cy.<span class="title function_">get</span>(<span class="string">'.prdName'</span>).<span class="title function_">contains</span>(<span class="string">'羽絨'</span>) <span class="comment">//Assertion</span></span><br><span class="line"> })</span><br><span class="line">})</span><br></pre></td></tr></table></figure><p><img src="https://hackmd.io/_uploads/BytHdzdU2.png" alt=""></p><p>在此文章主要針對取得 <code>css Locator</code> 進行系列操作。<br>可以使用 <code>#idName</code>, <code>.cssName</code>, <code>[title = '搜尋']</code>, <code>[name = 'search']</code> 等方式<br>其實 cypress 官方網站也滿容易讀,可以根據我們想要在網頁上進行何種操作,搜尋相應的功能。<br>例如: Assertion <a href="https://docs.cypress.io/guides/references/assertions">cypress-assertions</a></p><p>小補充另一個取得定位的方式:<br>XPath:<br> XPath是一種用於導航XML文件的語言,同樣也適用於HTML文件。它提供了一種根據元素在文檔層次結構中的路徑選擇元素的方法。XPath表達式非常強大且靈活,可以根據元素的屬性、文本內容等條件進行選擇。</p><p>在Cypress中,您可以使用XPath選擇器,只需將選擇器字符串以 xpath 為前綴添加到命令中。例如:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cy.<span class="title function_">xpath</span>(<span class="string">'//button[@id="submit-btn"]'</span>).<span class="title function_">click</span>();</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><p>有空就找找實作影片來練習一下~</p>
<p>而今天的實作練習,訪問 momoshop 取得搜尋框元素 -&gt; 輸入搜尋的關鍵字(“雨傘”) -&gt; 點擊搜尋 -&gt;<br>查看搜尋後的項目是否包含關鍵字。</p>
<figure class="highligh</summary>
<category term="E2E" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/E2E/"/>
<category term="test" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/test/"/>
<category term="cypress" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/cypress/"/>
</entry>
<entry>
<title>自動化測試 E2E - cypress</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2023/05/07/cypress-1/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2023/05/07/cypress-1/</id>
<published>2023-05-07T04:48:47.000Z</published>
<updated>2023-05-07T05:15:42.870Z</updated>
<content type="html"><![CDATA[<p><img src="https://i.imgur.com/AE7iJQ1.png" alt=""></p><p>每次在交付完成的任務給 PM 之前,總是會先自行反覆點擊測驗過才提能安心提供。但除了自己點擊之外,是否有其他更為簡易的方式可以進行測試呢?Cypress 是一個用於編寫端對端測試的 JavaScript 測試框架。他可以幫助我們做到基礎的自動化測試,今天就先來認識看看吧~</p><h2 id="建立專案"><a href="#建立專案" class="headerlink" title="建立專案"></a>建立專案</h2><p>在本地建立一個 cypress-project 資料夾,進入該檔案夾<br><code>npm init -y</code><br><code>npm install cypress</code></p><ul><li>安裝完後<figure class="highlight javascript"><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><span class="line">{</span><br><span class="line"> <span class="string">"name"</span>: <span class="string">"cypress-project-1"</span>,</span><br><span class="line"> <span class="string">"version"</span>: <span class="string">"1.0.0"</span>,</span><br><span class="line"> <span class="string">"description"</span>: <span class="string">""</span>,</span><br><span class="line"> <span class="string">"main"</span>: <span class="string">"index.js"</span>,</span><br><span class="line"> <span class="string">"scripts"</span>: {</span><br><span class="line"> <span class="string">"test"</span>: <span class="string">"echo \"Error: no test specified\" && exit 1"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="string">"keywords"</span>: [],</span><br><span class="line"> <span class="string">"author"</span>: <span class="string">""</span>,</span><br><span class="line"> <span class="string">"license"</span>: <span class="string">"ISC"</span>,</span><br><span class="line"> <span class="string">"dependencies"</span>: {</span><br><span class="line"> <span class="string">"cypress"</span>: <span class="string">"^12.11.0"</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><h2 id="實作測試功能"><a href="#實作測試功能" class="headerlink" title="實作測試功能"></a>實作測試功能</h2><ul><li>訪問 google 頁面</li><li>進行關鍵字搜尋</li></ul><p><img src="https://i.imgur.com/2FOKkBZ.png" alt=""></p><h3 id="測試語法"><a href="#測試語法" class="headerlink" title="測試語法"></a>測試語法</h3><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line"><span class="title function_">it</span>(<span class="string">'google search'</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="comment">//visit 進入不同網站</span></span><br><span class="line"> cy.<span class="title function_">visit</span>(<span class="string">'https://www.google.com.tw/?hl=zh_TW'</span>)</span><br><span class="line"></span><br><span class="line"> cy.<span class="title function_">get</span>(<span class="string">'#APjFqb'</span>).<span class="title function_">type</span>(<span class="string">'what is cypress.io{Enter}'</span>)</span><br><span class="line"> <span class="comment">//除了點擊搜尋按鈕之外,一般也會按下 enter鍵觸發</span></span><br><span class="line"> <span class="comment">// cy.contains('Google 搜尋').click()</span></span><br><span class="line">})</span><br></pre></td></tr></table></figure><h3 id="測試操作"><a href="#測試操作" class="headerlink" title="測試操作"></a>測試操作</h3><p><code>npx cypress open</code> 進入測試介面,選擇 E2E</p><p><img src="https://i.imgur.com/rmkiayJ.png" alt=""></p><ul><li>選擇要測試的檔案:</li></ul><p><img src="https://i.imgur.com/W6yP5nu.png" alt=""></p><ul><li>透過選取器可以找到相對應的元素,並針對該元素下指令<ul><li>這邊我們就是拿到 搜尋框,並進行關鍵字的輸入<br><img src="https://i.imgur.com/RZ5EjKZ.png" alt=""></li></ul></li></ul><h3 id="測試結果呈現"><a href="#測試結果呈現" class="headerlink" title="測試結果呈現"></a>測試結果呈現</h3><ul><li>會進到 google 頁面</li><li>在輸入框輸入 what is cypress.io ,點擊 Enter 搜尋</li></ul><p><img src="https://i.imgur.com/a37BYX1.png" alt=""></p><p><img src="https://i.imgur.com/8QbuLdQ.jpg" alt=""></p><p>小結:</p><p>cy.visit(url):訪問指定網址。<br>cy.get():使用 cy.get() 方法選擇元素。我們可以使用不同的選擇器(如:CSS 選擇器)來指向特定元素。<br>type(): 使用 type() 方法在輸入框中輸入內容。<br>click():使用 cy.get() 定位到這些元素,然後使用 click() 方法模擬點擊操作。</p>]]></content>
<summary type="html"><p><img src="https://i.imgur.com/AE7iJQ1.png" alt=""></p>
<p>每次在交付完成的任務給 PM 之前,總是會先自行反覆點擊測驗過才提能安心提供。但除了自己點擊之外,是否有其他更為簡易的方式可以進行測試呢?Cypress 是一</summary>
<category term="E2E" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/E2E/"/>
<category term="test" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/test/"/>
<category term="cypress" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/cypress/"/>
</entry>
<entry>
<title>vueTest - Vue test util (1)</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2023/01/31/vueTest-2/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2023/01/31/vueTest-2/</id>
<published>2023-01-31T05:45:08.000Z</published>
<updated>2023-08-05T04:31:50.302Z</updated>
<content type="html"><![CDATA[<ul><li>測試 App.vue<ul><li>引入 <code>@vue/test-utils</code> 使用 shallowMount 方法</li><li>shallowMount 可以渲染出組件<h2 id="shallowMount-mount"><a href="#shallowMount-mount" class="headerlink" title="shallowMount , mount"></a>shallowMount , mount</h2>shallowMount : 只會渲染該元件當層的資料內容<br>mount : 深度渲染,會將元件內所包含的其他元件一起都渲染出</li></ul></li><li>例如以下範例: 在 App.vue 中有包含數個元件</li></ul><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><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><span class="line"> //App.vue</span><br><span class="line"><template></span><br><span class="line"></span><br><span class="line"><img class="logo" alt="Vue logo" src="./assets/logo.png" /></span><br><span class="line"></span><br><span class="line"><h1>Test demo</h1></span><br><span class="line"></span><br><span class="line"><AddCount /></span><br><span class="line"></span><br><span class="line"><HelloWorld /></span><br><span class="line"></span><br><span class="line"><div class="itemFlex"></span><br><span class="line"></span><br><span class="line"><CardBox v-for="i in 4" :key="i" /></span><br><span class="line"></span><br><span class="line"></div></span><br><span class="line"></span><br><span class="line"><UserList /></span><br><span class="line"></span><br><span class="line"><PhotoItem /></span><br><span class="line"></span><br><span class="line"></template></span><br></pre></td></tr></table></figure><ul><li>測試元件</li></ul><figure class="highlight javascript"><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><span class="line"><span class="keyword">import</span> { shallowMount, mount } <span class="keyword">from</span> <span class="string">"@vue/test-utils"</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">App</span> <span class="keyword">from</span> <span class="string">'@/App.vue'</span></span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"><span class="title function_">describe</span>(<span class="string">'App.vue test'</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"><span class="title function_">it</span>(<span class="string">'測試組件 1'</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"><span class="comment">//渲染出 App 元件</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> wrapper = <span class="title function_">shallowMount</span>(<span class="title class_">App</span>);</span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(wrapper.<span class="title function_">text</span>())</span><br><span class="line"></span><br><span class="line"><span class="title function_">expect</span>(wrapper.<span class="title function_">text</span>()).<span class="title function_">toMatch</span>(<span class="string">"Test demo"</span>)</span><br><span class="line"></span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="title function_">it</span>(<span class="string">'測試組件2'</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> wrapper = <span class="title function_">mount</span>(<span class="title class_">App</span>);</span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(wrapper.<span class="title function_">text</span>())</span><br><span class="line"></span><br><span class="line"><span class="title function_">expect</span>(wrapper.<span class="title function_">text</span>()).<span class="title function_">toMatch</span>(<span class="string">"若你是寫過 Vue 但沒有寫過單元測試的工程師"</span>)</span><br><span class="line"></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line">})</span><br></pre></td></tr></table></figure><p><img src="https://i.imgur.com/BcvGwlI.png" alt=""></p><p>get 與 find 差異</p><ul><li>抓取某個元件中 DOM 元素</li><li>兩者差異在於<ul><li>使用 get ,如果找不到元素會報錯,並且直接中斷測試的運行</li><li>使用 find 會依據 <code>exists()</code> 回傳布林值</li></ul></li></ul><p><code><button id="add" class="add-btn" @click="add">add 按鈕</button></code></p><p><img src="https://i.imgur.com/TWuFWX3.png" alt=""></p><ul><li>測試按鈕存不存在<ul><li>exists : 驗證某元素是否存在</li><li><a href="https://test-utils.vuejs.org/api/#exists"> exists</a></li></ul></li></ul><figure class="highlight javascript"><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><span class="line"><span class="title function_">describe</span>(<span class="string">'AddCount.vue'</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"><span class="title function_">it</span>(<span class="string">'test 1 '</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> wrapper = <span class="title function_">shallowMount</span>(<span class="title class_">AddCount</span>);</span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(wrapper.<span class="title function_">find</span>(<span class="string">'.add-btn'</span>))</span><br><span class="line"></span><br><span class="line"><span class="title function_">expect</span>(wrapper.<span class="title function_">find</span>(<span class="string">'.add-btn'</span>).<span class="title function_">exists</span>()).<span class="title function_">toBe</span>(<span class="literal">true</span>)</span><br><span class="line"></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line">})</span><br></pre></td></tr></table></figure><p><img src="https://i.imgur.com/0sBL0t6.png" alt=""></p><p><img src="https://i.imgur.com/htkF4X5.png" alt=""></p><h3 id="在情境應用"><a href="#在情境應用" class="headerlink" title="在情境應用"></a>在情境應用</h3><ul><li>在 AddCount 加入 <code>isOpen=ref(false)</code> 來判斷 button 是否在一開始要呈現</li><li>而再測試文件中就是要測試該按鈕在一開始並不會出現</li></ul><p><img src="https://i.imgur.com/YkBK6Ry.png" alt=""></p><figure class="highlight javascript"><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><span class="line"><span class="keyword">import</span> { shallowMount } <span class="keyword">from</span> <span class="string">'@vue/test-utils'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">AddCount</span> <span class="keyword">from</span> <span class="string">'@/components/AddCount.vue'</span></span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"><span class="title function_">describe</span>(<span class="string">'AddCount.vue'</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"><span class="title function_">it</span>(<span class="string">'test 1 '</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> wrapper = <span class="title function_">shallowMount</span>(<span class="title class_">AddCount</span>);</span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(wrapper.<span class="title function_">find</span>(<span class="string">'.add-btn'</span>))</span><br><span class="line"><span class="comment">// 找不到,並且回傳 false</span></span><br><span class="line"><span class="title function_">expect</span>(wrapper.<span class="title function_">find</span>(<span class="string">'.add-btn-err'</span>).<span class="title function_">exists</span>()).<span class="title function_">toBe</span>(<span class="literal">false</span>)</span><br><span class="line"></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"></span><br><span class="line">})</span><br></pre></td></tr></table></figure><h2 id="find-與-findAll"><a href="#find-與-findAll" class="headerlink" title="find 與 findAll"></a>find 與 findAll</h2><p>以 v-for list 的範例</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><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></pre></td><td class="code"><pre><span class="line"><script></span><br><span class="line"></span><br><span class="line">import { ref } from "vue";</span><br><span class="line"></span><br><span class="line">import data from "./data.json";</span><br><span class="line"></span><br><span class="line">export default {</span><br><span class="line"></span><br><span class="line">setup() {</span><br><span class="line"></span><br><span class="line">const employeeItem = ref(data);</span><br><span class="line"></span><br><span class="line">return {</span><br><span class="line"></span><br><span class="line">employeeItem,</span><br><span class="line"></span><br><span class="line">};</span><br><span class="line"></span><br><span class="line">},</span><br><span class="line"></span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"></script></span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"><template></span><br><span class="line"></span><br><span class="line"><ul class="item"></span><br><span class="line"></span><br><span class="line"><li class="user_list" v-for="item in employeeItem" :key="item.id"></span><br><span class="line"></span><br><span class="line"><div></span><br><span class="line"></span><br><span class="line"><p>員工編號: {{ item.userId }}</p></span><br><span class="line"></span><br><span class="line"><p>姓名: {{ item.username }}</p></span><br><span class="line"></span><br><span class="line"></div></span><br><span class="line"></span><br><span class="line"></li></span><br><span class="line"></span><br><span class="line"></ul></span><br><span class="line"></span><br><span class="line"></template></span><br></pre></td></tr></table></figure><p><img src="https://i.imgur.com/dqts5eV.png" alt=""></p><p><img src="https://i.imgur.com/PXPy1as.png" alt=""></p><p>如果是要抓元件中 list 有幾筆<br><code>wrapper.findAll('.user_list')</code> : 他會是一個陣列資料,其中包含好幾個 DOM wrapper </p><p><img src="https://i.imgur.com/I5lNSRX.png" alt=""></p><p>注意:<br> <code>TypeError: wrapper.findAll(...).text is not a function</code></p><ul><li>搭配使用 <code>at()</code> 用於找尋其中某一個物件</li></ul><figure class="highlight javascript"><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><span class="line"><span class="keyword">import</span> { shallowMount } <span class="keyword">from</span> <span class="string">'@vue/test-utils'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">UserList</span> <span class="keyword">from</span> <span class="string">'@/components/UserList.vue'</span></span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"><span class="title function_">describe</span>(<span class="string">'test UserList'</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"><span class="title function_">it</span>(<span class="string">'test Dom'</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> wrapper = <span class="title function_">shallowMount</span>(<span class="title class_">UserList</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// console.log(wrapper.findAll('.user_list').at(0).text())</span></span><br><span class="line"></span><br><span class="line"><span class="title function_">expect</span>(wrapper.<span class="title function_">findAll</span>(<span class="string">'.user_list'</span>).<span class="title function_">at</span>(<span class="number">0</span>).<span class="title function_">text</span>()).<span class="title function_">toMatch</span>(<span class="string">'員工編號: 399'</span>)</span><br><span class="line"></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line">})</span><br></pre></td></tr></table></figure><h3 id="另也可以測試所拿到的資料長度"><a href="#另也可以測試所拿到的資料長度" class="headerlink" title="另也可以測試所拿到的資料長度"></a>另也可以測試所拿到的資料長度</h3><ul><li>測試 DOM 資料長度</li></ul><figure class="highlight javascript"><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><span class="line"><span class="keyword">import</span> { shallowMount } <span class="keyword">from</span> <span class="string">'@vue/test-utils'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">UserList</span> <span class="keyword">from</span> <span class="string">'@/components/UserList.vue'</span></span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"><span class="title function_">describe</span>(<span class="string">'test UserList'</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"><span class="title function_">it</span>(<span class="string">'test Dom'</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> wrapper = <span class="title function_">shallowMount</span>(<span class="title class_">UserList</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// console.log(wrapper.findAll('.user_list').at(0).text())</span></span><br><span class="line"></span><br><span class="line"><span class="title function_">expect</span>(wrapper.<span class="title function_">findAll</span>(<span class="string">'.user_list'</span>).<span class="title function_">at</span>(<span class="number">0</span>).<span class="title function_">text</span>()).<span class="title function_">toMatch</span>(<span class="string">'員工編號: 399'</span>)</span><br><span class="line"></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"><span class="title function_">it</span>(<span class="string">'test List length'</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> wrapper = <span class="title function_">shallowMount</span>(<span class="title class_">UserList</span>);</span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(wrapper.<span class="title function_">findAll</span>(<span class="string">'.user_list'</span>).<span class="property">length</span>)</span><br><span class="line"></span><br><span class="line"><span class="title function_">expect</span>(wrapper.<span class="title function_">findAll</span>(<span class="string">'.user_list'</span>).<span class="property">length</span>).<span class="title function_">toBe</span>(<span class="number">6</span>)</span><br><span class="line"></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line">})</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><ul>
<li>測試 App.vue<ul>
<li>引入 <code>@vue/test-utils</code> 使用 shallowMount 方法</li>
<li>shallowMount 可以渲染出組件<h2 id="shallowMount-mount"><a h</summary>
<category term="test" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/test/"/>
<category term="test" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/test/"/>
</entry>
<entry>
<title>Vue 單元測試 - 基礎入門</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2023/01/28/vueTest-1/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2023/01/28/vueTest-1/</id>
<published>2023-01-28T06:50:37.000Z</published>
<updated>2023-01-28T06:58:53.481Z</updated>
<content type="html"><![CDATA[<p>為了不斷建立以及加深自己的技能,即便目前工作上未能使用,還是可以提前做些準備,之前看到 Mike 老師推出的 vue 單元測試,就先入手~<br>趁近期有空先來奠定下測試的基礎,未來可以在專案內練習撰寫!</p><p><img src="https://i.imgur.com/xhxaYa1.jpg" alt=""></p><h2 id="專案創建"><a href="#專案創建" class="headerlink" title="專案創建"></a>專案創建</h2><p>若一開始專案沒有選擇 jest 或加入測試 要如何在現有專案加入?</p><ul><li>可以進入該專案進行安裝<br><code>vue add unit-jest</code></li></ul><p>這裡創建的專案是使用 vue-cli 創建,並且在自選項目加入 unit test </p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vue create my-project</span><br></pre></td></tr></table></figure><h2 id="執行-test"><a href="#執行-test" class="headerlink" title="執行 test"></a>執行 test</h2><p><code>npm run test:unit</code></p><h2 id="更改預設的測試檔案位置"><a href="#更改預設的測試檔案位置" class="headerlink" title="更改預設的測試檔案位置"></a>更改預設的測試檔案位置</h2><p>component 與 測試的檔案,可以放在同一個資料夾中,以方便找尋</p><ol><li>建立 <code>jest.config.js</code> 來設定 jest </li></ol><ul><li>testMatch: 指定從 src 資料夾開始找尋與 spec 相關的檔案</li></ul><figure class="highlight javascript"><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><span class="line"></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = {</span><br><span class="line"></span><br><span class="line"> <span class="attr">preset</span>: <span class="string">"@vue/cli-plugin-unit-jest"</span>,</span><br><span class="line"></span><br><span class="line"> <span class="attr">testMatch</span>: [<span class="string">"**/src/**/*.spec.[jt]s?(x)"</span>],</span><br><span class="line"></span><br><span class="line">};</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>**`</p><h2 id="測試的基本架構"><a href="#測試的基本架構" class="headerlink" title="測試的基本架構"></a>測試的基本架構</h2><ul><li>describe : 類似群組概念,可以包一個或多個相關的測試。</li><li>it 與 test 一樣:其內容為測試的單位,裏面撰寫測試內容</li><li>第一個參數,用來表示該測試的敘述(”Test to do list”, “Test to do 1”, “Test to do 2” )</li></ul><figure class="highlight javascript"><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><span class="line"></span><br><span class="line"><span class="title function_">describe</span>(<span class="string">"Test to do list"</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"> <span class="title function_">it</span>(<span class="string">"Test to do 1"</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"> <span class="title function_">test</span>(<span class="string">"Test to do 2"</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><ul><li>it 也可以單獨另外撰寫</li></ul><figure class="highlight javascript"><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><span class="line"><span class="title function_">it</span>(<span class="string">'這是test case'</span>,<span class="function">()=></span>{</span><br><span class="line"></span><br><span class="line">})</span><br></pre></td></tr></table></figure><ul><li>執行測試呈現的樣子</li></ul><figure class="highlight javascript"><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><span class="line"><span class="keyword">import</span> { shallowMount } <span class="keyword">from</span> <span class="string">'@vue/test-utils'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">HelloWorld</span> <span class="keyword">from</span> <span class="string">'@/components/HelloWorld.vue'</span></span><br><span class="line"></span><br><span class="line"><span class="title function_">describe</span>(<span class="string">'HelloWorld.vue'</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"><span class="title function_">it</span>(<span class="string">'renders props.msg when passed'</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> msg = <span class="string">'new message'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> wrapper = <span class="title function_">shallowMount</span>(<span class="title class_">HelloWorld</span>, {</span><br><span class="line"></span><br><span class="line"><span class="attr">props</span>: { msg }</span><br><span class="line"></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"><span class="title function_">expect</span>(wrapper.<span class="title function_">text</span>()).<span class="title function_">toMatch</span>(msg)</span><br><span class="line"><span class="comment">//</span></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line">})</span><br></pre></td></tr></table></figure><ul><li>wrapper 是指 HelloWorld 這個 component</li><li>wrapper.text() : 會顯示此元件中所包含的文字</li><li><code>expect(wrapper.text()).toMatch(msg)</code>: <ul><li>toMatch 有合乎</li></ul></li></ul><p><img src="https://i.imgur.com/ejvXWQF.png" alt=""></p><h2 id="expext-與斷言"><a href="#expext-與斷言" class="headerlink" title="expext 與斷言"></a>expext 與斷言</h2><figure class="highlight javascript"><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><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="title function_">describe</span>(<span class="string">"Test to do list"</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"> <span class="title function_">it</span>(<span class="string">"Test to do 1"</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"> <span class="title function_">expect</span>(<span class="number">1</span> + <span class="number">1</span>).<span class="title function_">toBe</span>(<span class="number">2</span>);</span><br><span class="line"></span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"> <span class="title function_">it</span>(<span class="string">"Test to do 2"</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"> <span class="title function_">expect</span>(<span class="number">4</span> - <span class="number">1</span>).<span class="title function_">toBe</span>(<span class="number">3</span>);</span><br><span class="line"></span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><ul><li>expect: 預期需要匹配的項目,如放入變數、component、function</li><li>toBe(百分之百準確): 斷言,用什麼方式來匹配,這裡使用 toBe 函式</li></ul><h2 id="其他備註"><a href="#其他備註" class="headerlink" title="其他備註"></a>其他備註</h2><p>而官方網站已建議若要創建新專案可以使用 vite 為基礎的專案。所以新開的專案都是使用 Vitest (之後有機會再使用新專案來開看看)。<br>這邊因先根據教學來進行,故先使用 vue-test-utils + jest </p><p><img src="https://i.imgur.com/yrD2UW0.png" alt=""></p>]]></content>
<summary type="html"><p>為了不斷建立以及加深自己的技能,即便目前工作上未能使用,還是可以提前做些準備,之前看到 Mike 老師推出的 vue 單元測試,就先入手~<br>趁近期有空先來奠定下測試的基礎,未來可以在專案內練習撰寫!</p>
<p><img src="https://i.imgur.c</summary>
<category term="test" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/test/"/>
<category term="test" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/test/"/>
</entry>
<entry>
<title>TS - Generics 泛型</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2023/01/25/TS-Generics/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2023/01/25/TS-Generics/</id>
<published>2023-01-25T06:27:13.000Z</published>
<updated>2023-01-27T05:15:30.651Z</updated>
<content type="html"><![CDATA[<p><img src="https://i.imgur.com/xGK5aDO.png" alt=""></p><h2 id="資料整理"><a href="#資料整理" class="headerlink" title="資料整理"></a>資料整理</h2><p>例如有兩個 interface 屬性一樣,差異在於 型別內容</p><figure class="highlight typescript"><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><span class="line"><span class="keyword">interface</span> <span class="title class_">DataA</span> {</span><br><span class="line"> <span class="attr">key</span>:<span class="built_in">string</span></span><br><span class="line"> <span class="attr">key2</span>:<span class="built_in">number</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">DataB</span> {</span><br><span class="line"> <span class="attr">key</span>:<span class="built_in">string</span></span><br><span class="line"> <span class="attr">key2</span>:<span class="built_in">boolean</span></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><ul><li>使用 泛型 整理</li><li>將 T 部分,設為傳入的變數,可以依據宣告得變數所符合的型別進行設定<figure class="highlight typescript"><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">GenericsObj</span><T> = {</span><br><span class="line"> <span class="attr">key</span>:<span class="built_in">string</span></span><br><span class="line"> <span class="attr">key2</span>:T</span><br><span class="line">}</span><br><span class="line"><span class="keyword">type</span> <span class="title class_">DataA</span> = <span class="title class_">GenericsObj</span><<span class="built_in">number</span>>;</span><br><span class="line"><span class="keyword">type</span> <span class="title class_">DataB</span> = <span class="title class_">GenericsObj</span><<span class="built_in">boolean</span>>;</span><br><span class="line"><span class="comment">//以上的 DataA、DataB 的型別會與剛剛 interface 的設定一樣</span></span><br></pre></td></tr></table></figure></li></ul><p>範例2:</p><figure class="highlight typescript"><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><span class="line"><span class="keyword">interface</span> <span class="title class_">KeyPair</span><T, U> {</span><br><span class="line"> <span class="attr">key</span>: T;</span><br><span class="line"> <span class="attr">value</span>: U;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="attr">kp1</span>: <span class="title class_">KeyPair</span><<span class="built_in">number</span>, <span class="built_in">string</span>> = { <span class="attr">key</span>: <span class="number">1</span>, <span class="attr">value</span>: <span class="string">"str"</span>}</span><br><span class="line"><span class="keyword">let</span> <span class="attr">kp2</span>: <span class="title class_">KeyPair</span><<span class="built_in">string</span>, <span class="built_in">number</span>> = { <span class="attr">key</span>: <span class="string">"str"</span>, <span class="attr">value</span>: <span class="number">123</span>}</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="attr">arr</span>:<span class="built_in">number</span>[] = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>];</span><br><span class="line"><span class="keyword">let</span> <span class="attr">arrTwo</span>:<span class="title class_">Array</span><<span class="built_in">number</span>> = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>]</span><br></pre></td></tr></table></figure><h2 id="payload-應用"><a href="#payload-應用" class="headerlink" title="payload 應用"></a>payload 應用</h2><ul><li>這邊以 redux 中整理的 action 為範例</li></ul><figure class="highlight typescript"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> userDataPayload = {</span><br><span class="line"> <span class="attr">userId</span>: <span class="built_in">string</span>,</span><br><span class="line"> <span class="attr">data</span>:<span class="built_in">any</span></span><br><span class="line">}</span><br><span class="line"><span class="comment">//負責生成 action 的函式</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">setUserDataAction</span> = (<span class="params">payload:userDataPayload </span>)=>({</span><br><span class="line"> <span class="attr">type</span>: <span class="string">'SET_USER_DATA'</span>,</span><br><span class="line"> payload</span><br><span class="line">})</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">resetUserDataAction</span> =(<span class="params"></span>)=>({</span><br><span class="line"> <span class="attr">type</span>: <span class="string">'RESET_USER_DATA'</span>,</span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">CartDataPayload</span> = {</span><br><span class="line"> <span class="attr">product</span>: <span class="built_in">string</span></span><br><span class="line">}</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">setCartDataAction</span> =(<span class="params">payload:CartDataPayload</span>)=>({</span><br><span class="line"> <span class="attr">type</span>: <span class="string">'SET_CART_DATA'</span>,</span><br><span class="line"> payload</span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">SetUserDataAction</span> = {</span><br><span class="line"> <span class="attr">type</span>: <span class="string">'SET_USER_DATA'</span>,</span><br><span class="line"> <span class="attr">payload</span>:userDataPayload</span><br><span class="line">}</span><br><span class="line"><span class="keyword">type</span> <span class="title class_">ResetUserDataAction</span> = {</span><br><span class="line"> <span class="attr">type</span>: <span class="string">'RESET_USER_DATA'</span></span><br><span class="line">}</span><br><span class="line"><span class="keyword">type</span> <span class="title class_">SetCartDataAction</span> = {</span><br><span class="line"> <span class="attr">type</span>: <span class="string">'SET_CART_DATA'</span>,</span><br><span class="line"> <span class="attr">payload</span>:<span class="title class_">CartDataPayload</span></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><ul><li>由上可以觀察到 SetUserDataAction、ResetUserDataAction、SetCartDataAction 整理為一個</li><li>將 action 的型別整理,其key為type 與 payload</li></ul><figure class="highlight typescript"><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><span class="line"><span class="keyword">type</span> <span class="title class_">Action</span><T,P> = {</span><br><span class="line"> <span class="attr">type</span>: T,</span><br><span class="line"> <span class="attr">payload</span>:P</span><br><span class="line">}</span><br><span class="line"><span class="keyword">type</span> <span class="title class_">ActionWithoutPayload</span><T> = {</span><br><span class="line"> <span class="attr">type</span>: T</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">SetUserDataAction</span> = <span class="title class_">Action</span><<span class="string">'SET_USER_DATA'</span>,userDataPayload></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">SetCartDataAction</span> = <span class="title class_">Action</span><<span class="string">'SET_CART_DATA'</span>,<span class="title class_">CartDataPayload</span>></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">ResetUserDataAction</span> = <span class="title class_">ActionWithoutPayload</span><<span class="string">'RESET_USER_DATA'</span>></span><br><span class="line"></span><br><span class="line"><span class="comment">//可以將action 中的 type 進行聚合</span></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">Actions</span> = <span class="variable constant_">SET_USER_DATA</span> | <span class="variable constant_">SET_CART_DATA</span> | <span class="variable constant_">RESET_USER_DATA</span>;</span><br></pre></td></tr></table></figure><ul><li>以下,進一步再將 Action 和 ActionWithoutPayload 進行整合,他們差異在與 payload </li></ul><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> <span class="title class_">Action</span><T, P = <span class="literal">null</span>> = p <span class="keyword">extends</span> {} ? {<span class="attr">type</span>: T, <span class="attr">payload</span>: P} : {<span class="attr">type</span>: T};</span><br></pre></td></tr></table></figure><p>型別參數動態生成不同型別</p><h2 id="函式的泛型"><a href="#函式的泛型" class="headerlink" title="函式的泛型"></a>函式的泛型</h2><figure class="highlight typescript"><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><span class="line"><span class="keyword">const</span> fn = (<span class="attr">param</span>: <span class="built_in">string</span> | <span class="built_in">number</span>):(<span class="built_in">string</span>|<span class="built_in">number</span>)[]=>[param];</span><br><span class="line"><span class="title function_">fn</span>(<span class="number">1</span>);<span class="comment">//number 陣列 number[];</span></span><br><span class="line"><span class="title function_">fn</span>(<span class="string">'hello'</span>) <span class="comment">//string[]</span></span><br></pre></td></tr></table></figure><p><img src="https://i.imgur.com/QZCK4Em.png" alt=""></p><figure class="highlight typescript"><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><span class="line"><span class="keyword">const</span> fn = <T>(<span class="attr">param</span>: T):(T)[]=>[param];</span><br><span class="line"><span class="title function_">fn</span>(<span class="number">1</span>);<span class="comment">//number 陣列 number[];</span></span><br><span class="line"><span class="title function_">fn</span>(<span class="string">'hello'</span>) <span class="comment">//string[]</span></span><br></pre></td></tr></table></figure><p><img src="https://i.imgur.com/Yeeuum6.png" alt=""></p><ul><li>function 改寫方式</li></ul><figure class="highlight typescript"><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><span class="line"><span class="keyword">function</span> fn<T>(<span class="attr">param</span>:T):T[]{</span><br><span class="line"> <span class="keyword">return</span> [param]</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="type-的泛型"><a href="#type-的泛型" class="headerlink" title="type 的泛型"></a>type 的泛型</h2><figure class="highlight typescript"><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><span class="line"><span class="comment">//共用模板</span></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">GenericList</span><T> = T[];</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">StrList</span> = <span class="title class_">GenericList</span><<span class="built_in">string</span>>;</span><br><span class="line"><span class="keyword">type</span> <span class="title class_">BoolList</span> = <span class="title class_">GenericList</span><<span class="built_in">boolean</span>>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">GenericValObj</span><T> = {[<span class="attr">key</span>:<span class="built_in">string</span>]:T} </span><br><span class="line"><span class="keyword">type</span> <span class="title class_">NumValObj</span> = <span class="title class_">GenericValObj</span><<span class="built_in">number</span>></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="attr">numValObj</span>:<span class="title class_">NumValObj</span> = {</span><br><span class="line"> <span class="attr">img_res_200</span>:<span class="number">200</span></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><img src="https://i.imgur.com/sJFzEUg.png" alt=""></p><p><img src="https://i.imgur.com/7P1MnFL.png" alt=""></p><ul><li>嘗試聚合資料</li></ul><figure class="highlight typescript"><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><span class="line"><span class="keyword">type</span> <span class="title class_">GenericUnion</span><T,U> = T | U | T[] | U[];</span><br><span class="line"><span class="keyword">type</span> strNumUnion = <span class="title class_">GenericUnion</span><<span class="built_in">string</span>,<span class="built_in">number</span>></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="attr">val</span>:strNumUnion = <span class="string">"123"</span></span><br><span class="line"><span class="keyword">const</span> <span class="attr">val2</span>:strNumUnion = [<span class="string">"123"</span>]</span><br></pre></td></tr></table></figure><p><img src="https://i.imgur.com/y5Vl8M9.png" alt=""></p><h2 id="將函式改寫為-共用的泛型型別"><a href="#將函式改寫為-共用的泛型型別" class="headerlink" title="將函式改寫為 共用的泛型型別"></a>將函式改寫為 共用的泛型型別</h2><ul><li>將type 拉出來獨立撰寫,可以重複使用</li></ul><figure class="highlight typescript"><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><span class="line"><span class="keyword">const</span> fn = <T>(<span class="attr">param</span>: T):(T)[]=>{</span><br><span class="line"> <span class="keyword">return</span> [param]</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="comment">//上面的函式也可以用於</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">Props</span> {</span><br><span class="line"> <span class="attr">onFn</span>: <span class="keyword">typeof</span> fn</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//rewrite</span></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">GenericFn</span> = <T><span class="function">(<span class="params">param: T</span>) =></span> T[]</span><br><span class="line"><span class="keyword">const</span> <span class="attr">fn</span>:<span class="title class_">GenericFn</span> = <span class="function">(<span class="params">param</span>) =></span> {</span><br><span class="line"> <span class="keyword">return</span> [param]</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//共用,如下有個 interface 其中有個屬性的型別與 GenericFn 一樣,則可以共用</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">Props</span> {</span><br><span class="line"> <span class="attr">onFn</span>:<span class="title class_">GenericFn</span></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight typescript"><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><span class="line"><span class="keyword">function</span> fn<T>(<span class="attr">param</span>:T):T[]{</span><br><span class="line"> <span class="keyword">return</span> [param]</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//產生型別泛型</span></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">FnType</span> = <span class="keyword">typeof</span> fn ;</span><br></pre></td></tr></table></figure><p><img src="https://i.imgur.com/yxsVm1s.png" alt=""></p><p><img src="https://i.imgur.com/zYtwh7H.png" alt=""><br><img src="https://i.imgur.com/tPHEDZ7.png" alt=""></p><h3 id="比較-lt-T-gt-位置差異"><a href="#比較-lt-T-gt-位置差異" class="headerlink" title="比較<T>位置差異"></a>比較<code><T></code>位置差異</h3><figure class="highlight typescript"><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><span class="line"><span class="keyword">type</span> <span class="title class_">FnTypeA</span> = <T><span class="function">(<span class="params">param: T</span>) =></span> T[]</span><br><span class="line"><span class="keyword">type</span> <span class="title class_">FnTypeB</span><T> = <span class="function">(<span class="params">param: T</span>) =></span> T[]</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="attr">fn1</span>:<span class="title class_">FnTypeA</span> = <span class="function">(<span class="params">param</span>) =></span> {</span><br><span class="line"> <span class="keyword">return</span> [param]</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//必須指定好型別的 argument</span></span><br><span class="line"><span class="keyword">const</span> <span class="attr">fn2</span>:<span class="title class_">FnTypeB</span><<span class="built_in">string</span>> = <span class="function">(<span class="params">param</span>) =></span> {</span><br><span class="line"> <span class="keyword">return</span> [param]</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//兩個函式在使用上會有差異:</span></span><br><span class="line"><span class="title function_">fn1</span>();</span><br><span class="line"></span><br><span class="line"><span class="title function_">fn2</span>(<span class="string">'Hi'</span>)</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><img src="https://i.imgur.com/J3zJs2Y.png" alt=""></p><p><img src="https://i.imgur.com/0wxPZk9.png" alt=""></p><ul><li>fn1 可以填入任何內容、可以動態填入型別<br><img src="https://i.imgur.com/pwfnIjO.png" alt=""><br><img src="https://i.imgur.com/6B8gtAc.png" alt=""><br><img src="https://i.imgur.com/OgPatHZ.png" alt=""></li><li>fn2 只能填入 string 內容<br><img src="https://i.imgur.com/cwmVA5b.png" alt=""></li></ul><figure class="highlight typescript"><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><span class="line"><span class="keyword">export</span> <span class="keyword">type</span> <span class="title class_">ClickFn</span> = <<span class="title class_">Event</span>><span class="function">(<span class="params">e:Event</span>) =></span> <span class="built_in">any</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//使用 function 會無法重複使用寫好的型別</span></span><br><span class="line"><span class="comment">// 引用</span></span><br><span class="line"><span class="keyword">const</span> <span class="attr">handleClick</span>:<span class="title class_">ClickFn</span> = <span class="function">(<span class="params">e</span>)=></span>{</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="interface-的泛型"><a href="#interface-的泛型" class="headerlink" title="interface 的泛型"></a>interface 的泛型</h2><figure class="highlight typescript"><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><span class="line"><span class="keyword">export</span> <span class="keyword">interface</span> <span class="title class_">GenericI</span><T>{</span><br><span class="line"> [<span class="attr">key</span>:<span class="built_in">string</span>]: T</span><br><span class="line">} </span><br><span class="line"><span class="keyword">type</span> <span class="title class_">NumValObj</span> = <span class="title class_">GenericI</span><<span class="built_in">number</span>>;</span><br><span class="line"><span class="keyword">const</span> <span class="attr">numberValObj</span>:<span class="title class_">NumValObj</span> = {</span><br><span class="line"> <span class="attr">res</span>:<span class="number">123</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//type寫法也可以一樣</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">type</span> <span class="title class_">GenericT</span><T> = {</span><br><span class="line"> [<span class="attr">key</span>:<span class="built_in">string</span>]: T</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//API 的應用!!!</span></span><br><span class="line"><span class="comment">//注意:in 寫法只用於 type 中</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">type</span> <span class="title class_">GenericKeyValObj</span><T <span class="keyword">extends</span> keyof <span class="built_in">any</span>,P> = {</span><br><span class="line"> [key <span class="keyword">in</span> T ]: P</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//可以應用於 API </span></span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">ApiKey</span> = <span class="string">'user'</span> | <span class="string">'id'</span> | <span class="string">'password'</span>; <span class="comment">//將欄位值設定好</span></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">UserApiData</span> = <span class="title class_">GenericKeyValObj</span><<span class="title class_">ApiKey</span>, <span class="built_in">string</span>></span><br><span class="line"></span><br></pre></td></tr></table></figure><p><img src="https://i.imgur.com/dceV8io.png" alt=""></p><ul><li><p>可以很快的生成 API 的資料型別<br><img src="https://i.imgur.com/Vv3lVDC.png" alt=""></p></li><li><p>其他範例</p></li></ul><figure class="highlight typescript"><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><span class="line"><span class="comment">//類似呼叫API的函式</span></span><br><span class="line"><span class="comment">//Params : 參數</span></span><br><span class="line"><span class="comment">//Res result : 回傳值</span></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">GenericApiFn</span><<span class="title class_">Params</span>, <span class="title class_">Res</span>> = <span class="function">(<span class="params">params:Params</span>)=></span> <span class="title class_">Res</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//組合其他泛型使用,也可以將原本泛型參數自己使用</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">ApiContainerProps</span><<span class="title class_">Params</span>, <span class="title class_">Res</span>> {</span><br><span class="line"> <span class="attr">initData</span>: <span class="title class_">Res</span>;</span><br><span class="line"> <span class="attr">onAsyncCb</span>: <span class="title class_">GenericApiFn</span><<span class="title class_">Params</span>, <span class="title class_">Res</span>></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><ul><li>interface 與 type 的泛型寫法</li></ul><figure class="highlight typescript"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//interface 寫函式</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">FnI</span> {</span><br><span class="line"> <T>(<span class="attr">param</span>: T): T[]</span><br><span class="line">}</span><br><span class="line"><span class="comment">//同等於</span></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">FnT</span> = <T><span class="function">(<span class="params">param:T</span>)=></span>T[]</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="attr">fn</span>:<span class="title class_">FnT</span> = <span class="function">(<span class="params">param</span>)=></span>[param]</span><br></pre></td></tr></table></figure><ul><li><code><T></code>位置的調動</li></ul><figure class="highlight typescript"><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><span class="line"><span class="comment">//<T> 會影響整個 interface</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">GenericFnI</span><T> {</span><br><span class="line"> (<span class="attr">param</span>: T): T[]</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="attr">fn2</span>: <span class="title class_">GenericFnI</span><<span class="built_in">string</span>>= <span class="function">(<span class="params">param</span>)=></span>[param]</span><br></pre></td></tr></table></figure><p>過去都未曾注意到泛型可以抽成共用還有 <code><T></code> 的位置所放的位置,會影響宣告,透過此次的教學,讓我對泛型可以應用於實際情況的案例,同樣未來在訂定 type 或 interface 時可以加以注意,思考是否可以改寫為泛型加以使用。</p><p>參考資料<br><a href="https://www.youtube.com/watch?v=9hZbfX_Atpc&t=44s">成為進階TS開發者的第一哩路 — 泛型簡介與基礎(1)</a><br><a href="https://www.youtube.com/watch?v=7yA4ALLoSxY">成為進階TS開發者的第一哩路 — 泛型的函式, type和interface寫法一次說清楚!</a></p>]]></content>
<summary type="html"><p><img src="https://i.imgur.com/xGK5aDO.png" alt=""></p>
<h2 id="資料整理"><a href="#資料整理" class="headerlink" title="資料整理"></a>資料整理</h2><p>例如有兩</summary>
<category term="TypeScript" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/TypeScript/"/>
<category term="TypeScript" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/TypeScript/"/>
</entry>
<entry>
<title>TypeScript - interface 使用</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2023/01/25/TS-interface/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2023/01/25/TS-interface/</id>
<published>2023-01-25T05:34:04.000Z</published>
<updated>2023-01-26T05:04:49.453Z</updated>
<content type="html"><![CDATA[<p><img src="https://i.imgur.com/xGK5aDO.png" alt=""></p><p>最近在複習使用 TypeScript 發現還有些部分可以做紀錄並且重新回憶的區塊,藉此再紀錄於部落格。</p><h2 id="TS-interface的基礎宣告"><a href="#TS-interface的基礎宣告" class="headerlink" title="TS interface的基礎宣告"></a>TS interface的基礎宣告</h2><ul><li>將複雜系統簡化的結果叫做介面</li><li>介面一般首字母大寫</li></ul><figure class="highlight typescript"><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><span class="line"><span class="keyword">interface</span> <span class="title class_">Person</span> {</span><br><span class="line"> <span class="attr">name</span>: <span class="built_in">string</span>;</span><br><span class="line"> <span class="attr">age</span>: <span class="built_in">number</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="title class_">Eva</span>: <span class="title class_">Person</span> = {</span><br><span class="line"> <span class="attr">name</span>: <span class="string">'Eva'</span>,</span><br><span class="line"> <span class="attr">age</span>: <span class="number">25</span></span><br><span class="line">};</span><br></pre></td></tr></table></figure><h2 id="函式與介面"><a href="#函式與介面" class="headerlink" title="函式與介面"></a>函式與介面</h2><ul><li>以下範例宣告 AddFunction 的介面</li><li>並將此型別應用於 add 這個變數的方法中</li></ul><figure class="highlight typescript"><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><span class="line"><span class="keyword">interface</span> <span class="title class_">AddFunction</span> {</span><br><span class="line"> (<span class="attr">a</span>: <span class="built_in">number</span>, <span class="attr">b</span>: <span class="built_in">number</span>): <span class="built_in">number</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="attr">add</span>: <span class="title class_">AddFunction</span> = <span class="keyword">function</span>(<span class="params">a, b</span>) { <span class="keyword">return</span> a + b; };</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="class與介面"><a href="#class與介面" class="headerlink" title="class與介面"></a>class與介面</h2><figure class="highlight typescript"><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><span class="line"><span class="keyword">interface</span> <span class="title class_">CatInterface</span> {</span><br><span class="line"><span class="comment">//普通成員變數的規格</span></span><br><span class="line"><span class="attr">name</span>: <span class="built_in">string</span>;</span><br><span class="line"><span class="attr">breed</span>: <span class="built_in">string</span>;</span><br><span class="line"><span class="attr">noise</span>: <span class="built_in">string</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//普通成員方法的規格,使用函式型別格式</span></span><br><span class="line"><span class="title function_">makeNoise</span>(): <span class="built_in">void</span>;</span><br><span class="line"><span class="title function_">feed</span>(<span class="attr">something</span>: <span class="built_in">string</span>): <span class="built_in">void</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>若類別想要實踐此介面,必須用 <code>implements</code> 這個關鍵字</li><li>如果類別實踐介面的規格中,任何一個成員不見或沒有實踐時,會出現提醒訊息。</li></ul><figure class="highlight typescript"><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><span class="line"><span class="keyword">class</span> <span class="title class_">Cat</span> <span class="keyword">implements</span> <span class="title class_">CatInterface</span>{</span><br><span class="line"><span class="keyword">public</span> <span class="attr">name</span>: <span class="built_in">string</span>;</span><br><span class="line"><span class="keyword">public</span> <span class="attr">breed</span>: <span class="built_in">string</span>;</span><br><span class="line"><span class="keyword">public</span> <span class="attr">noise</span>: <span class="built_in">string</span> = <span class="string">'Meow meow!'</span>;</span><br><span class="line"></span><br><span class="line"> <span class="title function_">constructor</span>(<span class="params">name:<span class="built_in">string</span>, breed:<span class="built_in">string</span></span>){</span><br><span class="line"><span class="variable language_">this</span>.<span class="property">name</span> = name;</span><br><span class="line"><span class="variable language_">this</span>.<span class="property">breed</span> = breed;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">makeNoise</span>(<span class="params"></span>){</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">noise</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">feed</span>(<span class="params">something: <span class="built_in">string</span></span>){</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`<span class="subst">${<span class="variable language_">this</span>.name}</span> is eating <span class="subst">${something}</span>...`</span>)</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="搭配-interface-常用的方法"><a href="#搭配-interface-常用的方法" class="headerlink" title="搭配 interface 常用的方法"></a>搭配 interface 常用的方法</h2><ol><li>extends</li></ol><ul><li>以 <code>PersonalInfo</code> 為例</li></ul><figure class="highlight typescript"><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><span class="line"><span class="keyword">interface</span> <span class="title class_">PersonalInfo</span>{</span><br><span class="line"><span class="attr">name</span>: <span class="built_in">string</span>;</span><br><span class="line"><span class="attr">age</span>: <span class="built_in">number</span>;</span><br><span class="line"><span class="attr">interesting</span>: <span class="built_in">string</span>[];</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>假設今天想宣告一個新的使用者帳戶的介面為 <code>UserAccount</code><ul><li>除了有一些和客戶相關的規格屬性外,還要包含介面 <code>PersonalInfo</code> 裡的規格</li></ul></li></ul><figure class="highlight typescript"><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><span class="line"><span class="keyword">interface</span> <span class="title class_">UserAccount</span> <span class="keyword">extends</span> <span class="title class_">PersonalInfo</span>{</span><br><span class="line"><span class="attr">email</span>: <span class="built_in">string</span>;</span><br><span class="line"><span class="attr">password</span>: <span class="built_in">string</span>;</span><br><span class="line"><span class="attr">subscribed</span>: <span class="built_in">boolean</span>;</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>上面的撰寫方式,等同於</li><li>透過使用 extends 延展可以將功用的屬性、型別整理一起</li></ul><figure class="highlight typescript"><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><span class="line"><span class="keyword">interface</span> <span class="title class_">UserAccount</span>{</span><br><span class="line"><span class="attr">email</span>: <span class="built_in">string</span>;</span><br><span class="line"><span class="attr">password</span>: <span class="built_in">string</span>;</span><br><span class="line"><span class="attr">subscribed</span>: <span class="built_in">boolean</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//從PersonalInfo延展而來</span></span><br><span class="line"><span class="attr">name</span>: <span class="built_in">string</span>;</span><br><span class="line"><span class="attr">age</span>: <span class="built_in">number</span>;</span><br><span class="line"><span class="attr">interesting</span>: <span class="built_in">string</span>[];</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>另外若需要再合併新的型別,也可以透過逗號方式加以延伸</p><ul><li>此外還能再多新增 <code>SocialLinks</code></li></ul><figure class="highlight typescript"><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><span class="line"><span class="keyword">interface</span> <span class="title class_">SocialLinks</span> {</span><br><span class="line">facebook?: <span class="built_in">string</span>;</span><br><span class="line">twitter?: <span class="built_in">string</span>;</span><br><span class="line">linkedin?: <span class="built_in">string</span>;</span><br><span class="line">website?: ({<span class="attr">name</span>:<span class="built_in">string</span>; <span class="attr">url</span>:<span class="built_in">string</span>})[]</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>同時延展:透過逗號再加入新的</li></ul><figure class="highlight typescript"><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><span class="line"><span class="keyword">interface</span> <span class="title class_">UserAccount</span> <span class="keyword">extends</span> <span class="title class_">PersonalInfo</span>, <span class="title class_">SocialLinks</span>{</span><br><span class="line"><span class="comment">//...</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="pick"><a href="#pick" class="headerlink" title="pick"></a>pick</h2><p>Picking Items with <code>Pick<Type, Keys></code></p><ul><li>挑選想要的屬性(key)做使用</li><li>注意 pick 只能在 type 宣告使用</li></ul><figure class="highlight typescript"><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><span class="line"><span class="keyword">interface</span> <span class="title class_">Todo</span> {</span><br><span class="line"> <span class="attr">title</span>: <span class="built_in">string</span>;</span><br><span class="line"> <span class="attr">description</span>: <span class="built_in">string</span>;</span><br><span class="line"> <span class="attr">completed</span>: <span class="built_in">boolean</span>;</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line"><span class="keyword">type</span> <span class="title class_">TodoPreview</span> = <span class="title class_">Pick</span><<span class="title class_">Todo</span>, <span class="string">"title"</span> | <span class="string">"completed"</span>>;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">const</span> <span class="attr">todo</span>: <span class="title class_">TodoPreview</span> = {</span><br><span class="line"> <span class="attr">title</span>: <span class="string">"Clean room"</span>,</span><br><span class="line"> <span class="attr">completed</span>: <span class="literal">false</span>,</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(todo.<span class="property">title</span>); <span class="comment">// "Clean room"</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(todo.<span class="property">description</span>); <span class="comment">// undefined</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><ul><li>注意 pick 只能在 type 宣告使用<figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">interface</span> todo = <span class="title class_">Pick</span><<span class="title class_">Todo</span>, "title" | "completed">;</span><br><span class="line">// '<span class="title class_">Pick</span>' only refers to a type, but is being used as a value here.</span><br></pre></td></tr></table></figure></li></ul><h2 id="omit"><a href="#omit" class="headerlink" title="omit"></a>omit</h2><p><code>Omit<Type, Keys></code></p><figure class="highlight typescript"><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><span class="line"><span class="keyword">interface</span> <span class="title class_">Todo</span> {</span><br><span class="line"> <span class="attr">title</span>: <span class="built_in">string</span>;</span><br><span class="line"> <span class="attr">description</span>: <span class="built_in">string</span>;</span><br><span class="line"> <span class="attr">completed</span>: <span class="built_in">boolean</span>;</span><br><span class="line"> <span class="attr">createdAt</span>: <span class="built_in">number</span>;</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line"><span class="keyword">type</span> <span class="title class_">TodoPreview</span> = <span class="title class_">Omit</span><<span class="title class_">Todo</span>, <span class="string">"description"</span>>;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">const</span> <span class="attr">todo</span>: <span class="title class_">TodoPreview</span> = {</span><br><span class="line"> <span class="attr">title</span>: <span class="string">"Clean room"</span>,</span><br><span class="line"> <span class="attr">completed</span>: <span class="literal">false</span>,</span><br><span class="line"> <span class="attr">createdAt</span>: <span class="number">1615544252770</span>,</span><br><span class="line">};</span><br><span class="line"> </span><br></pre></td></tr></table></figure><p>參考資料<br><a href="https://refine.dev/blog/typescript-pick-utility-type/">A Detailed Guide on TypeScript Pick Type</a></p>]]></content>
<summary type="html"><p><img src="https://i.imgur.com/xGK5aDO.png" alt=""></p>
<p>最近在複習使用 TypeScript 發現還有些部分可以做紀錄並且重新回憶的區塊,藉此再紀錄於部落格。</p>
<h2 id="TS-interface的基礎</summary>
<category term="TypeScript" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/TypeScript/"/>
<category term="TypeScript" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/TypeScript/"/>
</entry>
<entry>
<title>Leetcode rotate-image</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2022/12/21/rotate-image/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2022/12/21/rotate-image/</id>
<published>2022-12-21T01:46:00.000Z</published>
<updated>2022-12-21T09:56:31.016Z</updated>
<content type="html"><![CDATA[<p>一開始看到題目,看到2維陣列就會有些緊張,想著是否要拆開,或是要如何從圖示去轉陣列,寫得很亂又雜還是解不出來。<br>看完其他教學才知道可以從斜對角開始調換,最後再將左右做調換。</p><p>You are given an n x n 2D matrix representing an image, rotate the image by 90 degrees (clockwise).</p><p>You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation.</p><p> <img src="https://i.imgur.com/0khxyek.png" alt=""></p><p><img src="https://i.imgur.com/LjKoWWh.jpg" alt=""></p><figure class="highlight javascript"><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><span class="line"><span class="keyword">var</span> rotate = <span class="keyword">function</span> (<span class="params">matrix</span>) {</span><br><span class="line"> <span class="comment">//斜對角</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i < matrix.<span class="property">length</span>; i++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> j = <span class="number">0</span>; j < matrix.<span class="property">length</span>; j++) {</span><br><span class="line"> <span class="keyword">let</span> temp = matrix[i][j];</span><br><span class="line"> matrix[i][j] = matrix[j][i];</span><br><span class="line"> matrix[j][i] = temp;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//reverse</span></span><br><span class="line"> <span class="comment">// Secondly Make Reflected Image Of Matrix</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i < matrix.<span class="property">length</span>; i++) {</span><br><span class="line"> <span class="comment">//最左和最右調換,為兩兩調換,所以j的長度為matrix長度除以2</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> j = <span class="number">0</span>; j < matrix.<span class="property">length</span> / <span class="number">2</span>; j++) {</span><br><span class="line"> <span class="keyword">var</span> <span class="title class_">Temp</span> = matrix[i][j]</span><br><span class="line"> <span class="comment">//右側最後的值為長度-1</span></span><br><span class="line"> matrix[i][j] = matrix[i][matrix.<span class="property">length</span> - <span class="number">1</span> - j]</span><br><span class="line"> matrix[i][matrix.<span class="property">length</span> - <span class="number">1</span> - j] = <span class="title class_">Temp</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> matrix;</span><br><span class="line">};</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>參考資料:<br><a href="https://www.youtube.com/watch?v=swlO6KKh8yk">Rotate Image - LeetCode 48 - JavaScript</a></p>]]></content>
<summary type="html"><p>一開始看到題目,看到2維陣列就會有些緊張,想著是否要拆開,或是要如何從圖示去轉陣列,寫得很亂又雜還是解不出來。<br>看完其他教學才知道可以從斜對角開始調換,最後再將左右做調換。</p>
<p>You are given an n x n 2D matrix represe</summary>
<category term="Leetcode" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/Leetcode/"/>
<category term="Leetcode" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/Leetcode/"/>
</entry>
<entry>
<title>Redux Toolkit - RTK Query中間層非同步Fetch API的處理</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2022/12/01/React-Middleware/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2022/12/01/React-Middleware/</id>
<published>2022-12-01T04:55:30.000Z</published>
<updated>2022-12-01T13:08:43.844Z</updated>
<content type="html"><![CDATA[<p>當發起 dispatch 到 UI 更新之間做什麼事情</p><ul><li><p>希望 dispath 有能力可以再去做其他事情(所以會在過程中去做一些邏輯)</p></li><li><p>希望過程中可以再做些事情(UI 從 dispatch 到真正渲染之間)</p><p><img src="https://i.imgur.com/FROBvmD.png" alt=""><br><a href="https://redux.js.org/understanding/history-and-design/middleware">Middleware</a></p></li><li><p>實際上是一個 function</p></li><li><p>next 是 dispatch 的意思,next 所代表的是傳入 action ,會調用下一個 dispatch 來執行所傳入的這個 action </p></li></ul><p>以官網範例:</p><ul><li>他是 3 個函式包在一起</li></ul><figure class="highlight javascript"><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><span class="line"><span class="keyword">const</span> <span class="title function_">logger</span> = store => <span class="function"><span class="params">nextDispatch</span> =></span> <span class="function"><span class="params">action</span> =></span> { </span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'dispatching'</span>, action) </span><br><span class="line"><span class="keyword">let</span> result = <span class="title function_">nextDispatch</span>(action) </span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'next state'</span>, store.<span class="title function_">getState</span>()) </span><br><span class="line"><span class="keyword">return</span> result </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>在專案建立<br>位置:src / middleware</p><h3 id="簡易說明"><a href="#簡易說明" class="headerlink" title="簡易說明"></a>簡易說明</h3><p>在 return 最後的 function 之前,第二個 function 就是將原有的 dispatch 丟到最後的 function 中,再 return 出去。<br>在取的 dispatch 之前,會再拿到 store 也是使用 api 時候會回傳進來的東西。<br>當 middleware 建立好之後,要到 store 當案進行宣告</p><h3 id="combineReducers"><a href="#combineReducers" class="headerlink" title="combineReducers"></a>combineReducers</h3><ul><li>建立的 slice夾中可能會有多個 reducer,例如 todoReducer, friendReducer, phoneReduce…</li></ul><p>Middleware 與 store 的建立<br><img src="https://i.imgur.com/H7EOAfX.png" alt=""></p><p>在 middleware 去寫功能的時後,主要分為兩個部分</p><ol><li>在 dispach 之前要做什麼事情</li><li>在 dispach 之後要做什麼事情</li></ol><h2 id="RTK-Query"><a href="#RTK-Query" class="headerlink" title="RTK Query"></a>RTK Query</h2><p>使用 middileware 去定義我們的 reducers 會分成多個階段</p><ul><li>pedding</li><li>success</li><li>error<br>針對每一次 API 取資料,加入到 reducers 中,此方式會使得 reducer 變得龐大、複雜。<br>RTK Query 協助將所有關於 call API 或是 獲取資料過程的功能,將他包裝成一個攻能,並且完全獨立於 reducer 或 redux 的邏輯</li><li>可以使用 RTK Query 中的 hook 去獲取當前 data , error 狀態等<br><a href="https://redux-toolkit.js.org/rtk-query/overview">官方文件</a></li></ul><h2 id="建立-api"><a href="#建立-api" class="headerlink" title="建立 api"></a>建立 api</h2><p>educerPath => 最後會產生 reducer ,所包含內容會有 pedding, success,error 等狀態<br>baseQuery => 就是放入 baseUrl<br>endpoint => 放入 query 資訊<br> any : 表示會回傳一個 any 結果<br> string : 需要傳入 string 的 input </p><p>json placeholder</p><p><img src="https://i.imgur.com/40MQaiu.png" alt=""></p><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> { createApi, fetchBaseQuery } <span class="keyword">from</span> <span class="string">'@reduxjs/toolkit/query/react'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> todoApiService = <span class="title function_">createApi</span>({</span><br><span class="line"></span><br><span class="line"><span class="attr">reducerPath</span>: <span class="string">'todoApi'</span>,</span><br><span class="line"></span><br><span class="line"><span class="attr">baseQuery</span>: <span class="title function_">fetchBaseQuery</span>({ <span class="attr">baseUrl</span>: <span class="string">'https://jsonplaceholder.typicode.com/'</span> }),</span><br><span class="line"></span><br><span class="line"><span class="attr">endpoints</span>: <span class="function">(<span class="params">builder</span>) =></span> ({</span><br><span class="line"></span><br><span class="line"><span class="comment">// getPokemonByName: builder.query<Pokemon, string>({</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// query: (name) => `pokemon/${name}`,</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// }),</span></span><br><span class="line"></span><br><span class="line"><span class="attr">getTodoApi</span>: builder.<span class="property">query</span><any, string>({</span><br><span class="line"></span><br><span class="line"><span class="attr">query</span>: <span class="function">(<span class="params">id</span>) =></span> <span class="string">`todos/<span class="subst">${id}</span>`</span>,</span><br><span class="line"></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line">}),</span><br><span class="line"></span><br><span class="line">})</span><br><span class="line"><span class="comment">// Export hooks for usage in functional components, which are </span></span><br><span class="line"><span class="comment">// auto-generated based on the defined endpoints </span></span><br><span class="line"><span class="comment">// 以下會自動對應產生</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> { useGetTodoApiQuery } = todoApiService</span><br></pre></td></tr></table></figure><h2 id="至-store-新增-todoAPI"><a href="#至-store-新增-todoAPI" class="headerlink" title="至 store 新增 todoAPI"></a>至 store 新增 todoAPI</h2><p><img src="https://i.imgur.com/ChMTJOz.png" alt=""></p><h2 id="引用-API-hook"><a href="#引用-API-hook" class="headerlink" title="引用 API hook"></a>引用 API hook</h2><p><code>import { useGetTodoApiQuery } from './services/todoApi';</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><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><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="string">'./App.css'</span>;</span><br><span class="line"><span class="keyword">import</span> styled <span class="keyword">from</span> <span class="string">'styled-components'</span></span><br><span class="line"><span class="keyword">import</span> { useAppSelector, useAppDispatch } <span class="keyword">from</span> <span class="string">'./hooks'</span>;</span><br><span class="line"><span class="keyword">import</span> { addTodo, addTimestamp } <span class="keyword">from</span> <span class="string">'./slice/todo'</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, { useState } <span class="keyword">from</span> <span class="string">'react'</span>;</span><br><span class="line"><span class="keyword">import</span> { useGetTodoApiQuery } <span class="keyword">from</span> <span class="string">'./services/todoApi'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">Wrapper</span> = styled.<span class="property">div</span><span class="string">`</span></span><br><span class="line"><span class="string"> padding: 1.5rem;</span></span><br><span class="line"><span class="string">`</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">Title</span> = styled.<span class="property">h2</span><span class="string">`</span></span><br><span class="line"><span class="string"> font-weight: 900;</span></span><br><span class="line"><span class="string"> margin-top: 2rem;</span></span><br><span class="line"><span class="string">`</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">NoteInput</span> = styled.<span class="property">input</span><span class="string">`</span></span><br><span class="line"><span class="string"> width: 100%;</span></span><br><span class="line"><span class="string"> height: 40px;</span></span><br><span class="line"><span class="string"> border-radius: 10px;</span></span><br><span class="line"><span class="string"> padding-left: .5rem;</span></span><br><span class="line"><span class="string"> box-sizing: border-box;</span></span><br><span class="line"><span class="string">`</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">SubmitBtn</span> = styled.<span class="property">button</span><span class="string">`</span></span><br><span class="line"><span class="string"> width: 100%;</span></span><br><span class="line"><span class="string"> box-sizing: border-box;</span></span><br><span class="line"><span class="string"> height: 40px;</span></span><br><span class="line"><span class="string"> background: #000;</span></span><br><span class="line"><span class="string"> display: flex;</span></span><br><span class="line"><span class="string"> justify-content: center;</span></span><br><span class="line"><span class="string"> align-items: center;</span></span><br><span class="line"><span class="string"> color: #fff;</span></span><br><span class="line"><span class="string"> border-radius: 10px;</span></span><br><span class="line"><span class="string"> border: 0;</span></span><br><span class="line"><span class="string"> font-weight: 900;</span></span><br><span class="line"><span class="string"> margin-top: 1rem;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"> :active {</span></span><br><span class="line"><span class="string"> background: #000000be;</span></span><br><span class="line"><span class="string"> }</span></span><br><span class="line"><span class="string">`</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">Item</span> = styled.<span class="property">div</span><span class="string">`</span></span><br><span class="line"><span class="string"> margin-top: 1rem;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"> > b {</span></span><br><span class="line"><span class="string"> margin-right: .5rem;</span></span><br><span class="line"><span class="string"> }</span></span><br><span class="line"><span class="string">`</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">App</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">const</span> todoReducer = <span class="title function_">useAppSelector</span>(<span class="function"><span class="params">state</span> =></span> state.<span class="property">todoReducer</span>)</span><br><span class="line"> <span class="keyword">const</span> todoList = todoReducer.<span class="property">todoList</span></span><br><span class="line"> <span class="keyword">const</span> dispatch = <span class="title function_">useAppDispatch</span>()</span><br><span class="line"> <span class="keyword">const</span> [text, setText] = <span class="title function_">useState</span>(<span class="string">""</span>)</span><br><span class="line"> <span class="keyword">const</span> { data, error, isLoading } = <span class="title function_">useGetTodoApiQuery</span>(<span class="string">'1'</span>)</span><br><span class="line"> <span class="comment">//api 獲取資料</span></span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'data:'</span>, data)</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'error:'</span>, error)</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'isLoading:'</span>, isLoading)</span><br><span class="line"></span><br><span class="line"> <span class="comment">//處裡 data 可能 undefined 的問題</span></span><br><span class="line"> <span class="keyword">const</span> { userId = <span class="string">'N/A'</span>, title = <span class="string">'N/A'</span> } = data || {}</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">Wrapper</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">Title</span>></span>TODO LIST<span class="tag"></<span class="name">Title</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">NoteInput</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">value</span>=<span class="string">{text}</span> <span class="attr">onChange</span>=<span class="string">{(e:</span> <span class="attr">React.ChangeEvent</span><<span class="attr">HTMLInputElement</span>></span>) => {</span></span><br><span class="line"><span class="language-xml"> setText(e.target.value)</span></span><br><span class="line"><span class="language-xml"> }} /></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">SubmitBtn</span> <span class="attr">onClick</span>=<span class="string">{()</span> =></span> {</span></span><br><span class="line"><span class="language-xml"> if (text === '') {</span></span><br><span class="line"><span class="language-xml"> alert('請輸入TODO內容')</span></span><br><span class="line"><span class="language-xml"> return</span></span><br><span class="line"><span class="language-xml"> }</span></span><br><span class="line"><span class="language-xml"> dispatch(addTodo(text))</span></span><br><span class="line"><span class="language-xml"> setText('')</span></span><br><span class="line"><span class="language-xml"> }}></span></span><br><span class="line"><span class="language-xml"> Submit</span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">SubmitBtn</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">SubmitBtn</span> <span class="attr">onClick</span>=<span class="string">{()</span> =></span> {</span></span><br><span class="line"><span class="language-xml"> dispatch(addTimestamp())</span></span><br><span class="line"><span class="language-xml"> }}></span></span><br><span class="line"><span class="language-xml"> Record Timestamp</span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">SubmitBtn</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">Title</span>></span>List<span class="tag"></<span class="name">Title</span>></span></span></span><br><span class="line"><span class="language-xml"> {</span></span><br><span class="line"><span class="language-xml"> todoList.map((todo, index) => {</span></span><br><span class="line"><span class="language-xml"> return <span class="tag"><<span class="name">Item</span> <span class="attr">key</span>=<span class="string">{todo}</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">b</span>></span>{index + 1}<span class="tag"></<span class="name">b</span>></span></span></span><br><span class="line"><span class="language-xml"> {todo}</span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">Item</span>></span></span></span><br><span class="line"><span class="language-xml"> })</span></span><br><span class="line"><span class="language-xml"> }</span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">Title</span>></span>List2<span class="tag"></<span class="name">Title</span>></span></span></span><br><span class="line"><span class="language-xml"> {</span></span><br><span class="line"><span class="language-xml"> isLoading && <span class="tag"><<span class="name">p</span>></span> 正在載入資料...<span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> }</span></span><br><span class="line"><span class="language-xml"> {</span></span><br><span class="line"><span class="language-xml"> !isLoading &&</span></span><br><span class="line"><span class="language-xml"> (</span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">div</span>></span></span></span><br><span class="line"><span class="language-xml"> {/* <span class="tag"><<span class="name">p</span>></span>User ID:{data?.userId}<span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">p</span>></span>Usr Title:{data?.title}<span class="tag"></<span class="name">p</span>></span> */}</span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">p</span>></span>User ID:{userId}<span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">p</span>></span>Usr Title:{title}<span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="language-xml"> )</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"> }</span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">Wrapper</span>></span></span></span><br><span class="line"><span class="language-xml"> );</span></span><br><span class="line"><span class="language-xml">}</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">export default App;</span></span><br><span class="line"><span class="language-xml"></span></span><br></pre></td></tr></table></figure><p>若是使用 react thunk </p><ul><li>這裡的 middleware 的 reducer 中的 status 要自己去定義</li><li>優點:可以完全掌控自己 reducer 的內容</li><li>但相對也會較為繁瑣</li></ul>]]></content>
<summary type="html"><p>當發起 dispatch 到 UI 更新之間做什麼事情</p>
<ul>
<li><p>希望 dispath 有能力可以再去做其他事情(所以會在過程中去做一些邏輯)</p>
</li>
<li><p>希望過程中可以再做些事情(UI 從 dispatch 到真正渲染之間)</</summary>
<category term="React" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/React/"/>
<category term="React" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/React/"/>
</entry>
<entry>
<title>Redux Toolkit</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2022/12/01/ReduxToolkit/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2022/12/01/ReduxToolkit/</id>
<published>2022-12-01T04:03:04.000Z</published>
<updated>2022-12-01T13:07:07.117Z</updated>
<content type="html"><![CDATA[<p>安裝:<br><a href="https://redux.js.org/introduction/installation">官網安裝</a></p><p>此範例來自 Bruce 前端課程,使用 todoList 來練習</p><ul><li>從官網學習基礎設定</li></ul><ol><li>建立 store 同時,撰寫 reducer(會自動產生出對應 reducer 的 action)<ol><li>action 如同 dispatch 所送出的包裹</li><li>reducer 會去拆解包裹,以了解用戶想做的事<br>應用於 todo-list</li></ol></li><li>store 中會存有幾條備忘錄,幾條 todo視像要做</li><li>建立資料夾 src / slice ,此 slice 中包含 reducer, action<br><a href="https://redux.js.org/tutorials/typescript-quick-start">TS-設立tool-kit</a><br>建立 store 的方式,要先建立 reducer</li></ol><h3 id="src-slice-todo-ts"><a href="#src-slice-todo-ts" class="headerlink" title="src / slice / todo.ts"></a>src / slice / todo.ts</h3><ul><li>建立 slice,並注意要傳入三個參數<ul><li>name : slice 的名字</li><li>initialState 初始化的 state,建立初始狀態得值以及型別</li></ul></li></ul><figure class="highlight javascript"><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><span class="line"><span class="keyword">import</span> { createSlice } <span class="keyword">from</span> <span class="string">'@reduxjs/toolkit'</span></span><br><span class="line"><span class="comment">// Define a type for the slice state </span></span><br><span class="line">interface todoState { </span><br><span class="line"> <span class="attr">todoList</span>: <span class="title class_">Array</span><string></span><br><span class="line">}</span><br><span class="line"><span class="keyword">const</span> <span class="attr">initialState</span>: todoState = { </span><br><span class="line"> <span class="attr">todoList</span>: [] </span><br><span class="line">}</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> todoSlice = <span class="title function_">createSlice</span>({ </span><br><span class="line"><span class="attr">name</span>:<span class="string">'todo'</span>,</span><br><span class="line">initialState,</span><br><span class="line"><span class="attr">reducers</span>:{</span><br><span class="line"><span class="comment">//state:當下狀態</span></span><br><span class="line"><span class="comment">//action:對應的動作</span></span><br><span class="line"><span class="attr">addTodo</span>: <span class="function">(<span class="params">state,action</span>)=></span>{</span><br><span class="line">state.<span class="property">todoList</span>.<span class="title function_">push</span>(action.<span class="property">payload</span>)</span><br><span class="line">},</span><br><span class="line"><span class="attr">addTimestamp</span>:<span class="function">(<span class="params">state</span>)=></span>{</span><br><span class="line">state.<span class="property">todoList</span>.<span class="title function_">push</span>(<span class="title class_">Date</span>.<span class="title function_">now</span>().<span class="title function_">toString</span>())</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">} </span><br><span class="line">})</span><br></pre></td></tr></table></figure><p>在此範例中會有兩個 dispatch</p><ol><li>submit</li><li>record timestamp</li></ol><ul><li>dispatch 會發出上面兩個 action </li><li>reducer 要兩個事件接收<br>最後的 export todoSlice</li><li>todoSlice 中會包含 actions , reducer , 以及其他 API</li></ul><h2 id="建立-store"><a href="#建立-store" class="headerlink" title="建立 store"></a>建立 store</h2><ol><li>位置 src / store.ts<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> { configureStore } <span class="keyword">from</span> <span class="string">'@reduxjs/toolkit'</span></span><br></pre></td></tr></table></figure></li></ol><p><img src="https://i.imgur.com/41RnyWT.png" alt=""></p><p>從上面過程,可以看到我們 store, action , reducer 都撰寫完成</p><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><ul><li>回到 UI 觸發狀態改變的地方 </li><li><ol><li>index.tsx 裝入 store<ul><li>像是 context 的概念作為 context provider 的內容</li></ul></li></ol></li></ul><figure class="highlight javascript"><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><span class="line"><span class="keyword">import</span> { <span class="title class_">Provider</span> } <span class="keyword">from</span> <span class="string">"react-redux"</span>;</span><br><span class="line"><span class="keyword">import</span> store <span class="keyword">from</span> <span class="string">'./store'</span></span><br><span class="line"><span class="title class_">ReactDOM</span>.<span class="title function_">render</span>(</span><br><span class="line"></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">React.StrictMode</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">Provider</span> <span class="attr">store</span>=<span class="string">{store}</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">App</span> /></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">Provider</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">React.StrictMode</span>></span></span>,</span><br><span class="line"></span><br><span class="line"><span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">'root'</span>)</span><br><span class="line"></span><br><span class="line">);</span><br></pre></td></tr></table></figure><p>拿到 store 中的 todoList 來使用渲染於畫面</p><ul><li>要如何拿到 store ? 使用 useSelector</li><li>在這裡要注意因為使用 TS 所以會有類型定義問題!<ul><li>src / hooks.tsx</li></ul></li></ul><ol><li>型別首先要來自於 store 檔案</li></ol><ul><li>ReturnType: 幫我們將 store 中的內容,直接導出對應的 type</li></ul><p><code>export type RootState = ReturnType<typeof store.getState></code></p><ol start="2"><li>回到 hooks 建立定義好型別的 API</li></ol><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="attr">useAppSelector</span>: <span class="title class_">TypedUseSelectorHook</span><<span class="title class_">RootState</span>> = useSelector</span><br></pre></td></tr></table></figure><ol start="3"><li>可以 到 App 檔案或相關的子組件都可以調用 store 的內容<ul><li>可以拿到預設的 state </li></ul></li></ol><figure class="highlight javascript"><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><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> { useAppSelector } <span class="keyword">from</span> <span class="string">'./hooks'</span>;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">App</span>(<span class="params"></span>) {</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> todoReducer = <span class="title function_">useAppSelector</span>(<span class="function"><span class="params">state</span> =></span> state.<span class="property">todoReducer</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> todoList = todoReducer.<span class="property">todoList</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> (</span><br><span class="line"></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">Wrapper</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">Title</span>></span>TODO LIST<span class="tag"></<span class="name">Title</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">NoteInput</span> <span class="attr">type</span>=<span class="string">"text"</span> /></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">SubmitBtn</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">Submit</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">SubmitBtn</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">SubmitBtn</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">Record Timestamp</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">SubmitBtn</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">Title</span>></span>List<span class="tag"></<span class="name">Title</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">{</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">todoList.map((todo, index) => {</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">return <span class="tag"><<span class="name">Item</span> <span class="attr">key</span>=<span class="string">{todo}</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">b</span>></span>{index + 1}<span class="tag"></<span class="name">b</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">{todo}</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">Item</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">})</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">}</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">Wrapper</span>></span></span></span><br><span class="line"></span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">App</span>;</span><br></pre></td></tr></table></figure><h3 id="狀態更新"><a href="#狀態更新" class="headerlink" title="狀態更新"></a>狀態更新</h3><ul><li>使用 dispatch 一些 action</li><li>定義 useDispatch </li></ul><ol><li>hooks<figure class="highlight javascript"><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><span class="line"><span class="keyword">import</span> { <span class="title class_">TypedUseSelectorHook</span>, useDispatch, useSelector } <span class="keyword">from</span> <span class="string">'react-redux'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> type { <span class="title class_">RootState</span>, <span class="title class_">AppDispatch</span> } <span class="keyword">from</span> <span class="string">'./store'</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//自定義 hook</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Use throughout your app instead of plain `useDispatch` and `useSelector`</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="attr">useAppDispatch</span>: <span class="function">() =></span> <span class="title class_">AppDispatch</span> = useDispatch</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="attr">useAppSelector</span>: <span class="title class_">TypedUseSelectorHook</span><<span class="title class_">RootState</span>> = useSelector</span><br></pre></td></tr></table></figure></li><li>store.ts</li></ol><figure class="highlight javascript"><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><span class="line"><span class="keyword">import</span> { configureStore } <span class="keyword">from</span> <span class="string">'@reduxjs/toolkit'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> todoReducer <span class="keyword">from</span> <span class="string">'./slice/todo'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> store = <span class="title function_">configureStore</span>({</span><br><span class="line"></span><br><span class="line"><span class="attr">reducer</span>: {</span><br><span class="line"></span><br><span class="line">todoReducer</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// Infer the `RootState` and `AppDispatch` types from the store itself</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//匯出對應的類型</span></span><br><span class="line"><span class="keyword">export</span> type <span class="title class_">RootState</span> = <span class="title class_">ReturnType</span><<span class="keyword">typeof</span> store.<span class="property">getState</span>></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> type <span class="title class_">AppDispatch</span> = <span class="keyword">typeof</span> store.<span class="property">dispatch</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> store</span><br></pre></td></tr></table></figure><p>到 App.tsx 使用 dispatch</p><ul><li>宣告 dispatch</li><li>設置 setState 的值</li><li>綁定於 input 並讓 input onchange 時去觸發值得改變</li></ul><figure class="highlight javascript"><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><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="string">'./App.css'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> styled <span class="keyword">from</span> <span class="string">'styled-components'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> { useAppSelector, useAppDispatch } <span class="keyword">from</span> <span class="string">'./hooks'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> { addTodo, addTimestamp } <span class="keyword">from</span> <span class="string">'./slice/todo'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, { useState } <span class="keyword">from</span> <span class="string">'react'</span>;</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"><span class="keyword">function</span> <span class="title function_">App</span>(<span class="params"></span>) {</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> todoReducer = <span class="title function_">useAppSelector</span>(<span class="function"><span class="params">state</span> =></span> state.<span class="property">todoReducer</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> todoList = todoReducer.<span class="property">todoList</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> dispatch = <span class="title function_">useAppDispatch</span>()</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> [text, setText] = <span class="title function_">useState</span>(<span class="string">""</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> (</span><br><span class="line"></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">Wrapper</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">Title</span>></span>TODO LIST<span class="tag"></<span class="name">Title</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">NoteInput</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">value</span>=<span class="string">{text}</span> <span class="attr">onChange</span>=<span class="string">{(e:</span> <span class="attr">React.ChangeEvent</span><<span class="attr">HTMLInputElement</span>></span>) => {</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">setText(e.target.value)</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">}} /></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">SubmitBtn</span> <span class="attr">onClick</span>=<span class="string">{()</span> =></span> {</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">if (text === '') {</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">alert('請輸入TODO內容')</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">return</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">}</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">dispatch(addTodo(text))</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">setText('')</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">}}></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">Submit</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">SubmitBtn</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">SubmitBtn</span> <span class="attr">onClick</span>=<span class="string">{()</span> =></span> {</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">dispatch(addTimestamp())</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">}}></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">Record Timestamp</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">SubmitBtn</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">Title</span>></span>List<span class="tag"></<span class="name">Title</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">{</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">todoList.map((todo, index) => {</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">return <span class="tag"><<span class="name">Item</span> <span class="attr">key</span>=<span class="string">{todo}</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">b</span>></span>{index + 1}<span class="tag"></<span class="name">b</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">{todo}</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">Item</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">})</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">}</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">Wrapper</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">);</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">}</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"> </span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">export default App;</span></span><br></pre></td></tr></table></figure><h2 id="總結步驟"><a href="#總結步驟" class="headerlink" title="總結步驟"></a>總結步驟</h2><ol><li>定義 slice 中的內容,其中包含 初始的資料定義、 reducers<ol><li>reducers 會透過 toolkit 這工具,將對應得 action 產生出來</li><li>action 可以在 dispatch 做發送時帶出去</li></ol></li><li>定義 provider 作為將 store 資料傳入的橋樑</li><li>store 的產生:來自於將 slice 中的 reducers 建立好之後可以隨之建立的內容</li><li>建立 hooks :撰寫自定義的 hook ,將原本內建的 hook 進行重新包裝</li></ol>]]></content>
<summary type="html"><p>安裝:<br><a href="https://redux.js.org/introduction/installation">官網安裝</a></p>
<p>此範例來自 Bruce 前端課程,使用 todoList 來練習</p>
<ul>
<li>從官網學習基礎設定</</summary>
<category term="React" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/React/"/>
<category term="React" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/React/"/>
</entry>
<entry>
<title>React - 建立元件</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2022/11/22/react-component/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2022/11/22/react-component/</id>
<published>2022-11-22T02:36:50.000Z</published>
<updated>2022-11-26T10:15:38.217Z</updated>
<content type="html"><![CDATA[<p><img src="https://i.imgur.com/VykOAkm.png" alt=""></p><p>前段時間練習了一些 React 的基礎,對於 JSX 以及一些 hook 的用法比較有概念,所以就以 Bruce 的 React 課程實作再來練習,樣式部分以 Tailwind 為主此外也搭配 TS 來撰寫。</p><h2 id="1-Header"><a href="#1-Header" class="headerlink" title="1. Header"></a>1. Header</h2><ul><li>製作 IGHeader 元件,因為到不同頁面都會有 header 存在,所以可以將它放在外面的共用元件。</li></ul><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><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title class_">IGHeader</span>: <span class="title class_">React</span>.<span class="property">FC</span> = <span class="function">() =></span> {</span><br><span class="line"> <span class="keyword">const</span> go = <span class="title function_">useNavigate</span>()</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">header</span> <span class="attr">className</span>=<span class="string">"sticky top-0 border-b-[1px] bg-white border-gray-300 "</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">div</span> <span class="attr">className</span>=<span class="string">"flex justify-between items-center h-[60px] px-2 lg:max-w-[1024px] lg:mx-auto lg:px-0"</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">img</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">className</span>=<span class="string">"w-[100px] cursor-pointer"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">src</span>=<span class="string">"/images/logo.svg"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> /></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">div</span> <span class="attr">className</span>=<span class="string">"flex"</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">svg</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">xmlns</span>=<span class="string">"http://www.w3.org/2000/svg"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">className</span>=<span class="string">"h-6 w-6 mr-4 cursor-pointer"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">fill</span>=<span class="string">"none"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">viewBox</span>=<span class="string">"0 0 24 24"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">stroke</span>=<span class="string">"currentColor"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">onClick</span>=<span class="string">{()</span> =></span> go('/')}</span></span><br><span class="line"><span class="language-xml"> ></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">path</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">strokeLinecap</span>=<span class="string">"round"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">strokeLinejoin</span>=<span class="string">"round"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">strokeWidth</span>=<span class="string">{2}</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">d</span>=<span class="string">"M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> /></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">svg</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">svg</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">xmlns</span>=<span class="string">"http://www.w3.org/2000/svg"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">className</span>=<span class="string">"h-6 w-6 mr-4 cursor-pointer"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">fill</span>=<span class="string">"none"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">viewBox</span>=<span class="string">"0 0 24 24"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">stroke</span>=<span class="string">"currentColor"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">onClick</span>=<span class="string">{()</span> =></span> go('/following')}</span></span><br><span class="line"><span class="language-xml"> ></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">path</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">strokeLinecap</span>=<span class="string">"round"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">strokeLinejoin</span>=<span class="string">"round"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">strokeWidth</span>=<span class="string">{2}</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">d</span>=<span class="string">"M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> /></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">svg</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">div</span> <span class="attr">className</span>=<span class="string">" h-6 w-6 text-white bg-gray-900 font-bold flex rounded-full justify-center items-center"</span>></span></span></span><br><span class="line"><span class="language-xml"> E</span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">header</span>></span></span></span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="2-IGContainer"><a href="#2-IGContainer" class="headerlink" title="2. IGContainer"></a>2. IGContainer</h2><p>頁面佈局設定,除了 限時動態頁面會呈現外,在追蹤者頁面也會使用到</p><ul><li>使用 Tailwind 設定左右版面以及當螢幕不同尺寸的設定</li><li>將樣式寫在(style.div 裏面),作為一個組件 export 出去</li></ul><h2 id="3-限時動態列表(IGStory)"><a href="#3-限時動態列表(IGStory)" class="headerlink" title="3. 限時動態列表(IGStory)"></a>3. 限時動態列表(IGStory)</h2><p> <img src="https://i.imgur.com/jzE9sAZ.png" alt=""></p><ul><li>因隸屬於 home 裡面的位置,所以可以將檔案,放在 home 資料夾中,屬於 home 中的組件<br>//通常在一份專案中不用引入兩個 css 框架<br>實作:<ol start="2"><li>List Container 的容器<br><a href="https://tailwindcss.com/docs/overflow#scrolling-horizontally-if-needed">文件</a></li></ol><ul><li>在組建內部要使用 JS 相關的邏輯的寫法,要在要面用大括號刮起來</li><li>每一個小圖都是一個 item ,所以可以先製作組件</li></ul></li></ul><h3 id="限時動態-item-組件"><a href="#限時動態-item-組件" class="headerlink" title="限時動態 item 組件"></a>限時動態 item 組件</h3><ul><li>此組件建立其中的小項目</li></ul><figure class="highlight javascript"><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><span class="line"><span class="keyword">import</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">'react'</span></span><br><span class="line"></span><br><span class="line">type <span class="title class_">ItemProps</span> = {</span><br><span class="line"> <span class="attr">name</span>: string;</span><br><span class="line"> <span class="attr">avatar</span>: string;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">Item</span>: <span class="title class_">React</span>.<span class="property">FC</span><<span class="title class_">ItemProps</span>> = <span class="function">(<span class="params">{ name, avatar }</span>) =></span> {</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">div</span> <span class="attr">className</span>=<span class="string">" text-center "</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">div</span> <span class="attr">className</span>=<span class="string">" rounded-full w-[56px] h-[56px] ring-2 border-2 border-white ring-red-500 mx-[11px] p-[3px] "</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">style</span>=<span class="string">{{</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">backgroundImage:</span> `<span class="attr">url</span>(${<span class="attr">avatar</span>})`,</span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">backgroundPosition:</span> "<span class="attr">center</span>",</span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">backgroundSize:</span> "<span class="attr">cover</span>",</span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> }}></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">p</span> <span class="attr">className</span>=<span class="string">"text-xs mt-1"</span>></span>{name}<span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"> )</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">Item</span></span><br></pre></td></tr></table></figure><h3 id="外層"><a href="#外層" class="headerlink" title="外層"></a>外層</h3><ul><li>在外層的主要檔案,就是將模板建立好,讓 item 可以 map 進去</li></ul><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><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title class_">IGStory</span>: <span class="title class_">React</span>.<span class="property">FC</span> = <span class="function">() =></span> {</span><br><span class="line"> <span class="keyword">const</span> storyData = [</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"id"</span>: <span class="number">1</span>,</span><br><span class="line"> <span class="string">"name"</span>: <span class="string">"bruce_fe"</span>,</span><br><span class="line"> <span class="string">"avatar"</span>: <span class="string">"/images/avatars/a1.png"</span></span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"id"</span>: <span class="number">2</span>,</span><br><span class="line"> <span class="string">"name"</span>: <span class="string">"max"</span>,</span><br><span class="line"> <span class="string">"avatar"</span>: <span class="string">"/images/avatars/a2.png"</span></span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"id"</span>: <span class="number">3</span>,</span><br><span class="line"> <span class="string">"name"</span>: <span class="string">"fm"</span>,</span><br><span class="line"> <span class="string">"avatar"</span>: <span class="string">"/images/avatars/a3.png"</span></span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"id"</span>: <span class="number">4</span>,</span><br><span class="line"> <span class="string">"name"</span>: <span class="string">"joanne"</span>,</span><br><span class="line"> <span class="string">"avatar"</span>: <span class="string">"/images/avatars/a4.png"</span></span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"id"</span>: <span class="number">5</span>,</span><br><span class="line"> <span class="string">"name"</span>: <span class="string">"focus"</span>,</span><br><span class="line"> <span class="string">"avatar"</span>: <span class="string">"/images/avatars/a5.png"</span></span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"id"</span>: <span class="number">6</span>,</span><br><span class="line"> <span class="string">"name"</span>: <span class="string">"louis"</span>,</span><br><span class="line"> <span class="string">"avatar"</span>: <span class="string">"/images/avatars/a6.png"</span></span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"id"</span>: <span class="number">7</span>,</span><br><span class="line"> <span class="string">"name"</span>: <span class="string">"alvin"</span>,</span><br><span class="line"> <span class="string">"avatar"</span>: <span class="string">"/images/avatars/a7.png"</span></span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"id"</span>: <span class="number">8</span>,</span><br><span class="line"> <span class="string">"name"</span>: <span class="string">"grace"</span>,</span><br><span class="line"> <span class="string">"avatar"</span>: <span class="string">"/images/avatars/a8.png"</span></span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"id"</span>: <span class="number">9</span>,</span><br><span class="line"> <span class="string">"name"</span>: <span class="string">"rance"</span>,</span><br><span class="line"> <span class="string">"avatar"</span>: <span class="string">"/images/avatars/a9.png"</span></span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"id"</span>: <span class="number">10</span>,</span><br><span class="line"> <span class="string">"name"</span>: <span class="string">"bruce_fe"</span>,</span><br><span class="line"> <span class="string">"avatar"</span>: <span class="string">"/images/avatars/a10.png"</span></span><br><span class="line"> }</span><br><span class="line"> ]</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">div</span> <span class="attr">className</span>=<span class="string">'w-full flex items-center h-[110px] box-border overflow-x-auto overflow-y-hidden no-scrollbar shadow-md lg:my-8'</span>></span></span></span><br><span class="line"><span class="language-xml"> {/* <span class="tag"><<span class="name">Item</span> <span class="attr">name</span>=<span class="string">"Mike"</span> <span class="attr">avatar</span>=<span class="string">'/images/avatars/a1.png'</span> /></span> */}</span></span><br><span class="line"><span class="language-xml"> {</span></span><br><span class="line"><span class="language-xml"> storyData?.map((item) => {</span></span><br><span class="line"><span class="language-xml"> const { id, name, avatar } = item</span></span><br><span class="line"><span class="language-xml"> return <span class="tag"><<span class="name">Item</span> <span class="attr">key</span>=<span class="string">{id}</span> <span class="attr">name</span>=<span class="string">{name}</span> <span class="attr">avatar</span>=<span class="string">{avatar}</span> /></span></span></span><br><span class="line"><span class="language-xml"> })</span></span><br><span class="line"><span class="language-xml"> }</span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"> )</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">IGStory</span></span><br></pre></td></tr></table></figure><h2 id="3-User-組件"><a href="#3-User-組件" class="headerlink" title="3. User 組件"></a>3. User 組件</h2><ul><li>使用者資訊表,在不同區塊都有重複出現,所以可以抽成共用組件</li><li>現定義好 props 的型別</li><li>依照藥的版型來切出樣貌,將變數帶入</li></ul><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><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> <span class="title class_">IGUserProps</span> = {</span><br><span class="line"> size?: <span class="string">"medium"</span> | <span class="string">"small"</span>;</span><br><span class="line"> showFollow?: <span class="built_in">boolean</span>;</span><br><span class="line"> isFollowing?: <span class="built_in">boolean</span>;</span><br><span class="line"> account?: <span class="built_in">string</span>;</span><br><span class="line"> location?: <span class="built_in">string</span>;</span><br><span class="line"> avatar?: <span class="built_in">string</span>;</span><br><span class="line"> id?: <span class="built_in">number</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">IGUser</span>: <span class="title class_">React</span>.<span class="property">FC</span><<span class="title class_">IGUserProps</span>> = <span class="function">(<span class="params">{</span></span></span><br><span class="line"><span class="params"><span class="function"> size = <span class="string">"small"</span>,</span></span></span><br><span class="line"><span class="params"><span class="function"> showFollow = <span class="literal">false</span>,</span></span></span><br><span class="line"><span class="params"><span class="function"> isFollowing = <span class="literal">false</span>,</span></span></span><br><span class="line"><span class="params"><span class="function"> account,</span></span></span><br><span class="line"><span class="params"><span class="function"> location,</span></span></span><br><span class="line"><span class="params"><span class="function"> avatar,</span></span></span><br><span class="line"><span class="params"><span class="function"> id,</span></span></span><br><span class="line"><span class="params"><span class="function">}</span>) =></span> {</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"></span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">div</span> <span class="attr">className</span>=<span class="string">"flex h-[70px] items-center box-border px-4 "</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">div</span> <span class="attr">className</span>=<span class="string">{</span>`${<span class="attr">size</span> === <span class="string">"small"</span> ? "<span class="attr">w-</span>[<span class="attr">40px</span>] <span class="attr">h-</span>[<span class="attr">40px</span>]" <span class="attr">:</span> "<span class="attr">w-</span>[<span class="attr">60px</span>] <span class="attr">h-</span>[<span class="attr">60px</span>]"} <span class="attr">overflow-hidden</span> <span class="attr">rounded-full</span> `}</span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">style</span>=<span class="string">{{</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">backgroundImage:</span> `<span class="attr">url</span>(${<span class="attr">avatar</span>})`,</span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">backgroundPosition:</span> "<span class="attr">center</span>",</span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">backgroundSize:</span> "<span class="attr">cover</span>",</span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> }}</span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> ></span><span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">div</span> <span class="attr">className</span>=<span class="string">"ml-4"</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">p</span> <span class="attr">className</span>=<span class="string">"text-sm font-bold"</span>></span>{account}<span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">p</span> <span class="attr">className</span>=<span class="string">"text-gray-400"</span>></span>{location}<span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="language-xml"> {showFollow && (</span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">p</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">className</span>=<span class="string">{</span>`${<span class="attr">isFollowing</span> ? "<span class="attr">text-gray-700</span>" <span class="attr">:</span> "<span class="attr">text-blue-400</span>"} <span class="attr">text-xs</span> <span class="attr">ml-auto</span> <span class="attr">cursor-pointer</span> <span class="attr">font-bold</span>`}</span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> ></span> {isFollowing ? "FOLLOWING" : "FOLLOW"}<span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> )</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"> }</span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>memo 對於重複渲染,效能優化使用</li></ul><p><a href="https://ithelp.ithome.com.tw/articles/10252827">border-box</a></p><p><img src="https://i.imgur.com/x16ZQBu.png" alt=""></p><h2 id="post-組件"><a href="#post-組件" class="headerlink" title="post 組件"></a>post 組件</h2><p> <img src="https://i.imgur.com/HMvp7dy.jpg" alt=""></p><ul><li>分為三個部分</li></ul><ol><li>user</li></ol><ul><li>可以使用前面所製作的 user 組件</li></ul><ol start="2"><li>img</li></ol><ul><li>直接放入該項圖片</li></ul><ol start="3"><li>評論區</li></ol><ul><li>也可以製作成小組件,最後再放入 post 組件</li><li>注意傳入 props 要先設定好傳入的型別</li></ul><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><span class="line"><span class="keyword">import</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">'react'</span></span><br><span class="line"></span><br><span class="line">type <span class="title class_">CommentsProps</span> = {</span><br><span class="line"> <span class="attr">likes</span>: number;</span><br><span class="line"> <span class="attr">description</span>: string;</span><br><span class="line"> <span class="attr">hashTags</span>: string;</span><br><span class="line"> <span class="attr">createTime</span>: string;</span><br><span class="line"> <span class="attr">account</span>: string;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">Comments</span>: <span class="title class_">React</span>.<span class="property">FC</span><<span class="title class_">CommentsProps</span>> = <span class="function">(<span class="params"></span></span></span><br><span class="line"><span class="params"><span class="function"> {</span></span></span><br><span class="line"><span class="params"><span class="function"> likes,</span></span></span><br><span class="line"><span class="params"><span class="function"> description,</span></span></span><br><span class="line"><span class="params"><span class="function"> hashTags,</span></span></span><br><span class="line"><span class="params"><span class="function"> createTime,</span></span></span><br><span class="line"><span class="params"><span class="function"> account,</span></span></span><br><span class="line"><span class="params"><span class="function"> }</span>) =></span> {</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">div</span> <span class="attr">className</span>=<span class="string">'px-4'</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">div</span> <span class="attr">className</span>=<span class="string">'flex items-center justify-between box-border my-4'</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">div</span> <span class="attr">className</span>=<span class="string">'flex py-1'</span>></span></span></span><br><span class="line"><span class="language-xml"> // svg</span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">p</span> <span class="attr">className</span>=<span class="string">'text-sm font-bold'</span>></span>{likes} likes<span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">p</span> <span class="attr">className</span>=<span class="string">'text-sm font-bold'</span>></span>{description} <span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">p</span> <span class="attr">className</span>=<span class="string">'text-blue-400 font-bold'</span>></span>{hashTags} <span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">p</span> <span class="attr">className</span>=<span class="string">'text-gray-400 font-[500] text-xs mt-2'</span>></span>View all 999 comments <span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">p</span> <span class="attr">className</span>=<span class="string">"text-gray-400 text-[10px] mt-1"</span>></span>{createTime}<span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="language-xml"> )</span></span><br><span class="line"><span class="language-xml">}</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"></span></span><br></pre></td></tr></table></figure><h2 id="profile-區塊"><a href="#profile-區塊" class="headerlink" title="profile 區塊"></a>profile 區塊</h2><ul><li><p>實作快速,直接做出簡易的版面</p></li><li><p>套用前面所做的 IGUser 即可以使用</p><p><img src="https://i.imgur.com/0nIA31V.png" alt=""></p></li></ul><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><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">IGUser</span> <span class="keyword">from</span> <span class="string">"components/IGUser"</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">IGProfile</span> = (<span class="params"></span>) => {</span><br><span class="line"> <span class="keyword">const</span> followingList = [</span><br><span class="line"> {</span><br><span class="line"> <span class="attr">id</span>: <span class="number">1</span>,</span><br><span class="line"> <span class="attr">location</span>: <span class="string">"Singapore"</span>,</span><br><span class="line"> <span class="attr">account</span>: <span class="string">"max_999"</span>,</span><br><span class="line"> <span class="attr">isFollowing</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="attr">avatar</span>: <span class="string">"/images/avatars/a1.png"</span>,</span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="attr">id</span>: <span class="number">2</span>,</span><br><span class="line"> <span class="attr">location</span>: <span class="string">"Singapore"</span>,</span><br><span class="line"> <span class="attr">account</span>: <span class="string">"fm_999"</span>,</span><br><span class="line"> <span class="attr">isFollowing</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="attr">avatar</span>: <span class="string">"/images/avatars/a2.png"</span>,</span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="attr">id</span>: <span class="number">3</span>,</span><br><span class="line"> <span class="attr">location</span>: <span class="string">"Singapore"</span>,</span><br><span class="line"> <span class="attr">account</span>: <span class="string">"joanne_999"</span>,</span><br><span class="line"> <span class="attr">isFollowing</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="attr">avatar</span>: <span class="string">"/images/avatars/a3.png"</span>,</span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="attr">id</span>: <span class="number">4</span>,</span><br><span class="line"> <span class="attr">location</span>: <span class="string">"Singapore"</span>,</span><br><span class="line"> <span class="attr">account</span>: <span class="string">"focus_999"</span>,</span><br><span class="line"> <span class="attr">isFollowing</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="attr">avatar</span>: <span class="string">"/images/avatars/a4.png"</span>,</span><br><span class="line"> },]</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">div</span> <span class="attr">className</span>=<span class="string">"mt-8 ml-6 border-box shadow-md px-4"</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">div</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">IGUser</span> <span class="attr">size</span>=<span class="string">'medium'</span> <span class="attr">account</span>=<span class="string">'Tmommy_0814'</span> <span class="attr">avatar</span>=<span class="string">"/images/avatar.png"</span> /></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">p</span> <span class="attr">className</span>=<span class="string">"text-gray-400 px-4 mt-2"</span>></span>You are Following<span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"><<span class="name">div</span> ></span></span></span><br><span class="line"><span class="language-xml"> {</span></span><br><span class="line"><span class="language-xml"> followingList?.map((item) => {</span></span><br><span class="line"><span class="language-xml"> const { location, account, isFollowing, avatar, id } = item</span></span><br><span class="line"><span class="language-xml"> return <span class="tag"><<span class="name">IGUser</span> <span class="attr">location</span>=<span class="string">{location}</span> <span class="attr">account</span>=<span class="string">{account}</span> <span class="attr">isFollowing</span>=<span class="string">{isFollowing}</span> <span class="attr">avatar</span>=<span class="string">{avatar}</span> <span class="attr">key</span>=<span class="string">{id}</span> <span class="attr">showFollow</span> /></span></span></span><br><span class="line"><span class="language-xml"> })</span></span><br><span class="line"><span class="language-xml"> }</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="language-xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"> )</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">IGProfile</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="小結"><a href="#小結" class="headerlink" title="小結"></a>小結</h2><p>此次練習在使用 Tailwind 有些不習慣,主要是在於要稍微記得他的關鍵字並去文件查找屬性來應用,待使用到第三的區塊切版時就變得快速些~<br>另外,使用在課程中 Bruce 也會去說明每個區塊的切割以及重用性,可以將檔案分別放在哪個檔案,以利未來維護。<br>過去可能拿版面並未想太多,或是沒有多餘時間分析每一頁面的某些區塊是否有重複,我們可以依據建立開關或傳入的資料區紹維變動下版面,就可以達到一起使用 component 的效果。</p>]]></content>
<summary type="html"><p><img src="https://i.imgur.com/VykOAkm.png" alt=""></p>
<p>前段時間練習了一些 React 的基礎,對於 JSX 以及一些 hook 的用法比較有概念,所以就以 Bruce 的 React 課程實作再來練習,樣式部分以</summary>
<category term="React" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/React/"/>
<category term="React" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/React/"/>
</entry>
<entry>
<title>刷題練習 - Majority Element</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2022/11/10/leetcode-Majority-Element/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2022/11/10/leetcode-Majority-Element/</id>
<published>2022-11-10T02:36:50.000Z</published>
<updated>2022-11-10T06:42:28.618Z</updated>
<content type="html"><![CDATA[<p>Given an array nums of size n, return the majority element.</p><p>The majority element is the element that appears more than ⌊n / 2⌋ times. You may assume that the majority element always exists in the array.</p><p>Example 1:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Input: nums = [3,2,3]</span><br><span class="line">Output: 3</span><br></pre></td></tr></table></figure><p>Example 2:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Input: nums = [2,2,1,1,1,2,2]</span><br><span class="line">Output: 2</span><br></pre></td></tr></table></figure><p>在一開始觀察題目,會直覺想說要找出陣列中出現最多次的元素,此外也注意到題目說明有提及運用 n/2 與陣列長度比較出現次數。<br>在一開始會傾向使用 雜湊表 來進行解題,如同找出陣列為一值的方式找出答案。</p><figure class="highlight javascript"><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><span class="line"><span class="keyword">var</span> majorityElement = <span class="keyword">function</span> (<span class="params">nums</span>) {</span><br><span class="line"> <span class="keyword">let</span> newObj = {}</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> num <span class="keyword">of</span> nums) {</span><br><span class="line"> <span class="comment">// console.log(num)</span></span><br><span class="line"> (!newObj[num]) ? newObj[num] = <span class="number">1</span> : newObj[num]++</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// console.log(newObj)</span></span><br><span class="line"> <span class="keyword">let</span> nNum = nums.<span class="property">length</span> / <span class="number">2</span></span><br><span class="line"> <span class="comment">// console.log('nNum', nNum)</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> key <span class="keyword">in</span> newObj) {</span><br><span class="line"> <span class="keyword">if</span> (newObj[key] > nNum) <span class="keyword">return</span> key</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">};</span><br></pre></td></tr></table></figure><p>另外也發現可以使用,Boyer–Moore majority vote algorithm(摩爾投票算法)來解題。<br>宣告變數 result , 以及計算變數。<br>將陣列loop ,判斷陣列元素有無出現進行 count 的加減<br>以 <code>majorityElement2([4, 5, 5, 4, 4])</code> 為範例:<br>第一個元素 4 ,因為 count === 0 , result === 4。<br>進入第二個元素 5,因為 result === 4 進入判斷式 else => count– 。 所以 count === 0 。<br>進入第三個元素 5,因為 result === 5 進入判斷式 result === elem => count++。 所以 count === 1 。<br>進入第四個元素 4,因為 result === 5 進入判斷式 else => count– 。 所以 count === 0 。<br>進入第五個元素 4,因為 result === 4 進入判斷式 result === elem => count++。 所以 count === 1 。</p><p>在迴圈的最後元素 4 ,為目前 count 為 1</p><figure class="highlight javascript"><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><span class="line"></span><br><span class="line"><span class="keyword">var</span> majorityElement2 = <span class="keyword">function</span> (<span class="params">nums</span>) {</span><br><span class="line"> <span class="keyword">let</span> result;</span><br><span class="line"> <span class="keyword">let</span> count = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> elem <span class="keyword">of</span> nums) {</span><br><span class="line"> <span class="keyword">if</span> (count === <span class="number">0</span>) {</span><br><span class="line"> result = elem;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (result === elem) {</span><br><span class="line"> count++;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> count--;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line"></span><br><span class="line">};</span><br><span class="line"></span><br></pre></td></tr></table></figure><hr><ol start="229"><li>Majority Element II<br>此題也是使用摩爾投票法進行解題</li></ol><p>Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times.</p><p>Example 1:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Input: nums = [3,2,3]</span><br><span class="line">Output: [3]</span><br></pre></td></tr></table></figure><p>Example 2:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Input: nums = [1]</span><br><span class="line">Output: [1]</span><br></pre></td></tr></table></figure><p>Example 3:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Input: nums = [1,2]</span><br><span class="line">Output: [1,2]</span><br></pre></td></tr></table></figure><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> majorityElement = <span class="keyword">function</span> (<span class="params">nums</span>) {</span><br><span class="line"> <span class="comment">// 只要是 > n/3 就進入陣列</span></span><br><span class="line"> <span class="keyword">let</span> candidate1 = <span class="literal">null</span>;</span><br><span class="line"> <span class="keyword">let</span> candidate2 = <span class="literal">null</span>;</span><br><span class="line"> <span class="keyword">let</span> count1 = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">let</span> count2 = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> num <span class="keyword">of</span> nums) {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (candidate1 === num) {</span><br><span class="line"> count1++</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (candidate2 === num) {</span><br><span class="line"> count2++</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (count1 === <span class="number">0</span>) {</span><br><span class="line"> candidate1 = num;</span><br><span class="line"> count1++</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (count2 === <span class="number">0</span>) {</span><br><span class="line"> candidate2 = num;</span><br><span class="line"> count2++</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> count1--;</span><br><span class="line"> count2--;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'data:'</span>, candidate1, candidate2)</span><br><span class="line"> count1 = <span class="number">0</span>;</span><br><span class="line"> count2 = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">const</span> res = [];</span><br><span class="line"></span><br><span class="line"> limit = <span class="title class_">Math</span>.<span class="title function_">floor</span>(nums.<span class="property">length</span> / <span class="number">3</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> num <span class="keyword">of</span> nums) {</span><br><span class="line"> <span class="keyword">if</span> (candidate1 === num) count1++;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (candidate2 === num) {</span><br><span class="line"> count2++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (count1 > limit) res.<span class="title function_">push</span>(candidate1)</span><br><span class="line"> <span class="keyword">if</span> (count2 > limit) res.<span class="title function_">push</span>(candidate2)</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(res, count1, count2)</span><br><span class="line"> <span class="keyword">return</span> res</span><br><span class="line"></span><br><span class="line">};</span><br><span class="line"><span class="title function_">majorityElement</span>([<span class="number">1</span>, <span class="number">2</span>])</span><br></pre></td></tr></table></figure><p><img src="https://i.imgur.com/T2y5qLa.jpg" alt=""></p>]]></content>
<summary type="html"><p>Given an array nums of size n, return the majority element.</p>
<p>The majority element is the element that appears more than ⌊n / 2⌋ tim</summary>
<category term="Leetcode" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/Leetcode/"/>
<category term="Leetcode" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/Leetcode/"/>
</entry>
<entry>
<title>刷題練習 - Rotate Array</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2022/11/07/Rotate-array/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2022/11/07/Rotate-array/</id>
<published>2022-11-07T09:13:53.398Z</published>
<updated>2022-11-10T03:02:33.416Z</updated>
<content type="html"><![CDATA[<p>Given an array, rotate the array to the right by k steps, where k is non-negative.</p><p>Example 1:</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><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Input: nums = [1,2,3,4,5,6,7], k = 3</span><br><span class="line">Output: [5,6,7,1,2,3,4]</span><br><span class="line">Explanation:</span><br><span class="line">rotate 1 steps to the right: [7,1,2,3,4,5,6]</span><br><span class="line">rotate 2 steps to the right: [6,7,1,2,3,4,5]</span><br><span class="line">rotate 3 steps to the right: [5,6,7,1,2,3,4]</span><br></pre></td></tr></table></figure><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><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Example 2:</span><br><span class="line"></span><br><span class="line">Input: nums = [-1,-100,3,99], k = 2</span><br><span class="line">Output: [3,99,-1,-100]</span><br><span class="line">Explanation: </span><br><span class="line">rotate 1 steps to the right: [99,-1,-100,3]</span><br><span class="line">rotate 2 steps to the right: [3,99,-1,-100]</span><br></pre></td></tr></table></figure><p>1.由上述範例可以觀察到,根據 k 值進行抓取最後的元素至最前面,以此類推下去。<br>當 k 為某值的時後,會由陣列最後方取的該數目元素。<br>以下為直覺解法:</p><figure class="highlight javascript"><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><span class="line"><span class="comment">//會有 問題:Time Limit Exceeded</span></span><br><span class="line"><span class="keyword">const</span> rotateArray1 = <span class="keyword">function</span> (<span class="params">nums, k</span>) {</span><br><span class="line"> <span class="comment">//unshift 將給入的元素值放到最前面</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i < k; i++) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'nums.pop()'</span>, nums.<span class="title function_">pop</span>())</span><br><span class="line"> nums.<span class="title function_">unshift</span>(nums.<span class="title function_">pop</span>());</span><br><span class="line"> }</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'num'</span>, nums)</span><br><span class="line"> <span class="keyword">return</span> nums;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>2.也可以先將陣列進行反轉 reverse ,再依據 k 值 來進行前後段區分,來進行反轉</p><figure class="highlight javascript"><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><span class="line"><span class="keyword">const</span> <span class="title function_">revNum</span> = (<span class="params">nums, start, end</span>) => {</span><br><span class="line"> <span class="keyword">while</span> (start < end) {</span><br><span class="line"></span><br><span class="line"> [nums[start], nums[end]] = [nums[end], nums[start]]</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'[nums[start], nums[end]]'</span>, [nums[start], nums[end]])</span><br><span class="line"> start++;</span><br><span class="line"> end--;</span><br><span class="line"> }</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(nums)</span><br><span class="line">}</span><br><span class="line"><span class="comment">// revNum([1, 2, 3, 4], 0, 3)</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> rotateArray2 = <span class="keyword">function</span> (<span class="params">nums, k</span>) {</span><br><span class="line"> k = k % nums.<span class="property">length</span></span><br><span class="line"> <span class="comment">//先整個陣列 reverse</span></span><br><span class="line"> nums.<span class="title function_">reverse</span>()</span><br><span class="line"> <span class="title function_">revNum</span>(nums, <span class="number">0</span>, k - <span class="number">1</span>)</span><br><span class="line"> <span class="title function_">revNum</span>(nums, k, nums.<span class="property">length</span> - <span class="number">1</span>)</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><p>Given an array, rotate the array to the right by k steps, where k is non-negative.</p>
<p>Example 1:</p>
<figure class="highlight plainte</summary>
<category term="Leetcode" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/Leetcode/"/>
<category term="Leetcode" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/Leetcode/"/>
</entry>
<entry>
<title>React 測試 - 以登入元件練習</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2022/11/02/rect-test-2/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2022/11/02/rect-test-2/</id>
<published>2022-11-02T12:49:15.000Z</published>
<updated>2022-11-04T02:37:05.784Z</updated>
<content type="html"><![CDATA[<p>想找專案練習來更認識測試的運用,至 youtube 找尋測試相關的教學。</p><h3 id="建立-login-檔案"><a href="#建立-login-檔案" class="headerlink" title="建立 login 檔案"></a>建立 login 檔案</h3><ul><li><p>login.js : 製作登入元件</p></li><li><p>login.test.js : 撰寫測試</p><p><img src="https://i.imgur.com/4Pw5JTD.png" alt=""></p></li></ul><h3 id="確認-輸入框-有渲染至文件"><a href="#確認-輸入框-有渲染至文件" class="headerlink" title="確認 輸入框 有渲染至文件"></a>確認 輸入框 有渲染至文件</h3><ul><li>使用 <code>getByPlaceholderText</code> 取得輸入框元素</li></ul><figure class="highlight html"><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><span class="line"><span class="tag"><<span class="name">form</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">input</span></span></span><br><span class="line"><span class="tag"> <span class="attr">type</span>=<span class="string">"text"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">placeholder</span>=<span class="string">"username"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">value</span>=<span class="string">''</span></span></span><br><span class="line"><span class="tag"> /></span></span><br><span class="line"> <span class="tag"><<span class="name">input</span></span></span><br><span class="line"><span class="tag"> <span class="attr">type</span>=<span class="string">"password"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">placeholder</span>=<span class="string">"password"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">value</span>=<span class="string">''</span></span></span><br><span class="line"><span class="tag"> /></span></span><br><span class="line"> <span class="tag"></<span class="name">form</span>></span></span><br></pre></td></tr></table></figure><figure class="highlight javascript"><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><span class="line"><span class="title function_">test</span>(<span class="string">"username input should be rendered"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">render</span>(<span class="language-xml"><span class="tag"><<span class="name">Login</span> /></span></span>);</span><br><span class="line"> <span class="keyword">const</span> usernameInputEl = screen.<span class="title function_">getByPlaceholderText</span>(<span class="regexp">/username/i</span>);</span><br><span class="line"> <span class="title function_">expect</span>(usernameInputEl).<span class="title function_">toBeInTheDocument</span>();</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="title function_">test</span>(<span class="string">"password input should be rendered"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">render</span>(<span class="language-xml"><span class="tag"><<span class="name">Login</span> /></span></span>);</span><br><span class="line"> <span class="keyword">const</span> passwordInputEl = screen.<span class="title function_">getByPlaceholderText</span>(<span class="regexp">/password/i</span>);</span><br><span class="line"> <span class="title function_">expect</span>(passwordInputEl).<span class="title function_">toBeInTheDocument</span>();</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h3 id="確認畫面上有按鈕"><a href="#確認畫面上有按鈕" class="headerlink" title="確認畫面上有按鈕"></a>確認畫面上有按鈕</h3><ul><li>getByRole 取得按鈕</li></ul><figure class="highlight javascript"><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><span class="line"><span class="title function_">test</span>(<span class="string">"button should be rendered"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">render</span>(<span class="language-xml"><span class="tag"><<span class="name">Login</span> /></span></span>);</span><br><span class="line"> <span class="keyword">const</span> buttonEl = screen.<span class="title function_">getByRole</span>(<span class="string">"button"</span>);</span><br><span class="line"> <span class="title function_">expect</span>(buttonEl).<span class="title function_">toBeInTheDocument</span>();</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h3 id="輸入框一開始為空"><a href="#輸入框一開始為空" class="headerlink" title="輸入框一開始為空"></a>輸入框一開始為空</h3><figure class="highlight javascript"><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><span class="line"><span class="title function_">test</span>(<span class="string">"username input should be empty"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">render</span>(<span class="language-xml"><span class="tag"><<span class="name">Login</span> /></span></span>);</span><br><span class="line"> <span class="keyword">const</span> usernameInputEl = screen.<span class="title function_">getByPlaceholderText</span>(<span class="regexp">/username/i</span>);</span><br><span class="line"> <span class="title function_">expect</span>(usernameInputEl.<span class="property">value</span>).<span class="title function_">toBe</span>(<span class="string">""</span>);</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="title function_">test</span>(<span class="string">"password input should be empty"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">render</span>(<span class="language-xml"><span class="tag"><<span class="name">Login</span> /></span></span>);</span><br><span class="line"> <span class="keyword">const</span> passwordInputEl = screen.<span class="title function_">getByPlaceholderText</span>(<span class="regexp">/password/i</span>);</span><br><span class="line"> <span class="title function_">expect</span>(passwordInputEl.<span class="property">value</span>).<span class="title function_">toBe</span>(<span class="string">""</span>);</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h3 id="輸入框為空時,按鈕應為-disabled"><a href="#輸入框為空時,按鈕應為-disabled" class="headerlink" title="輸入框為空時,按鈕應為 disabled"></a>輸入框為空時,按鈕應為 disabled</h3><ul><li>只要取得按鈕元素並使用 <code>toBeDisabled()</code></li></ul><figure class="highlight javascript"><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><span class="line"><span class="title function_">test</span>(<span class="string">"button should be disabled"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">render</span>(<span class="language-xml"><span class="tag"><<span class="name">Login</span> /></span></span>);</span><br><span class="line"> <span class="keyword">const</span> buttonEl = screen.<span class="title function_">getByRole</span>(<span class="string">"button"</span>);</span><br><span class="line"> <span class="title function_">expect</span>(buttonEl).<span class="title function_">toBeDisabled</span>();</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h3 id="錯誤訊息的提示"><a href="#錯誤訊息的提示" class="headerlink" title="錯誤訊息的提示"></a>錯誤訊息的提示</h3><p><img src="https://i.imgur.com/hQ33Kxa.png" alt=""></p><ul><li>確保一開始進入畫面,該訊息不應該出現</li><li>可以看見 <code>toBeVisible()</code> ,反之期望無法看見,就需加入not</li></ul><figure class="highlight javascript"><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><span class="line"><span class="title function_">test</span>(<span class="string">"error message should not be visible"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">render</span>(<span class="language-xml"><span class="tag"><<span class="name">Login</span> /></span></span>);</span><br><span class="line"> <span class="keyword">const</span> errorEl = screen.<span class="title function_">getByTestId</span>(<span class="string">"error"</span>);</span><br><span class="line"> <span class="title function_">expect</span>(errorEl).<span class="property">not</span>.<span class="title function_">toBeVisible</span>();</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h3 id="輸入框的輸入事件"><a href="#輸入框的輸入事件" class="headerlink" title="輸入框的輸入事件"></a>輸入框的輸入事件</h3><ul><li><a href="https://testing-library.com/docs/dom-testing-library/api-events/">fireEvent</a> 用來針對事件進行測試</li></ul><p><img src="https://i.imgur.com/E9wT8gO.png" alt=""></p><figure class="highlight javascript"><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><span class="line"><span class="title function_">test</span>(<span class="string">"username input should change"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">render</span>(<span class="language-xml"><span class="tag"><<span class="name">Login</span> /></span></span>);</span><br><span class="line"> <span class="keyword">const</span> usernameInputEl = screen.<span class="title function_">getByPlaceholderText</span>(<span class="regexp">/username/i</span>);</span><br><span class="line"> <span class="comment">//模擬傳入的值</span></span><br><span class="line"> <span class="keyword">const</span> testValue = <span class="string">"test"</span>;</span><br><span class="line"></span><br><span class="line"> fireEvent.<span class="title function_">change</span>(usernameInputEl, { <span class="attr">target</span>: { <span class="attr">value</span>: testValue } });</span><br><span class="line"> <span class="title function_">expect</span>(usernameInputEl.<span class="property">value</span>).<span class="title function_">toBe</span>(testValue);</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="title function_">test</span>(<span class="string">"password input should change"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">render</span>(<span class="language-xml"><span class="tag"><<span class="name">Login</span> /></span></span>);</span><br><span class="line"> <span class="keyword">const</span> passwordInputEl = screen.<span class="title function_">getByPlaceholderText</span>(<span class="regexp">/password/i</span>);</span><br><span class="line"> <span class="keyword">const</span> testValue = <span class="string">"test"</span>;</span><br><span class="line"></span><br><span class="line"> fireEvent.<span class="title function_">change</span>(passwordInputEl, { <span class="attr">target</span>: { <span class="attr">value</span>: testValue } });</span><br><span class="line"> <span class="title function_">expect</span>(passwordInputEl.<span class="property">value</span>).<span class="title function_">toBe</span>(testValue);</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h3 id="當輸入框有值的時候,按鈕不應該-disabled"><a href="#當輸入框有值的時候,按鈕不應該-disabled" class="headerlink" title="當輸入框有值的時候,按鈕不應該 disabled"></a>當輸入框有值的時候,按鈕不應該 <code>disabled</code></h3><ul><li>期望按鈕可以點擊</li><li>在 jsx 檔案內要設置在輸入框沒有值的時候才是 disabled</li></ul><p><img src="https://i.imgur.com/MdNkcGo.png" alt=""></p><figure class="highlight javascript"><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><span class="line"></span><br><span class="line"><span class="title function_">test</span>(<span class="string">"button should not be disabled when inputs exist"</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">render</span>(<span class="language-xml"><span class="tag"><<span class="name">Login</span> /></span></span>);</span><br><span class="line"> <span class="keyword">const</span> buttonEl = screen.<span class="title function_">getByRole</span>(<span class="string">"button"</span>);</span><br><span class="line"> <span class="keyword">const</span> usernameInputEl = screen.<span class="title function_">getByPlaceholderText</span>(<span class="regexp">/username/i</span>);</span><br><span class="line"> <span class="keyword">const</span> passwordInputEl = screen.<span class="title function_">getByPlaceholderText</span>(<span class="regexp">/password/i</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> testValue = <span class="string">"test"</span>;</span><br><span class="line"></span><br><span class="line"> fireEvent.<span class="title function_">change</span>(usernameInputEl, { <span class="attr">target</span>: { <span class="attr">value</span>: testValue } });</span><br><span class="line"> fireEvent.<span class="title function_">change</span>(passwordInputEl, { <span class="attr">target</span>: { <span class="attr">value</span>: testValue } });</span><br><span class="line"></span><br><span class="line"> <span class="title function_">expect</span>(buttonEl).<span class="property">not</span>.<span class="title function_">toBeDisabled</span>();</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h4 id="css-補充"><a href="#css-補充" class="headerlink" title="css 補充"></a>css 補充</h4><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">style={{ <span class="attribute">visibility</span>: error ? <span class="string">"visible"</span> : <span class="string">"hidden"</span> }}</span><br></pre></td></tr></table></figure><p>類似: display:none和visibility:hidden</p><p>而兩者差異:<br>visibility:的隱藏,是物件的位置仍舊保持著不會消失,<br>display: none, 會將 html 該物件拔除</p><h2 id="小結"><a href="#小結" class="headerlink" title="小結"></a>小結</h2><p>此練習範例,很請楚地知道在建立一個功能元件之後,如何再加入每一個區塊的測試,如標題文字、輸入框、按鈕的測試等等,也可以觀察到測試根據使用情境一步步的拆解並加入測試<br>下一篇會有串接資料搭配測試,敬請期待</p><p>參考資料<br><a href="https://github.com/safak/youtube2022/blob/react-testing/src/components/login/Login.jsx">github-login</a><br><a href="https://www.youtube.com/watch?v=Flo268xRpV0">React Testing Tutorial with React Testing Library and Jest</a></p>]]></content>
<summary type="html"><p>想找專案練習來更認識測試的運用,至 youtube 找尋測試相關的教學。</p>
<h3 id="建立-login-檔案"><a href="#建立-login-檔案" class="headerlink" title="建立 login 檔案"></a>建立 login </summary>
<category term="React 測試" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/React-%E6%B8%AC%E8%A9%A6/"/>
<category term="React" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/React/"/>
</entry>
<entry>
<title>React 測試</title>
<link href="https://github.com/Eva813/Eva813.github.io.git/2022/11/02/rect-test-1/"/>
<id>https://github.com/Eva813/Eva813.github.io.git/2022/11/02/rect-test-1/</id>
<published>2022-11-02T07:43:21.000Z</published>
<updated>2022-11-04T02:37:02.192Z</updated>
<content type="html"><![CDATA[<p>使用 JavaSript 要進行測試最常使用的就是使用 Jest ,另外依據使用的前端框架來搭配使用進行測試。<br>以下內文就先以一些範例來直接學習</p><h2 id="testing-library"><a href="#testing-library" class="headerlink" title="testing-library"></a>testing-library</h2><ul><li><p>當使創建一個 react 檔案,會預設加入的測試範例檔</p><figure class="highlight javascript"><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><span class="line"> <span class="title function_">test</span>(<span class="string">'renders learn react link'</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="keyword">const</span> linkElement = screen.<span class="title function_">getByText</span>(<span class="regexp">/learn react/i</span>);</span><br><span class="line"> <span class="title function_">expect</span>(linkElement).<span class="title function_">toBeInTheDocument</span>();</span><br><span class="line">});</span><br></pre></td></tr></table></figure></li><li><p>screen : it represent the whole document which we have rendered</p></li><li><p>getByText: 取得 text</p><ul><li><code>getByText(/learn react/i)</code></li><li><code>expect(linkElement).toBeInTheDocument();</code></li><li>期待變數得值,<code>toBeInTheDocument()</code></li><li>檢測此項目是否存在於文件之中</li><li><ul><li><a href="https://github.com/testing-library/jest-dom#tobeinthedocument">toBeInTheDocument</a>:判斷一個 Element 是否存在於 DOM 中</li></ul></li></ul></li></ul><h3 id="撰寫測試的參考文件"><a href="#撰寫測試的參考文件" class="headerlink" title="撰寫測試的參考文件"></a>撰寫測試的參考文件</h3><p><a href="https://testing-library.com/docs/queries/byrole">ByRole</a><br><a href="https://www.w3.org/TR/html-aria/#docconformance"> role attribute</a></p><h3 id="加入列表(list)測試"><a href="#加入列表(list)測試" class="headerlink" title="加入列表(list)測試"></a>加入列表(list)測試</h3><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><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> logo <span class="keyword">from</span> <span class="string">'./logo.svg'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">'./App.css'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Login</span> <span class="keyword">from</span> <span class="string">'./components/Login/Login'</span>;</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">App</span>(<span class="params"></span>) {</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> (</span><br><span class="line"></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">div</span> <span class="attr">className</span>=<span class="string">"App"</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">header</span> <span class="attr">className</span>=<span class="string">"App-header"</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">{logo}</span> <span class="attr">className</span>=<span class="string">"App-logo"</span> <span class="attr">alt</span>=<span class="string">"logo"</span> /></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">Edit <span class="tag"><<span class="name">code</span>></span>src/App.js<span class="tag"></<span class="name">code</span>></span> and save to reload.</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">a</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"><span class="attr">className</span>=<span class="string">"App-link"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"><span class="attr">href</span>=<span class="string">"https://reactjs.org"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"><span class="attr">target</span>=<span class="string">"_blank"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"><span class="attr">rel</span>=<span class="string">"noopener noreferrer"</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml"> <span class="attr">.</span> ></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">Learn React</span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">a</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">ul</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">li</span>></span>Apple<span class="tag"></<span class="name">li</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">li</span>></span>Banana<span class="tag"></<span class="name">li</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">li</span>></span>Kiwi<span class="tag"></<span class="name">li</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">ul</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">header</span>></span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"></span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">App</span>;</span><br></pre></td></tr></table></figure><figure class="highlight javascript"><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><span class="line"><span class="title function_">test</span>(<span class="string">'renders 3 list items'</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">render</span>(<span class="language-xml"><span class="tag"><<span class="name">App</span> /></span></span>);</span><br><span class="line"> <span class="keyword">const</span> listItems = screen.<span class="title function_">getAllByRole</span>(<span class="string">"listitem"</span>);</span><br><span class="line"> <span class="title function_">expect</span>(listItems.<span class="property">length</span>).<span class="title function_">toEqual</span>(<span class="number">3</span>);</span><br><span class="line">});</span><br></pre></td></tr></table></figure><ul><li>jest <a href="https://jestjs.io/docs/expect">expect</a></li><li>需要時到官網看相關使用的API<br><code>expect(listItems.length).toBe(3);</code><br><code>expect(listItems.length).toEqual(3);</code></li></ul><h3 id="測試-title"><a href="#測試-title" class="headerlink" title="測試 title"></a>測試 title</h3><ul><li>getByTestId:運用此方法可以直接取得在元素上設置的 data-testid</li><li>getByTitle : 取得在標籤設置 title 的元素</li></ul><figure class="highlight html"><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><span class="line"><span class="comment"><!-- const a = 2</span></span><br><span class="line"><span class="comment">const b = 1 --></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">h1</span> <span class="attr">data-testid</span>=<span class="string">"mytestid"</span>></span>Hello<span class="tag"></<span class="name">h1</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">span</span> <span class="attr">title</span>=<span class="string">"sum"</span>></span>{a + b}<span class="tag"></<span class="name">span</span>></span></span><br></pre></td></tr></table></figure><figure class="highlight javascript"><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><span class="line"><span class="title function_">test</span>(<span class="string">'renders title'</span>, <span class="function">() =></span> {</span><br><span class="line"></span><br><span class="line"><span class="title function_">render</span>(<span class="language-xml"><span class="tag"><<span class="name">App</span> /></span></span>);</span><br><span class="line"><span class="keyword">const</span> title = screen.<span class="title function_">getByTestId</span>(<span class="string">"mytestid"</span>);</span><br><span class="line"><span class="title function_">expect</span>(title).<span class="title function_">toBeInTheDocument</span>();</span><br><span class="line"></span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="title function_">test</span>(<span class="string">'sum should be 3'</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="title function_">render</span>(<span class="language-xml"><span class="tag"><<span class="name">App</span> /></span></span>);</span><br><span class="line"> <span class="keyword">const</span> titleSum = screen.<span class="title function_">getByTitle</span>(<span class="string">"sum"</span>);</span><br><span class="line"> <span class="title function_">expect</span>(titleSum.<span class="property">textContent</span>).<span class="title function_">toBe</span>(<span class="string">"3"</span>);</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h3 id="運行測試"><a href="#運行測試" class="headerlink" title="運行測試"></a>運行測試</h3><p><code>npm run test</code></p><ul><li><p>透過測試所提供的錯誤提示,可以得知預期的結果以及實際運行後得到的值之間的差異</p><p><img src="https://i.imgur.com/IT8leGK.png" alt=""></p></li></ul><p>參考資料:<br><a href="https://ithelp.ithome.com.tw/articles/10281691">[Day29] React Testing Library 的一些實用的小技巧</a><br><a href="https://medium.com/%E6%89%8B%E5%AF%AB%E7%AD%86%E8%A8%98/nextjs-testing-tutorial-1-ed4b27563761">Next.js | 初探單元測試,使用 Jest + React Testing Library</a></p>]]></content>
<summary type="html"><p>使用 JavaSript 要進行測試最常使用的就是使用 Jest ,另外依據使用的前端框架來搭配使用進行測試。<br>以下內文就先以一些範例來直接學習</p>
<h2 id="testing-library"><a href="#testing-library" class</summary>
<category term="React 測試" scheme="https://github.com/Eva813/Eva813.github.io.git/categories/React-%E6%B8%AC%E8%A9%A6/"/>
<category term="React" scheme="https://github.com/Eva813/Eva813.github.io.git/tags/React/"/>
</entry>
</feed>