-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
501 lines (372 loc) · 79.4 KB
/
index.html
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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Colin‘s Blog</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta property="og:type" content="website">
<meta property="og:title" content="Colin‘s Blog">
<meta property="og:url" content="http://yoursite.com/index.html">
<meta property="og:site_name" content="Colin‘s Blog">
<meta property="og:locale" content="default">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Colin‘s Blog">
<link rel="alternate" href="/atom.xml" title="Colin‘s Blog" type="application/atom+xml">
<link rel="icon" href="/favicon.png">
<link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<div id="container">
<div id="wrap">
<header id="header">
<div id="banner"></div>
<div id="header-outer" class="outer">
<div id="header-title" class="inner">
<h1 id="logo-wrap">
<a href="/" id="logo">Colin‘s Blog</a>
</h1>
</div>
<div id="header-inner" class="inner">
<nav id="main-nav">
<a id="main-nav-toggle" class="nav-icon"></a>
<a class="main-nav-link" href="/">Home</a>
<a class="main-nav-link" href="/archives">Archives</a>
</nav>
<nav id="sub-nav">
<a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
<a id="nav-search-btn" class="nav-icon" title="Search"></a>
</nav>
<div id="search-form-wrap">
<form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit"></button><input type="hidden" name="sitesearch" value="http://yoursite.com"></form>
</div>
</div>
</div>
</header>
<div class="outer">
<section id="main">
<article id="post-来总结一下Context" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2020/04/07/来总结一下Context/" class="article-date">
<time datetime="2020-04-07T13:58:17.000Z" itemprop="datePublished">2020-04-07</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2020/04/07/来总结一下Context/">来总结一下Context</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h2 id="1、什么是Context"><a href="#1、什么是Context" class="headerlink" title="1、什么是Context"></a>1、什么是Context</h2><p>Context 设计目的是为了共享那些对于一个组件树而言是“全局”的数据。</p>
<h2 id="2、相关API"><a href="#2、相关API" class="headerlink" title="2、相关API"></a>2、相关API</h2><p>1、<code>React.createContext(defaultValue)</code></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"><span class="keyword">const</span> MyContext = React.createContext(defaultValue);</span><br></pre></td></tr></table></figure>
<p>创建一个 Context 对象。当 React 渲染一个订阅了这个 Context 对象的组件,这个组件会从组件树s中离自身最近的那个匹配的 <code>Provider</code> 中读取到当前的 context 值。</p>
<p><strong>只有</strong>当组件所处的树中没有匹配到 Provider 时,其 <code>defaultValue</code> 参数才会生效。这有助于在不使用 Provider 包装组件的情况下对组件进行测试。</p>
<p>2、<code>Context.Provider</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><MyContext.Provider value={/* 某个值 */}></span><br></pre></td></tr></table></figure>
<p>每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化。</p>
<p>当 Provider 的 <code>value</code> 值发生变化时,它内部的所有消费组件都会重新渲染。</p>
<p>3、<code>Class.contextType</code></p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyClass</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span> </span>{</span><br><span class="line"> componentDidMount() {</span><br><span class="line"> <span class="keyword">let</span> value = <span class="keyword">this</span>.context;</span><br><span class="line"> }</span><br><span class="line"> render() {</span><br><span class="line"> <span class="keyword">let</span> value = <span class="keyword">this</span>.context;</span><br><span class="line"> <span class="comment">/* 基于 MyContext 组件的值进行渲染 */</span></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">MyClass.contextType = MyContext;</span><br></pre></td></tr></table></figure>
<p>挂载在 class 上的 <code>contextType</code> 属性会被重赋值为一个由 <code>React.createContext()</code>]创建的 Context 对象。</p>
<p>这能让你使用 <code>this.context</code> 来消费最近 Context 上的那个值。你可以在任何生命周期中访问到它,包括 render 函数中。</p>
<p>4、<code>Context.Consumer</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></pre></td><td class="code"><pre><span class="line"><MyContext.Consumer></span><br><span class="line"> {value => <button>{value}</button>}</span><br><span class="line"><<span class="regexp">/MyContext.Consumer></span></span><br></pre></td></tr></table></figure>
<p>让你在<strong>函数式组件</strong>中完成订阅 context。</p>
<h2 id="3、为什么不建议优先使用Context"><a href="#3、为什么不建议优先使用Context" class="headerlink" title="3、为什么不建议优先使用Context"></a>3、为什么不建议优先使用Context</h2><p>1、当 provider 的父组件进行重渲染时,可能会在 consumers 组件中触发意外的渲染。举个例子,当每一次 Provider 重渲染时,以下的代码会重渲染所有下面的 consumers 组件,因为 <code>value</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></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">App</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span> </span>{</span><br><span class="line"> render() {</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <MyContext.Provider value={{<span class="attr">something</span>: <span class="string">'something'</span>}}></span><br><span class="line"> <Toolbar /></span><br><span class="line"> <<span class="regexp">/MyContext.Provider></span></span><br><span class="line"><span class="regexp"> );</span></span><br><span class="line"><span class="regexp"> }</span></span><br><span class="line"><span class="regexp">}</span></span><br></pre></td></tr></table></figure>
<p>2、从Provider到下属consumer的数据传递不受shouldComponentUpdate方法的约束,因此,即使上层组件跳过更新,Consumer也会被更新。</p>
<p>3、对于组件之间的数据通信或者状态管理,有效使用props或者state解决,然后再考虑使用第三方的成熟库进行解决,以上的方法都不是最佳的方案的时候,再考虑context。</p>
<h2 id="4、在HOOKS的中使用"><a href="#4、在HOOKS的中使用" class="headerlink" title="4、在HOOKS的中使用"></a>4、在HOOKS的中使用</h2><p>1、useContext</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> themes = {</span><br><span class="line"> light: {</span><br><span class="line"> foreground: <span class="string">"#000000"</span>,</span><br><span class="line"> background: <span class="string">"#eeeeee"</span></span><br><span class="line"> },</span><br><span class="line"> dark: {</span><br><span class="line"> foreground: <span class="string">"#ffffff"</span>,</span><br><span class="line"> background: <span class="string">"#222222"</span></span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> ThemeContext = React.createContext(themes.light);</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">App</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <ThemeContext.Provider value={themes.dark}></span><br><span class="line"> <Toolbar /></span><br><span class="line"> <<span class="regexp">/ThemeContext.Provider></span></span><br><span class="line"><span class="regexp"> );</span></span><br><span class="line"><span class="regexp">}</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">function Toolbar(props) {</span></span><br><span class="line"><span class="regexp"> return (</span></span><br><span class="line"><span class="regexp"> <div></span></span><br><span class="line"><span class="regexp"> <ThemedButton /</span>></span><br><span class="line"> <<span class="regexp">/div></span></span><br><span class="line"><span class="regexp"> );</span></span><br><span class="line"><span class="regexp">}</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">function ThemedButton() {</span></span><br><span class="line"><span class="regexp"> const theme = useContext(ThemeContext); </span></span><br><span class="line"><span class="regexp"> return ( </span></span><br><span class="line"><span class="regexp"> <button style={{ background:theme.background, color:theme.foreground }}>{theme}</span></span><br><span class="line"><span class="regexp"> </</span>button> </span><br><span class="line"> );</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>2、结合useReducer产生类似redux的效果</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React, {useContext, useReducer} <span class="keyword">from</span> <span class="string">'react'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> reducer = <span class="function">(<span class="params">state = <span class="number">0</span>, {type}</span>) =></span> {</span><br><span class="line"> <span class="keyword">switch</span> (type) {</span><br><span class="line"> <span class="keyword">case</span> <span class="string">"add"</span>:</span><br><span class="line"> <span class="keyword">return</span> state + <span class="number">1</span></span><br><span class="line"> <span class="keyword">case</span> <span class="string">'delete'</span>:</span><br><span class="line"> <span class="keyword">return</span> state - <span class="number">1</span></span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> <span class="keyword">return</span> state;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="keyword">const</span> Context = React.createContext(<span class="literal">null</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> Hook = <span class="function"><span class="params">()</span> =></span> {</span><br><span class="line"> <span class="comment">/*useReducer第二个参数为count的初始值*/</span></span><br><span class="line"> <span class="keyword">const</span> [count, dispatch] = useReducer(reducer, <span class="number">10</span>)</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <Context.Provider value={[count, dispatch]}></span><br><span class="line"> <div></span><br><span class="line"> <div>mom ... {count}<<span class="regexp">/div></span></span><br><span class="line"><span class="regexp"> <Child/</span>></span><br><span class="line"> {<span class="comment">/*父组件直接更新count*/</span>}</span><br><span class="line"> <button onClick={() => dispatch({<span class="attr">type</span>: <span class="string">'add'</span>})}>mom add<<span class="regexp">/button></span></span><br><span class="line"><span class="regexp"> <button onClick={() => dispatch({type: 'delete'})}>mom delete</</span>button></span><br><span class="line"> <<span class="regexp">/div></span></span><br><span class="line"><span class="regexp"> </</span>Context.Provider></span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> Child = <span class="function"><span class="params">()</span> =></span> {</span><br><span class="line"> <span class="comment">/*子组件从Context获取count, dispatch*/</span></span><br><span class="line"> <span class="keyword">const</span> [count, dispatch] = useContext(Context)</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> <div>child...{count}<<span class="regexp">/div></span></span><br><span class="line"><span class="regexp"> <button onClick={() => dispatch({type: 'add'})}>child add</</span>button></span><br><span class="line"> <button onClick={() => dispatch({<span class="attr">type</span>: <span class="string">'delete'</span>})}>child <span class="keyword">delete</span><<span class="regexp">/button></span></span><br><span class="line"><span class="regexp"> </</span>div>)</span><br><span class="line">}</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> Hook</span><br></pre></td></tr></table></figure>
<p>参考</p>
<p><a href="https://juejin.im/post/5e53d9116fb9a07c9070da44#heading-25" target="_blank" rel="noopener">https://juejin.im/post/5e53d9116fb9a07c9070da44#heading-25</a></p>
<p><a href="https://react.docschina.org/docs/context.html" target="_blank" rel="noopener">https://react.docschina.org/docs/context.html</a></p>
<p><a href="https://react.docschina.org/docs/hooks-reference.html" target="_blank" rel="noopener">https://react.docschina.org/docs/hooks-reference.html</a></p>
<p><a href="https://github.com/haizlin/fe-interview/issues/943" target="_blank" rel="noopener">https://github.com/haizlin/fe-interview/issues/943</a></p>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2020/04/07/来总结一下Context/" data-id="ck8q2ynl300035xztnwvl6pta" class="article-share-link">Share</a>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/React/">React</a></li></ul>
</footer>
</div>
</article>
<article id="post-React之Class组件生命周期与Hook对比" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2020/04/04/React之Class组件生命周期与Hook对比/" class="article-date">
<time datetime="2020-04-03T16:00:00.000Z" itemprop="datePublished">2020-04-04</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2020/04/04/React之Class组件生命周期与Hook对比/">React生命周期</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h2 id="Class组件的声明周期"><a href="#Class组件的声明周期" class="headerlink" title="Class组件的声明周期"></a>Class组件的声明周期</h2><p>俗话说,温故而知新。虽说目前很多数人提倡全面拥抱Hook,在拥抱之前不如再复习下class组件的生命周期。</p>
<h3 id="React16-3之前的生命周期"><a href="#React16-3之前的生命周期" class="headerlink" title="React16.3之前的生命周期"></a>React16.3之前的生命周期</h3><p><img src="/2020/04/04/React之Class组件生命周期与Hook对比/lifecycle16.3.png" alt></p>
<p>可以看到生命周期分为4个阶段:Initialization初始化、Mounting挂载、Updation更新、Unmounting卸载。</p>
<p>加了删除线的生命周期在16.3之后已移除.</p>
<h4 id="Initialization初始化"><a href="#Initialization初始化" class="headerlink" title="Initialization初始化"></a><strong>Initialization初始化</strong></h4><p><strong>1、constructor(props)</strong></p>
<p>在 React 组件挂载之前,会调用它的构造函数<code>constructor()</code>。</p>
<p>如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数。</p>
<h4 id="Mounting挂载"><a href="#Mounting挂载" class="headerlink" title="Mounting挂载"></a>Mounting挂载</h4><p><del><strong>1、componentWillMount()</strong></del></p>
<p>它在 <code>render()</code> 之前调用,因此在此方法中同步调用 <code>setState()</code> 不会触发额外渲染。通常,建议使用 <code>constructor()</code> 来初始化 state。避免在此方法中引入任何副作用或订阅。如遇此种情况,请改用 <code>componentDidMount()</code>。</p>
<p>此方法是服务端渲染唯一会调用的生命周期函数。</p>
<p><strong>2、render()</strong></p>
<p><code>render()</code> 方法是 class 组件中唯一必须实现的方法。<code>render()</code> 函数应该为纯函数,这意味着在不修改组件 state 的情况下,每次调用时都返回相同的结果,并且它不会直接与浏览器交互。</p>
<p><strong>3、componentDidMount()</strong></p>
<p><code>componentDidMount()</code> 会在组件挂载后(插入 DOM 树中)立即调用。依赖于 DOM 节点的初始化应该放在这里。如需通过网络请求获取数据,此处是实例化请求的好地方。</p>
<p>这个方法是比较适合添加订阅的地方。如果添加了订阅,请不要忘记在 <code>componentWillUnmount()</code> 里取消订阅。</p>
<p>你可以在 <code>componentDidMount()</code> 里<strong>直接调用 <code>setState()</code></strong>。它将触发额外渲染,但此渲染会发生在浏览器更新屏幕之前。如此保证了即使在 <code>render()</code> 两次调用的情况下,用户也不会看到中间状态。</p>
<h4 id="Updation更新"><a href="#Updation更新" class="headerlink" title="Updation更新"></a>Updation更新</h4><p><strong><del>1、componentWillReceiveProps(nextProps)</del></strong></p>
<p><code>componentWillReceiveProps()</code> 会在已挂载的组件接收新的 props 之前被调用。如果你需要更新状态以响应 prop 更改(例如,重置它),你可以比较 <code>this.props</code> 和 <code>nextProps</code> 并在此方法中使用 <code>this.setState()</code> 执行 state 转换。</p>
<p>请注意,如果父组件导致组件重新渲染,即使 props 没有更改,也会调用此方法。如果只想处理更改,请确保进行当前值与变更值的比较。</p>
<p>在挂载过程中,React 不会针对初始 props 调用 <code>componentWillReceiveProps()</code>。组件只会在组件的 props 更新时调用此方法。调用 <code>this.setState()</code> 通常不会触发 <code>componentWillReceiveProps()</code>。</p>
<p><strong>2、shouldComponentUpdate(nextProps, nextState)</strong></p>
<p>根据 <code>shouldComponentUpdate()</code> 的返回值,判断 React 组件的输出是否受当前 state 或 props 更改的影响。默认行为是 state 每次发生变化组件都会重新渲染。大部分情况下,你应该遵循默认行为。</p>
<p>当 props 或 state 发生变化时,<code>shouldComponentUpdate()</code> 会在渲染执行之前被调用。返回值默认为 true。首次渲染或使用 <code>forceUpdate()</code> 时不会调用该方法。</p>
<p>如果你一定要手动编写此函数,可以将 <code>this.props</code> 与 <code>nextProps</code> 以及 <code>this.state</code> 与<code>nextState</code> 进行比较,并返回 <code>false</code> 以告知 React 可以跳过更新。请注意,返回 <code>false</code> 并不会阻止子组件在 state 更改时重新渲染。</p>
<p>我们不建议在 <code>shouldComponentUpdate()</code> 中进行深层比较或使用 <code>JSON.stringify()</code>。这样非常影响效率,且会损害性能。</p>
<p><strong><del>3、componentWillUpdate(nextProps, nextState)</del></strong></p>
<p>当组件收到新的 props 或 state 时,会在渲染之前调用 <code>componentWillUpdate()</code>。使用此作为在更新发生之前执行准备更新的机会。初始渲染不会调用此方法。</p>
<p>注意,你不能此方法中调用 <code>this.setState()</code>;在 <code>componentWillUpdate()</code> 返回之前,你也不应该执行任何其他操作(例如,dispatch Redux 的 action)触发对 React 组件的更新。</p>
<p>所以基本上可以理解为没啥用吧。</p>
<p><strong>4、render()</strong></p>
<p><strong>5、componentDidUpdate(prevProps, prevState)</strong></p>
<p><code>componentDidUpdate()</code> 会在更新后会被立即调用。首次渲染不会执行此方法。</p>
<h4 id="Unmounting卸载"><a href="#Unmounting卸载" class="headerlink" title="Unmounting卸载"></a>Unmounting卸载</h4><p><strong>1、componentWillunmount</strong></p>
<p><code>componentWillUnmount()</code> 会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 <code>componentDidMount()</code> 中创建的订阅等。</p>
<p><code>componentWillUnmount()</code> 中<strong>不应调用 <code>setState()</code></strong>,因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。</p>
<h3 id="React16-3之后的生命周期"><a href="#React16-3之后的生命周期" class="headerlink" title="React16.3之后的生命周期"></a>React16.3之后的生命周期</h3><p><img src="/2020/04/04/React之Class组件生命周期与Hook对比/lifecycle16.4.png" alt></p>
<p>即更新后的生命周期为:</p>
<ol>
<li><p>挂载阶段</p>
<ul>
<li><p><code>constructor</code></p>
</li>
<li><p><code>static getDerivedStateFromProps(props, state)</code><strong>(新增</strong>)</p>
<p><code>getDerivedStateFromProps</code> 会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。</p>
<p>此方法适用于罕见的用例,即 state 的值在任何时候都取决于 props。</p>
</li>
<li><p><code>render</code></p>
</li>
<li><p><code>componentDidMount</code></p>
</li>
</ul>
</li>
<li><p>更新阶段</p>
<ul>
<li><p><code>static getDerivedStateFromProps(props, state)s</code></p>
</li>
<li><p><code>shouldComponentUpdate(nextProps, nextState)</code></p>
</li>
<li><p><code>render</code></p>
</li>
<li><p><code>getSnapshotBeforeUpdate(prevProps, prevState)</code><strong>(新增)</strong></p>
<p><code>getSnapshotBeforeUpdate()</code> 在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 <code>componentDidUpdate()</code>。</p>
</li>
<li><p><code>componentDidUpdate(prevProps, prevState, snapshot)</code></p>
</li>
</ul>
</li>
<li><p>卸载阶段</p>
<ul>
<li><code>componentWillUnmount</code></li>
</ul>
</li>
</ol>
<h3 id="全面拥抱Hooks"><a href="#全面拥抱Hooks" class="headerlink" title="全面拥抱Hooks"></a>全面拥抱Hooks</h3><p>不要在各种生命周期里徘徊了,请全面拥抱hooks吧!</p>
<p><a href="https://zh-hans.reactjs.org/docs/hooks-effect.html" target="_blank" rel="noopener">https://zh-hans.reactjs.org/docs/hooks-effect.html</a></p>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2020/04/04/React之Class组件生命周期与Hook对比/" data-id="ck8q2ynko00005xztr6szw7yi" class="article-share-link">Share</a>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/React/">React</a></li></ul>
</footer>
</div>
</article>
<article id="post-ES6" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2020/04/02/ES6/" class="article-date">
<time datetime="2020-04-01T16:00:00.000Z" itemprop="datePublished">2020-04-02</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2020/04/02/ES6/">ES6核心概念</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h4 id="0、ES6的含义"><a href="#0、ES6的含义" class="headerlink" title="0、ES6的含义"></a>0、ES6的含义</h4><p>ES是EcamScript的缩写,是一个定制脚本语言标准的组织</p>
<p>可以把ES6理解为JavaScript6</p>
<p>ES6及之后的版本可以认为是现代的JavaScript</p>
<h4 id="1、Let和Const"><a href="#1、Let和Const" class="headerlink" title="1、Let和Const"></a><strong>1、Let和Const</strong></h4><table>
<thead>
<tr>
<th style="text-align:left"></th>
<th>let 和 const</th>
<th>var</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">能否重复声明变量</td>
<td>不可以</td>
<td>可以</td>
</tr>
<tr>
<td style="text-align:left">作用域范围</td>
<td>块作用域</td>
<td>函数作用域</td>
</tr>
</tbody>
</table>
<p>行业规范:建议用const,除非确认后续会改变的变量再用let</p>
<h4 id="2、箭头函数"><a href="#2、箭头函数" class="headerlink" title="2、箭头函数"></a><strong>2、箭头函数</strong></h4><p><strong>写法更加简洁</strong></p>
<p>函数体单行可以省略{}及return</p>
<p>单个参数可以省略()</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"><span class="keyword">const</span> square = <span class="function"><span class="params">a</span> =></span> a * a;</span><br></pre></td></tr></table></figure>
<p><strong>箭头函数不会绑定this,普通function的this会在运行时绑定</strong></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></pre></td><td class="code"><pre><span class="line"><span class="built_in">document</span>.getElementById(<span class="string">'the-button'</span>)</span><br><span class="line"> .addEventListener(<span class="string">'click'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="comment">//这里不能用箭头函数,否则this会指向window</span></span><br><span class="line"> <span class="keyword">this</span>.classList.add(<span class="string">'bigger'</span>);</span><br><span class="line"> <span class="comment">//这里可以用箭头函数,this指向外层的this,也就是这个dom对象。如果不用箭头函数,this也会指向window</span></span><br><span class="line"> setTimeout(<span class="function"><span class="params">()</span> =></span> {</span><br><span class="line"> <span class="keyword">this</span>.innerHTML = <span class="string">'clicked'</span>;</span><br><span class="line"> }, <span class="number">1000</span>);</span><br><span class="line">});</span><br></pre></td></tr></table></figure>
<h4 id="3、模板字符串(实用)"><a href="#3、模板字符串(实用)" class="headerlink" title="3、模板字符串(实用)"></a>3、模板字符串(实用)</h4><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> person = {</span><br><span class="line"> name:<span class="string">'Colin'</span>,</span><br><span class="line"> age: <span class="string">'18'</span></span><br><span class="line">};</span><br><span class="line"><span class="comment">//支持直接换行及逻辑判断</span></span><br><span class="line"><span class="keyword">const</span> intro = <span class="string">`大家好,我是<span class="subst">${person.name}</span>,今年<span class="subst">${person.age}</span>岁,来自杭州。</span></span><br><span class="line"><span class="string">我明年就<span class="subst">${person.age + <span class="number">1</span>}</span>岁了,我是<span class="subst">${person.age > <span class="number">18</span> ? <span class="string">'成年人'</span> : <span class="string">'少年'</span>}</span>。`</span>;</span><br></pre></td></tr></table></figure>
<h4 id="4、Set和Map"><a href="#4、Set和Map" class="headerlink" title="4、Set和Map"></a>4、Set和Map</h4><p>Set的用法</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> numberSet = <span class="keyword">new</span> <span class="built_in">Set</span>();</span><br><span class="line">numberSet.add(<span class="number">1</span>);</span><br><span class="line">numberSet.add(<span class="number">2</span>);</span><br><span class="line">numberSet.add(<span class="number">3</span>);</span><br><span class="line">numberSet.add(<span class="number">1</span>);</span><br><span class="line">numberSet.add(<span class="number">3</span>);</span><br><span class="line">numberSet.add(<span class="number">7</span>);</span><br><span class="line"><span class="comment">//{1, 2, 3, 7}</span></span><br><span class="line"></span><br><span class="line">numberSet.delete(<span class="number">1</span>); <span class="comment">//true</span></span><br><span class="line"><span class="built_in">console</span>.log(numberSet); <span class="comment">//{2,3,7}</span></span><br><span class="line"></span><br><span class="line">numberSet.has(<span class="number">2</span>); <span class="comment">//true</span></span><br><span class="line"></span><br><span class="line">numberSet.size; <span class="comment">//3</span></span><br><span class="line"></span><br><span class="line">numberSet.forEach(<span class="function"><span class="params">number</span> =></span> <span class="built_in">console</span>.log(number));</span><br><span class="line"><span class="comment">//2</span></span><br><span class="line"><span class="comment">//3</span></span><br><span class="line"><span class="comment">//7</span></span><br></pre></td></tr></table></figure>
<p>Map的用法</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">const</span> person = <span class="keyword">new</span> <span class="built_in">Map</span>();</span><br><span class="line">person.set(<span class="string">'name'</span>, <span class="string">'Colin'</span>);</span><br><span class="line">person.set(<span class="string">'age'</span>, <span class="string">'18'</span>);</span><br><span class="line">person.set(<span class="string">'hobby'</span>, [<span class="string">'吃'</span>,<span class="string">'喝'</span>]);</span><br><span class="line"></span><br><span class="line">person.get(<span class="string">'name'</span>);<span class="comment">//Colin</span></span><br><span class="line"></span><br><span class="line">person.size;<span class="comment">//3</span></span><br><span class="line"></span><br><span class="line">person.has(<span class="string">'age'</span>)<span class="comment">//true</span></span><br><span class="line"></span><br><span class="line">person.set(<span class="string">'age'</span>, <span class="string">'19'</span>);</span><br><span class="line"><span class="comment">//Map(3) {"name" => "Colin", "age" => 19, "hobby" => Array(2)}</span></span><br><span class="line"></span><br><span class="line">person.delete(<span class="string">'age'</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">const</span> item <span class="keyword">of</span> person){</span><br><span class="line"> <span class="built_in">console</span>.log(item);</span><br><span class="line">}</span><br><span class="line"><span class="comment">//["name", "Colin"]</span></span><br><span class="line"><span class="comment">//["age", "18"]</span></span><br><span class="line"><span class="comment">//["hobby", Array(2)]</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">const</span> [key, val] <span class="keyword">of</span> person){</span><br><span class="line"> <span class="built_in">console</span>.log(val);</span><br><span class="line">}</span><br><span class="line"><span class="comment">//Colin</span></span><br><span class="line"><span class="comment">//18</span></span><br><span class="line"><span class="comment">//['吃','喝']</span></span><br></pre></td></tr></table></figure>
<h4 id="5、解构赋值"><a href="#5、解构赋值" class="headerlink" title="5、解构赋值"></a>5、解构赋值</h4><p>Object的结构赋值</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">const</span> person = {</span><br><span class="line"> name:<span class="string">'Colin'</span>,</span><br><span class="line"> age: <span class="string">'18'</span>,</span><br><span class="line"> social: {</span><br><span class="line"> bilibili: <span class="string">'123'</span></span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> {</span><br><span class="line"> name, </span><br><span class="line"> social:{</span><br><span class="line"> bilibili</span><br><span class="line"> }</span><br><span class="line"> } = person;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> {</span><br><span class="line"> name : personName = <span class="string">'guset'</span>, <span class="comment">//重命名,并给出默认值</span></span><br><span class="line"> age = <span class="number">0</span>,<span class="comment">//默认为0</span></span><br><span class="line"> social:{</span><br><span class="line"> bilibili: bili</span><br><span class="line"> }</span><br><span class="line"> } = person;</span><br></pre></td></tr></table></figure>
<p>数组的结构赋值</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> info = <span class="string">'colin, 18'</span></span><br><span class="line"><span class="keyword">const</span> person = info.split(<span class="string">','</span>);</span><br><span class="line"><span class="keyword">const</span> [name, age] = person;</span><br><span class="line"></span><br><span class="line"><span class="comment">//实用小技巧,互换值</span></span><br><span class="line"><span class="keyword">let</span> a = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">let</span> b = <span class="number">-1</span>;</span><br><span class="line">[a, b] = [b, a];</span><br></pre></td></tr></table></figure>
<h4 id="6、剩余和扩展参数"><a href="#6、剩余和扩展参数" class="headerlink" title="6、剩余和扩展参数"></a>6、剩余和扩展参数</h4><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> team = [<span class="string">'赵'</span>,<span class="string">'钱'</span>,<span class="string">'孙'</span>,<span class="string">'李'</span>,<span class="string">'周'</span>,<span class="string">'吴'</span>];</span><br><span class="line"><span class="keyword">const</span> [a, b, ...c] = team;</span><br><span class="line"><span class="built_in">console</span>.log(c); <span class="comment">//["孙", "李", "周", "吴"]</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">sortNumbers</span>(<span class="params">...nums</span>)</span>{</span><br><span class="line"> <span class="built_in">console</span>.log(nums);<span class="comment">//[1, 2, 10]合并为一个数组</span></span><br><span class="line"> <span class="keyword">if</span>(nums.length === <span class="number">0</span>){</span><br><span class="line"> <span class="keyword">return</span> [];</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> <span class="keyword">return</span> nums.sort(<span class="function">(<span class="params">a, b</span>) =></span> a - b);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">sortNumbers(<span class="number">1</span>, <span class="number">2</span>, <span class="number">10</span>);</span><br></pre></td></tr></table></figure>
<p>扩展:把剩余的部分打撒</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="keyword">const</span> a = <span class="string">'赵'</span>;</span><br><span class="line"><span class="keyword">const</span> b = <span class="string">'钱'</span>;</span><br><span class="line"><span class="keyword">const</span> c = [<span class="string">"孙"</span>, <span class="string">"李"</span>, <span class="string">"周"</span>, <span class="string">"吴"</span>];</span><br><span class="line"><span class="keyword">const</span> team = [a, b, ...c]; <span class="comment">//['赵','钱','孙','李','周','吴']</span></span><br></pre></td></tr></table></figure>
<h4 id="7、函数默认参数值"><a href="#7、函数默认参数值" class="headerlink" title="7、函数默认参数值"></a>7、函数默认参数值</h4><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="function"><span class="keyword">function</span> <span class="title">orderCombo</span>(<span class="params">comboName = <span class="string">'巨无霸'</span>, drink = <span class="string">'可口可乐'</span></span>)</span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`您点了<span class="subst">${comboName}</span>,饮料是<span class="subst">${drink}</span>`</span>);</span><br><span class="line">}</span><br><span class="line">orderCombo(<span class="string">'鸡腿堡'</span>,<span class="string">'雪碧'</span>);</span><br><span class="line">orderCombo(<span class="literal">undefined</span>,<span class="string">'雪碧'</span>);</span><br></pre></td></tr></table></figure>
<h4 id="8、字符串方法"><a href="#8、字符串方法" class="headerlink" title="8、字符串方法"></a>8、字符串方法</h4><p>includes</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> string = <span class="string">'abc'</span></span><br><span class="line"><span class="keyword">const</span> subString = <span class="string">'ab'</span></span><br><span class="line">string.includes(subString)<span class="comment">//true string是否包含subString</span></span><br></pre></td></tr></table></figure>
<p>startsWith</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="keyword">const</span> string = <span class="string">'abc'</span></span><br><span class="line"><span class="keyword">const</span> subString = <span class="string">'ab'</span></span><br><span class="line">string.startsWith(subString)<span class="comment">//true string是否以subString开头</span></span><br><span class="line">string.startsWith(<span class="number">1</span>, <span class="string">'b'</span>)<span class="comment">//true string从第二位开始是否以‘b’开头</span></span><br></pre></td></tr></table></figure>
<p>endsWith</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="keyword">const</span> string = <span class="string">'abc'</span></span><br><span class="line"><span class="keyword">const</span> subString = <span class="string">'bc'</span></span><br><span class="line">string.endsWith(subString)<span class="comment">//true string是否以subString结尾</span></span><br><span class="line">string.endsWith(<span class="string">'b'</span>,<span class="number">2</span>)<span class="comment">//true string的前2位是否以‘b’结尾</span></span><br></pre></td></tr></table></figure>
<h4 id="9、for…of"><a href="#9、for…of" class="headerlink" title="9、for…of"></a>9、for…of</h4><p>数组、set、map</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 class="keyword">const</span> foods = [</span><br><span class="line"> <span class="string">'香辣鸡腿堡'</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 class="string">'新奥尔良烤鸡腿堡'</span></span><br><span class="line">]</span><br><span class="line"><span class="comment">//foods.entries()生成一个迭代器,可以获取序号。set也可以用。map用了没效果,object不能用。</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">const</span> [index, food] <span class="keyword">of</span> foods.entries()){</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`第<span class="subst">${index + <span class="number">1</span>}</span>号套餐的汉堡是<span class="subst">${food}</span>`</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>对Object的遍历还是要用for…in</p>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2020/04/02/ES6/" data-id="ck8q2ynky00015xztwtvk1vva" class="article-share-link">Share</a>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/ES6/">ES6</a></li></ul>
</footer>
</div>
</article>
<article id="post-Redux基础原理与实例" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2018/11/04/Redux基础原理与实例/" class="article-date">
<time datetime="2018-11-04T02:50:33.000Z" itemprop="datePublished">2018-11-04</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2018/11/04/Redux基础原理与实例/">Redux基础原理与实例</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h2 id="1、Redux是什么"><a href="#1、Redux是什么" class="headerlink" title="1、Redux是什么"></a>1、Redux是什么</h2><p>Redux是一个专注于数据状态管理的库,和React解耦(使用Vue或者其他前端框架也可以使用Redux)。其特点是单一状态(single state)及单向数据流。即:<br>(1)Web应用是一个状态机,视图与状态是一一对应的。<br>(2)所有的状态,保存在一个对象里面。</p>
<h3 id="1-1、Redux核心概念"><a href="#1-1、Redux核心概念" class="headerlink" title="1.1、Redux核心概念"></a>1.1、Redux核心概念</h3><p>以下是Redux中的几个核心概念:</p>
<h4 id="Store"><a href="#Store" class="headerlink" title="Store"></a>Store</h4><p>Store 就是保存数据的地方,整个应用只能有一个Store。</p>
<h4 id="State"><a href="#State" class="headerlink" title="State"></a>State</h4><p>Store对象包含所有数据。如果想得到某个时点的数据,就要对 Store 生成快照。这种时点的数据集合,就叫做 State,一个 State 对应一个 View。</p>
<h4 id="Action"><a href="#Action" class="headerlink" title="Action"></a>Action</h4><p>用户改变 State 的唯一办法,就是使用 Action。Action 就是 View 发出的通知,表示 State 应该要发生变化了。</p>
<h4 id="Reducer"><a href="#Reducer" class="headerlink" title="Reducer"></a>Reducer</h4><p>Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer。</p>
<h3 id="1-2、Redux的使用步骤"><a href="#1-2、Redux的使用步骤" class="headerlink" title="1.2、Redux的使用步骤"></a>1.2、Redux的使用步骤</h3><p>(1)通过reducer新建store,通过store.getState()获取当前state状态;<br>(2)若要改变当前state的状态,通过store.dispatch(action)进行;(store.dispatch()是 View 发出 Action 的唯一方法。)<br>(3)Reducer接受当前state和action,并返回新的state;</p>
<p>以下是React的工作流程图:<br><img src="/2018/11/04/Redux基础原理与实例/reduxFlow.jpg" alt></p>
<p>举个🌰<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">import {createStore} from <span class="string">'redux'</span></span><br><span class="line"></span><br><span class="line">//0 创建一个Reducer</span><br><span class="line"><span class="keyword">function</span> counter(state=0,action){</span><br><span class="line"> switch(action.type){</span><br><span class="line"> <span class="keyword">case</span>:<span class="string">'ADD'</span></span><br><span class="line"> <span class="built_in">return</span> state + 1</span><br><span class="line"> <span class="keyword">case</span>: <span class="string">'MINUS'</span></span><br><span class="line"> <span class="built_in">return</span> state - 1 </span><br><span class="line"> default:</span><br><span class="line"> <span class="built_in">return</span> 10 </span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">// 1 创建store</span><br><span class="line">const store = createStore(counter)</span><br><span class="line">store.getState() //10</span><br><span class="line"></span><br><span class="line">//2 派发事件,传递action</span><br><span class="line">store.dispatch({<span class="built_in">type</span>:<span class="string">'ADD'</span>})</span><br><span class="line">store.getState()//11</span><br></pre></td></tr></table></figure></p>
<p>此外,Store允许使用store.subscribe方法设置监听函数,一旦State发生变化,就自动执行这个函数。<br><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="function"><span class="keyword">function</span> <span class="title">listen</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="built_in">console</span>.log(store.getState())</span><br><span class="line">}</span><br><span class="line">store.subscribe(listen)</span><br></pre></td></tr></table></figure></p>
<h2 id="2、Redux如何与React一起使用"><a href="#2、Redux如何与React一起使用" class="headerlink" title="2、Redux如何与React一起使用"></a>2、Redux如何与React一起使用</h2><h3 id="2-1、使用原理"><a href="#2-1、使用原理" class="headerlink" title="2.1、使用原理"></a>2.1、使用原理</h3><p>(1)把stroe.dispatch()方法传递给react组件,组件内部可以调用从而修改状态<br>(2)store.subscribe方法订阅render函数,每次修改都重新渲染<br>(3)redux相关内容单独(文件)管理</p>
<h3 id="2-2、举🌰"><a href="#2-2、举🌰" class="headerlink" title="2.2、举🌰"></a>2.2、举🌰</h3><p>使用一个index.redux.js单独管理redux相关内容,修改之前的代码<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">//index.redux.js</span><br><span class="line"><span class="built_in">export</span> <span class="keyword">function</span> counter(state=0,action){</span><br><span class="line"> switch(action.type){</span><br><span class="line"> <span class="keyword">case</span>:<span class="string">'ADD'</span></span><br><span class="line"> <span class="built_in">return</span> state + 1</span><br><span class="line"> <span class="keyword">case</span>: <span class="string">'MINUS'</span></span><br><span class="line"> <span class="built_in">return</span> state - 1 </span><br><span class="line"> default:</span><br><span class="line"> <span class="built_in">return</span> 10 </span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">//创建统一的Acion Creator</span><br><span class="line"><span class="built_in">export</span> <span class="keyword">function</span> <span class="function"><span class="title">add</span></span>(){</span><br><span class="line"> <span class="built_in">return</span> {<span class="built_in">type</span>:<span class="string">'ADD'</span>}</span><br><span class="line">}</span><br><span class="line"><span class="built_in">export</span> <span class="keyword">function</span> <span class="function"><span class="title">minus</span></span>(){</span><br><span class="line"> <span class="built_in">return</span> {<span class="built_in">type</span>:<span class="string">'Minus'</span>}</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<p>//index.js中,向App组件传递store等参数<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">//index.js</span><br><span class="line">import {counter, add} from <span class="string">'./index.redux'</span></span><br><span class="line">const store = createStore(counter)</span><br><span class="line"><span class="keyword">function</span> <span class="function"><span class="title">render</span></span>(){</span><br><span class="line"> ReactDom.render(<App store={store} add={add}/>,</span><br><span class="line"> document.getElementById(<span class="string">'root'</span>))</span><br><span class="line">}</span><br><span class="line">store.subscribe(render) //订阅render函数,每次修改都重新渲染</span><br></pre></td></tr></table></figure></p>
<p>//App.js<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">//App.js</span><br><span class="line">class App extends React.Component{</span><br><span class="line"> <span class="function"><span class="title">render</span></span>(){</span><br><span class="line"> //接受props</span><br><span class="line"> const store = this.props.store</span><br><span class="line"> const add = this.props.add</span><br><span class="line"> const num = store.getState()</span><br><span class="line"> <span class="built_in">return</span> {</span><br><span class="line"> <div></span><br><span class="line"> <button onClick={() => store.dispatch(add())}>点击+1</button></span><br><span class="line"> <h1><span class="variable">${num}</span></h1></span><br><span class="line"> </div></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<h2 id="3、Redux异步处理"><a href="#3、Redux异步处理" class="headerlink" title="3、Redux异步处理"></a>3、Redux异步处理</h2><p>步骤如下:<br>(1)使用redux-trunk插件进行异步处理,首先进行安装;<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install redux-trunk --save</span><br></pre></td></tr></table></figure></p>
<p>(2)使用applyMiddleWare开启redux-trunk中间件;<br>(3)Action可以返回函数,异步完成后进行dispatch;</p>
<p>举个栗子,修改index.js<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">//index.js</span><br><span class="line">//引入中间件applyMiddleWare</span><br><span class="line">import {createStore, applyMiddleWare} from <span class="string">'redux'</span></span><br><span class="line">//引入trunk</span><br><span class="line">import trunk from <span class="string">'redux-trunk'</span></span><br><span class="line">//创建store时传入applyMiddleWare</span><br><span class="line">const store = createStore(counter,applyMiddleWare(trunk))</span><br></pre></td></tr></table></figure></p>
<p>在index.redux.js中新增一个函数,2秒后再dispatch<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">//index.redux.js</span><br><span class="line"><span class="built_in">export</span> <span class="keyword">function</span> counter(state=0,action){</span><br><span class="line"> switch(action.type){</span><br><span class="line"> <span class="keyword">case</span>:<span class="string">'ADD'</span></span><br><span class="line"> <span class="built_in">return</span> state + 1</span><br><span class="line"> <span class="keyword">case</span>: <span class="string">'MINUS'</span></span><br><span class="line"> <span class="built_in">return</span> state - 1 </span><br><span class="line"> default:</span><br><span class="line"> <span class="built_in">return</span> 10 </span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">//创建统一的Acion Creator</span><br><span class="line"><span class="built_in">export</span> <span class="keyword">function</span> <span class="function"><span class="title">add</span></span>(){</span><br><span class="line"> <span class="built_in">return</span> {<span class="built_in">type</span>:<span class="string">'ADD'</span>}</span><br><span class="line">}</span><br><span class="line"><span class="built_in">export</span> <span class="keyword">function</span> <span class="function"><span class="title">minus</span></span>(){</span><br><span class="line"> <span class="built_in">return</span> {<span class="built_in">type</span>:<span class="string">'Minus'</span>}</span><br><span class="line">}</span><br><span class="line">//2秒后再dispatch:同步<span class="built_in">return</span>对象 异步<span class="built_in">return</span>函数</span><br><span class="line"><span class="built_in">export</span> <span class="keyword">function</span> <span class="function"><span class="title">addAsync</span></span>(){</span><br><span class="line"> <span class="built_in">return</span> dispatch => {</span><br><span class="line"> setTimeout(()=>{</span><br><span class="line"> dispatch(add())</span><br><span class="line"> },2000)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<p>新增异步点击<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">//App.js</span><br><span class="line">class App extends React.Component{</span><br><span class="line"> <span class="function"><span class="title">render</span></span>(){</span><br><span class="line"> //接受props</span><br><span class="line"> const store = this.props.store</span><br><span class="line"> const add = this.props.add</span><br><span class="line"> const addAsync = this.props.addAsync</span><br><span class="line"> const num = store.getState()</span><br><span class="line"> //新增异步点击</span><br><span class="line"> <span class="built_in">return</span> {</span><br><span class="line"> <div></span><br><span class="line"> <button onClick={() => store.dispatch(add())}>点击+1</button></span><br><span class="line"> <button onClick={() => store.dispatch(addAsync())}>点击2秒后+1</button></span><br><span class="line"> <h1><span class="variable">${num}</span></h1></span><br><span class="line"> </div></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<h2 id="3-4、-Redux调试工具"><a href="#3-4、-Redux调试工具" class="headerlink" title="3-4、 Redux调试工具"></a>3-4、 Redux调试工具</h2><p>Redux-DevTools</p>
<figure class="highlight plain"><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">const store = createStore(reducers, compose(</span><br><span class="line"> applyMiddleware(thunk),</span><br><span class="line"> window.devToolsExtension?window.devToolsExtension():f => f</span><br><span class="line">))</span><br></pre></td></tr></table></figure>
<h2 id="4、使用react-redux"><a href="#4、使用react-redux" class="headerlink" title="4、使用react-redux"></a>4、使用react-redux</h2><p>redux使用较为复杂,我们当前是把store作为属性传入组件中,如果其他组件也需要store,store就好一层层传递,陷入属性传递的深渊中。<br>使用react-redux可以解决redux使用复杂的缺点。<br>(1)首先安装react-redux<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install react-redux --save</span><br></pre></td></tr></table></figure></p>
<p>(2)使用Provider组件在最外层,只用传入store一次,改写index.js:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">//index.js</span><br><span class="line">import {createStore,applyMiddleWare} from <span class="string">'redux'</span></span><br><span class="line">import trunk from <span class="string">'redux-trunk'</span></span><br><span class="line">//引入Provider</span><br><span class="line">import {Provider} from <span class="string">'react-redux'</span></span><br><span class="line">const store = createStore(counter,applyMiddleWare(trunk))</span><br><span class="line">ReactDom.render(</span><br><span class="line">(<Provider store={store}></span><br><span class="line"> <APP/></span><br><span class="line"> </Provider>),</span><br><span class="line"> document.getElementById(<span class="string">'root'</span>))</span><br><span class="line">//去除subscribe</span><br><span class="line">//store.subscribe(render)</span><br></pre></td></tr></table></figure></p>
<p>(3)使用Connect获取外部所需参数,改写App.js<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">//App.js</span><br><span class="line">import {connect} from <span class="string">'react-redux'</span></span><br><span class="line">class App extends React.Component{</span><br><span class="line"> <span class="function"><span class="title">render</span></span>(){</span><br><span class="line"> <span class="built_in">return</span> {</span><br><span class="line"> <div></span><br><span class="line"> <button onClick={this.props.add}>点击+1</button></span><br><span class="line"> <h1>{this.props.num}</h1></span><br><span class="line"> </div></span><br><span class="line"> }//add自动有了dispatch的功能</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">//我们需要的状态</span><br><span class="line">const mapStateToProps = state => {</span><br><span class="line"> <span class="built_in">return</span> {num:state}</span><br><span class="line">}</span><br><span class="line">//我们需要的action,自动dispatch</span><br><span class="line">const actionCreators() = {add,minus}</span><br><span class="line"></span><br><span class="line">//react-redux会将mapStateToProps及actionCreators方在props中</span><br><span class="line">App = connect(mapStateToProps,actionCreators)(App)</span><br></pre></td></tr></table></figure></p>
<h2 id="5、优化结构(使用装饰器模式)"><a href="#5、优化结构(使用装饰器模式)" class="headerlink" title="5、优化结构(使用装饰器模式)"></a>5、优化结构(使用装饰器模式)</h2><p>1、npm run eject<br>2、package.json中更改配置:<br> 使用bable-plugin-transform-decorators-legacy支持装饰器写法<br> bable中则加配置 “plugins”:[transform-decorators-legacy]<br>3、优化4中APP.js中的写发<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">//App.js</span><br><span class="line">import {connect} from <span class="string">'react-redux'</span></span><br><span class="line">//App = connect(mapStateToProps,actionCreators)(App)</span><br><span class="line">@connect(</span><br><span class="line"> //你要state中的什么属性,放到props中</span><br><span class="line"> state => ({num:state}),</span><br><span class="line"> //你要state中的什么方法,放到props中,会自动store.dispatch(action)</span><br><span class="line"> {add,minus}</span><br><span class="line">)</span><br><span class="line">class App extends React.Component{</span><br><span class="line"> <span class="function"><span class="title">render</span></span>(){</span><br><span class="line"> <span class="built_in">return</span> {</span><br><span class="line"> <div></span><br><span class="line"> <button onClick={this.props.add}>点击+1</button></span><br><span class="line"> <h1>{this.props.num}</h1></span><br><span class="line"> </div></span><br><span class="line"> }//add自动有了dispatch的功能</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2018/11/04/Redux基础原理与实例/" data-id="ck8q2ynl500045xzt9sovxeff" class="article-share-link">Share</a>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/React/">React</a></li></ul>
</footer>
</div>
</article>
</section>
<aside id="sidebar">
<div class="widget-wrap">
<h3 class="widget-title">Tags</h3>
<div class="widget">
<ul class="tag-list"><li class="tag-list-item"><a class="tag-list-link" href="/tags/ES6/">ES6</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/React/">React</a></li></ul>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">Tag Cloud</h3>
<div class="widget tagcloud">
<a href="/tags/ES6/" style="font-size: 10px;">ES6</a> <a href="/tags/React/" style="font-size: 20px;">React</a>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">Archives</h3>
<div class="widget">
<ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/04/">April 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/11/">November 2018</a></li></ul>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">Recent Posts</h3>
<div class="widget">
<ul>
<li>
<a href="/2020/04/07/来总结一下Context/">来总结一下Context</a>
</li>
<li>
<a href="/2020/04/04/React之Class组件生命周期与Hook对比/">React生命周期</a>
</li>
<li>
<a href="/2020/04/02/ES6/">ES6核心概念</a>
</li>
<li>
<a href="/2018/11/04/Redux基础原理与实例/">Redux基础原理与实例</a>
</li>
</ul>
</div>
</div>
</aside>
</div>
<footer id="footer">
<div class="outer">
<div id="footer-info" class="inner">
© 2020 Colin Gao<br>
Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
</div>
</div>
</footer>
</div>
<nav id="mobile-nav">
<a href="/" class="mobile-nav-link">Home</a>
<a href="/archives" class="mobile-nav-link">Archives</a>
</nav>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<link rel="stylesheet" href="/fancybox/jquery.fancybox.css">
<script src="/fancybox/jquery.fancybox.pack.js"></script>
<script src="/js/script.js"></script>
</div>
</body>
</html>