-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
456 lines (241 loc) · 231 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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>MagicYou</title>
<link href="https://blog.magicyou.cn/atom.xml" rel="self"/>
<link href="https://blog.magicyou.cn/"/>
<updated>2022-08-31T13:33:00.000Z</updated>
<id>https://blog.magicyou.cn/</id>
<author>
<name>magicyou</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>Next.js 一些东西</title>
<link href="https://blog.magicyou.cn/2022/08/31/react-Next.js%20%E4%B8%80%E4%BA%9B%E4%B8%9C%E8%A5%BF/"/>
<id>https://blog.magicyou.cn/2022/08/31/react-Next.js%20%E4%B8%80%E4%BA%9B%E4%B8%9C%E8%A5%BF/</id>
<published>2022-08-31T13:33:00.000Z</published>
<updated>2022-08-31T13:33:00.000Z</updated>
<content type="html"><![CDATA[<p>Next.js 一些东西</p><h1 id="Next-js-一些东西"><a href="#Next-js-一些东西" class="headerlink" title="Next.js 一些东西"></a>Next.js 一些东西</h1><h2 id="一-疑问:为什么要用-Next-js"><a href="#一-疑问:为什么要用-Next-js" class="headerlink" title="一. 疑问:为什么要用 Next.js"></a>一. 疑问:为什么要用 Next.js</h2><h3 id="需要ssr"><a href="#需要ssr" class="headerlink" title="需要ssr"></a>需要ssr</h3><p>ssr是什么,发展历程</p><p>服务端渲染:后端先调用数据库,获取数据之后,将数据和页面元素进行拼装,组合成完整的html页面,在直接返回给浏览器,以便用户浏览</p><p>客户端渲染:数据有浏览器通过ajax动态获取,在通过js将数据填充到dom元素最终展示到网页中,这样的过程叫做客户端渲染。</p><p>服务端渲染 VS 客户端渲染</p><ol><li>服务端渲染需要消耗更多的服务器资源(CPU,内存等)</li><li>客户端渲染可以将静态资源部署到cdn上,实现实现高并发</li><li>服务端渲染对SEO更友好</li></ol><h3 id="如今的react和Vue"><a href="#如今的react和Vue" class="headerlink" title="如今的react和Vue"></a>如今的react和Vue</h3><ol><li>同样都是前后端分离</li><li>客户端页面渲染</li></ol><h2 id="二-Next-js-初始化"><a href="#二-Next-js-初始化" class="headerlink" title="二. Next.js 初始化"></a>二. Next.js 初始化</h2><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">yarn create next-app</span><br></pre></td></tr></table></figure><h2 id="三-路由"><a href="#三-路由" class="headerlink" title="三. 路由"></a>三. 路由</h2><p>在 Next.js 中,一个 page(页面) 就是一个从 .js、jsx、.ts 或 .tsx 文件导出(export)的 React 组件 ,这些文件存放在 pages 目录下。每个 page(页面)都使用其文件名作为路由(route)。</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">|- pages</span><br><span class="line"> |- index.js</span><br><span class="line"> |- help.js</span><br><span class="line"> |- about.js</span><br></pre></td></tr></table></figure><h3 id="路由基本使用"><a href="#路由基本使用" class="headerlink" title="路由基本使用"></a>路由基本使用</h3><p>link跳转(next/link)</p><ul><li><p>属性 href 添加跳转路径(默认是history的push模式,向历史纪录添加一条)</p><ul><li>字符串:“ /news?newsId=123 ”</li><li>对象: “ {pathname: ‘/news’, query: {newsId: ‘123’} } ”</li></ul></li><li><p>属性 replace 替换当前页面</p></li><li><p>属性 scroll 跳转到页面顶部,默认为true</p></li><li><p>属性 passHref,强制 link 将href发送给子元素,默认false </p></li><li><p>属性 prefetch,在后台预取目标页面。默认值为 true。(预取功能只在生产环境中开启)</p></li></ul><p>js编程式跳转</p><ul><li><p>useRouter React Hook</p></li><li><p>router.push(‘/testRouter1’)</p></li><li><p>router.push({pathname: ‘/testRouter1’, query: {id: ‘123’} })</p></li><li><p>withRouter class 组件</p></li></ul><p>router对象的定义参数:</p><table><thead><tr><th align="center">属性</th><th align="center">用法</th><th align="center">默认值</th></tr></thead><tbody><tr><td align="center">pathname</td><td align="center">- -</td><td align="center">- -</td></tr><tr><td align="center">query</td><td align="center">- -</td><td align="center">- -</td></tr></tbody></table><p>其他的用法</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><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">import { useRouter } from 'next/router' </span><br><span class="line">const router = useRouter()</span><br><span class="line"></span><br><span class="line">router.query // 当前地址参数</span><br><span class="line">router.replace()</span><br><span class="line">router.prefetch() // 同 link 标签的prefetch属性,仅对 link标签有效,只能用于生产环境</span><br><span class="line">router.beforePopState() // ***</span><br><span class="line">router.reload() // 等同 window.location.reload()</span><br><span class="line"></span><br></pre></td></tr></table></figure><ul><li>router.events 路由事件<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><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">import { useRouter } from 'next/router' </span><br><span class="line">const router = useRouter()</span><br><span class="line"></span><br><span class="line">routeChangeStart(url, { shallow }) // 路由改变时</span><br><span class="line">routeChangeComplete(url, { shallow }) // 路由改变之后</span><br><span class="line">routeChangeError(url, { shallow }) // 路由跳转错误</span><br><span class="line">routeChangeError(err, url, { shallow }) // 路由跳转错误</span><br><span class="line">beforeHistoryChange(err, url, { shallow }) // 在更改浏览器历史记录之前触发</span><br><span class="line">hashChangeStart(err, url, { shallow }) // 当哈希值已更改但页面未更改时触发</span><br><span class="line">hashChangeComplete(err, url, { shallow }) // 当哈希值已更改但页面未更改时触发</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure></li></ul><h3 id="动态路由"><a href="#动态路由" class="headerlink" title="动态路由"></a>动态路由</h3><p>pages 目录下的[typeId].js 就是动态路由。<br>比如当前目录:</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><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">|- pages</span><br><span class="line"> |- index.js</span><br><span class="line"> |- help.js</span><br><span class="line"> |- about.js</span><br><span class="line"> |- news</span><br><span class="line"> |- index.js</span><br><span class="line"> |- [typeId].js</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>‘pages/news/1’、’pages/news/2’、’pages/news/2?name=lxl‘ 都会匹配到 ’pages/news/[typeId].js‘</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></pre></td><td class="code"><pre><span class="line">{typeId: 1} // pages/news/1.js</span><br><span class="line">{typeId: 2} // pages/news/2.js</span><br><span class="line">{typeId: 2, name: lxl} // pages/news/2.js?name=lxl</span><br></pre></td></tr></table></figure><p>多个参数呢?<br>动态路由在pages目录下动态路由文件名加三个点来扩展捕获所有参数<br>‘pages/goods/生活用品’、’pages/goods/科技数码?isHot=1’、’pages/goods/文学作品/3’<br> 就可以匹配到 ’pages/goods/[…slugs].js‘。(’slugs‘是自定义的,根据需要自行定义即可)</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></pre></td><td class="code"><pre><span class="line">{slugs: ['生活用品']} // pages/goods/生活用品</span><br><span class="line">{slugs: ['科技数码'], isHot: '1'} // pages/goods/科技数码?isHot=1</span><br><span class="line">{slugs: ['文学作品', '3'], isHot: '1'} // pages/goods/文学作品/3</span><br></pre></td></tr></table></figure><h2 id="四-预加载"><a href="#四-预加载" class="headerlink" title="四. 预加载"></a>四. 预加载</h2><p>什么是预加载</p><ol><li>预加载是性能优化技术</li><li>所需资源提前加载到本地,这样后面在需要用的时候直接从缓存取资源<br>Link 标签的属性 prefetch</li></ol><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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">Link</span> <span class="attr">href</span>=<span class="string">"/"</span> <span class="attr">prefetch</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">a</span>></span>pageIndex<span class="tag"></<span class="name">a</span>></span></span><br><span class="line"><span class="tag"></<span class="name">Link</span>></span></span><br></pre></td></tr></table></figure><h2 id="五-404-和-错误页定制"><a href="#五-404-和-错误页定制" class="headerlink" title="五. 404 和 错误页定制"></a>五. 404 和 错误页定制</h2><p>pages目录下:</p><ul><li>定制 404: 404.js</li><li>定制 错误页: _error.js</li></ul><h2 id="六-css支持"><a href="#六-css支持" class="headerlink" title="六. css支持"></a>六. css支持</h2><h3 id="添加全局样式表"><a href="#添加全局样式表" class="headerlink" title="添加全局样式表"></a>添加全局样式表</h3><p>全局样式应在 ‘pages/_app.js’中引入</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="string">'../styles/globals.css'</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">'antd/dist/antd.css'</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">MyApp</span>(<span class="params">{ Component, pageProps }</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="xml"><span class="tag"><<span class="name">Component</span> {<span class="attr">...pageProps</span>} /></span></span></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> MyApp</span><br></pre></td></tr></table></figure><p>这些样式 (globals.css) 将应用于你的应用程序中的所有页面和组件。 并且为了避免冲突,应该 只在 pages/_app.js 文件中导入(import)这些全局样式表</p><h3 id="从-node-modules-目录导入(import)样式"><a href="#从-node-modules-目录导入(import)样式" class="headerlink" title="从 node_modules 目录导入(import)样式"></a>从 node_modules 目录导入(import)样式</h3><figure class="highlight plain"><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">import Texty from 'rc-texty';</span><br><span class="line">import 'rc-texty/assets/index.css';</span><br></pre></td></tr></table></figure><h3 id="添加组件级-CSS"><a href="#添加组件级-CSS" class="headerlink" title="添加组件级 CSS"></a>添加组件级 CSS</h3><p>Next.js 通过 [name].module.css 文件命名约定来支持 CSS 模块 。</p><ul><li>CSS 模块会自动创建唯一的类名,在不同文件使用同一类名,样式不会冲突</li><li>nextjs中,个人推荐使用此方法写样式表</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Head <span class="keyword">from</span> <span class="string">'next/head'</span></span><br><span class="line"><span class="keyword">import</span> styles <span class="keyword">from</span> <span class="string">'../styles/Home.module.css'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="function"><span class="keyword">function</span> <span class="title">About</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div className={styles.container}></span><br><span class="line"> <main className={styles.main}></span><br><span class="line"> about</span><br><span class="line"> </main></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><h3 id="原生对sass支持很好"><a href="#原生对sass支持很好" class="headerlink" title="原生对sass支持很好"></a>原生对sass支持很好</h3><p>Next.js 内置 Sass,要确保安装 ‘sass’</p><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 sass</span><br></pre></td></tr></table></figure><h3 id="CSS-in-JS"><a href="#CSS-in-JS" class="headerlink" title="CSS-in-JS"></a>CSS-in-JS</h3><ul><li>支持内联样式</li><li>支持 styled-jsx<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"> <main className={styles.main}></span><br><span class="line"> <div></span><br><span class="line"> <p><span class="number">1</span></p></span><br><span class="line"> <p><span class="number">2</span></p></span><br><span class="line"> <style jsx></span><br><span class="line"> {<span class="string">`</span></span><br><span class="line"><span class="string"> p {</span></span><br><span class="line"><span class="string"> width: 100px;</span></span><br><span class="line"><span class="string"> }</span></span><br><span class="line"><span class="string"> p:nth-child(1) {</span></span><br><span class="line"><span class="string"> color: blue;</span></span><br><span class="line"><span class="string"> background: red;</span></span><br><span class="line"><span class="string"> }</span></span><br><span class="line"><span class="string"> p:nth-child(2) {</span></span><br><span class="line"><span class="string"> color: green;</span></span><br><span class="line"><span class="string"> background: pink;</span></span><br><span class="line"><span class="string"> }</span></span><br><span class="line"><span class="string"> `</span>}</span><br><span class="line"> </style></span><br><span class="line"> </div></span><br><span class="line"></main></span><br></pre></td></tr></table></figure></li></ul><h2 id="七-middleware-中间件"><a href="#七-middleware-中间件" class="headerlink" title="七. middleware 中间件"></a>七. middleware 中间件</h2><h2 id="八-Dynamic-Import-动态导入"><a href="#八-Dynamic-Import-动态导入" class="headerlink" title="八. Dynamic Import 动态导入"></a>八. Dynamic Import 动态导入</h2><p>nextjs 也支持 react 的 ‘lazy’相似的组件导入方式</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> dynamic <span class="keyword">from</span> <span class="string">'next/dynamic'</span></span><br><span class="line"><span class="keyword">const</span> DynamicComponent = dynamic(<span class="function">() =></span> <span class="keyword">import</span>(<span class="string">'../components/userInfo'</span>))</span><br><span class="line"></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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> DynamicComponent = dynamic(<span class="function">() =></span> <span class="keyword">import</span>(<span class="string">'../components/userInfo'</span>), { <span class="attr">loading</span>: <span class="function">() =></span> <span class="xml"><span class="tag"><<span class="name">p</span>></span>加载中...<span class="tag"></<span class="name">p</span>></span></span>, ssr: <span class="literal">false</span> })</span><br></pre></td></tr></table></figure><p>支持Suspense</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> DynamicLazyComponent = dynamic(</span><br><span class="line"> () => <span class="keyword">import</span>(<span class="string">'../components/userInfo'</span>),</span><br><span class="line"> { <span class="attr">suspense</span>: <span class="literal">true</span> }</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><Suspense fallback={<span class="string">`<p>加载中...</p>`</span>}></span><br><span class="line"> <DynamicLazyComponent /></span><br><span class="line"></Suspense></span><br></pre></td></tr></table></figure><h2 id="九-图片优化"><a href="#九-图片优化" class="headerlink" title="九. 图片优化"></a>九. 图片优化</h2><ul><li>模糊效果占位图,支持懒加载</li><li>默认加上 srcset 属性来适配不同 devicePixelRatio 的屏幕</li><li>默认会返回压缩后的图片</li><li>支持给图片设置优先级</li></ul><h2 id="十-如何获取数据"><a href="#十-如何获取数据" class="headerlink" title="十. 如何获取数据"></a>十. 如何获取数据</h2><p>nextjs中有两种形式的预渲染</p><h3 id="1-服务端渲染"><a href="#1-服务端渲染" class="headerlink" title="1. 服务端渲染"></a>1. 服务端渲染</h3><p>访问xxx路由之前,向服务服务器要数据,吧要回来的数据和html加工直接返回前台展示</p><h3 id="2-静态化"><a href="#2-静态化" class="headerlink" title="2. 静态化"></a>2. 静态化</h3><p>访问xxx路由之前,向服务器请求数据,将请求来的数据和html加工成真正的XXX.html文件<br>作用:下次访问同一个路由地址的时候,直接返回静态页面,减小服务器压力,以达到性能优化目的</p><table><thead><tr><th align="center">方法</th><th align="center">静态化</th><th align="center">只能在pages文件夹下</th><th align="center">作用</th></tr></thead><tbody><tr><td align="center">getStaticProps</td><td align="center">静态生成</td><td align="center">是</td><td align="center">在构建时获取数据</td></tr><tr><td align="center">getServerSideProps</td><td align="center">服务器端渲染</td><td align="center">是</td><td align="center">每次进入页面重新获取数据</td></tr></tbody></table><h2 id="十一-MDX"><a href="#十一-MDX" class="headerlink" title="十一. MDX"></a>十一. MDX</h2><p>MDX 是 Markdown 的超集,允许您直接在 markdown 文件中写入 JSX。</p><ol><li>安装依赖包</li></ol><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">npm install @next/mdx @mdx-js/loader</span><br></pre></td></tr></table></figure><ol start="2"><li>next.config.js 完善扩展<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="comment">// next.config.js</span></span><br><span class="line"><span class="keyword">const</span> withMDX = <span class="built_in">require</span>(<span class="string">'@next/mdx'</span>)({</span><br><span class="line"> extension: <span class="regexp">/\.mdx?$/</span>,</span><br><span class="line"> options: {</span><br><span class="line"> remarkPlugins: [],</span><br><span class="line"> rehypePlugins: [],</span><br><span class="line"> <span class="comment">// If you use `MDXProvider`, uncomment the following line.</span></span><br><span class="line"> <span class="comment">// providerImportSource: "@mdx-js/react",</span></span><br><span class="line"> },</span><br><span class="line">})</span><br><span class="line"><span class="built_in">module</span>.exports = withMDX({</span><br><span class="line"> <span class="comment">// Append the default value with md extensions</span></span><br><span class="line"> pageExtensions: [<span class="string">'ts'</span>, <span class="string">'tsx'</span>, <span class="string">'js'</span>, <span class="string">'jsx'</span>, <span class="string">'md'</span>, <span class="string">'mdx'</span>],</span><br><span class="line">})</span><br></pre></td></tr></table></figure>现在 可以直接在 pages 目录创建后缀是 ’.mdx‘ 的文件,当然它也和’index.js’一样也是一个路由</li></ol><h2 id="十二-如何部署"><a href="#十二-如何部署" class="headerlink" title="十二. 如何部署"></a>十二. 如何部署</h2><h3 id="目前尝试部署方案"><a href="#目前尝试部署方案" class="headerlink" title="目前尝试部署方案"></a>目前尝试部署方案</h3><ul><li><p>源码放生产环境</p></li><li><p>yarn install</p></li><li><p>yarn build</p></li><li><p>yarn start,此时项目运行在服务端8883端口(可按实际情况更改端口)</p></li><li><p>不挂断运行服务 nohup yarn start >> ./log/nohup<code>date +%Y-%m-%d-%H</code>.out 2>&1 &</p></li><li><p>有域名,用nginx代理到8883端口 </p><h3 id="运行"><a href="#运行" class="headerlink" title="运行"></a>运行</h3></li><li><p>nohup 方式<br>nohup yarn start >> ./log/nohup<code>date +%Y-%m-%d-%H</code>.out 2>&1 &</p></li><li><p>pm2 方式<br>pm2 start yarn –name testxj03 – start</p></li></ul>]]></content>
<summary type="html"><p>Next.js 一些东西</p>
<h1 id="Next-js-一些东西"><a href="#Next-js-一些东西" class="headerlink" title="Next.js 一些东西"></a>Next.js 一些东西</h1><h2 id="一-疑问:</summary>
<category term="前端" scheme="https://blog.magicyou.cn/categories/%E5%89%8D%E7%AB%AF/"/>
<category term="React" scheme="https://blog.magicyou.cn/tags/React/"/>
<category term="Next.js" scheme="https://blog.magicyou.cn/tags/Next-js/"/>
</entry>
<entry>
<title>vue-</title>
<link href="https://blog.magicyou.cn/2022/03/11/vue-%E7%89%B9%E6%80%A7/"/>
<id>https://blog.magicyou.cn/2022/03/11/vue-%E7%89%B9%E6%80%A7/</id>
<published>2022-03-11T14:13:02.000Z</published>
<updated>2022-03-11T14:13:04.000Z</updated>
<content type="html"><![CDATA[<p>复习vue特性: 自定义v-model、$nextTick、slot、动态异步组件、keep-alive、mixin</p><span id="more"></span><p>主要参考来源:</p><ul><li><a href="https://cn.vuejs.org/v2/api">https://cn.vuejs.org/v2/api</a></li></ul><h2 id="v-model"><a href="#v-model" class="headerlink" title="v-model"></a>v-model</h2><blockquote><p>你可以用 v-model 指令在表单 <input>、<textarea> 及 <select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。 — vue官方文档</p></blockquote><p>基本用法:</p><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">template</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">id</span>=<span class="string">"name"</span> <span class="attr">v-model</span>=<span class="string">"name"</span>></span></span><br><span class="line"><span class="tag"></<span class="name">template</span>></span></span><br><span class="line"><span class="tag"><<span class="name">script</span>></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> {</span></span><br><span class="line"> data () {</span><br><span class="line"><span class="javascript"> <span class="keyword">return</span> {</span></span><br><span class="line"><span class="javascript"> name: <span class="string">'zjl'</span>,</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="tag"></<span class="name">script</span>></span></span><br></pre></td></tr></table></figure><h3 id="v-model-做了什么?"><a href="#v-model-做了什么?" class="headerlink" title="v-model 做了什么?"></a>v-model 做了什么?</h3><p>v-model 是个语法糖,一个指令实现数据同步、绑定数据,类似如下代码:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">v-bind:value</span>=<span class="string">"tangVal"</span> <span class="attr">v-on:input</span>=<span class="string">"tangVal=$event.target.value"</span>></span></span><br></pre></td></tr></table></figure><h3 id="修饰符"><a href="#修饰符" class="headerlink" title="修饰符"></a>修饰符</h3><ul><li>.lazy v-model 默认 input 事件触发值与数据同步,添加 lazy 修饰符之后,会转为 change 事件之后进行同步;</li><li>.number 自动将输入的内容转为数字类型(type=”number”返回的值也是字符串);</li><li>.trim 自动过滤用户输入的首尾空白字符</li></ul><h3 id="自定义组件使用-v-model"><a href="#自定义组件使用-v-model" class="headerlink" title="自定义组件使用 v-model"></a>自定义组件使用 v-model</h3><blockquote><p>一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value attribute 用于不同的目的。model 选项可以用来避免这样的冲突 — vue官方文档</p></blockquote><p>手写一个input 和 select</p><p>自定义 input 组件</p><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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">template</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">:value</span>=<span class="string">"value"</span> @<span class="attr">input</span>=<span class="string">"$emit('input', $event.target.value)"</span>></span></span><br><span class="line"><span class="tag"></<span class="name">template</span>></span></span><br><span class="line"><span class="tag"><<span class="name">script</span>></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> {</span></span><br><span class="line"> props: {</span><br><span class="line"><span class="javascript"> value: <span class="built_in">String</span></span></span><br><span class="line"> },</span><br><span class="line">}</span><br><span class="line"><span class="tag"></<span class="name">script</span>></span></span><br></pre></td></tr></table></figure><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><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="tag"><<span class="name">template</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">select</span> <span class="attr">:value</span>=<span class="string">"value"</span> @<span class="attr">input</span>=<span class="string">"$emit('change', $event.target.value)"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">option</span> <span class="attr">value</span>=<span class="string">"学生"</span>></span>学生<span class="tag"></<span class="name">option</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">option</span> <span class="attr">value</span>=<span class="string">"老师"</span>></span>老师<span class="tag"></<span class="name">option</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">option</span> <span class="attr">value</span>=<span class="string">"工人"</span>></span>工人<span class="tag"></<span class="name">option</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">option</span> <span class="attr">value</span>=<span class="string">"其他"</span>></span>其他<span class="tag"></<span class="name">option</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">select</span>></span></span><br><span class="line"><span class="tag"></<span class="name">template</span>></span></span><br><span class="line"><span class="tag"><<span class="name">script</span>></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> {</span></span><br><span class="line"> model: {</span><br><span class="line"><span class="javascript"> prop: <span class="string">'value'</span>,</span></span><br><span class="line"><span class="javascript"> event: <span class="string">'change'</span></span></span><br><span class="line"> },</span><br><span class="line"> props: {</span><br><span class="line"><span class="javascript"> value: <span class="built_in">String</span></span></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="tag"></<span class="name">script</span>></span></span><br></pre></td></tr></table></figure><h2 id="nextTick"><a href="#nextTick" class="headerlink" title="$nextTick"></a>$nextTick</h2><blockquote><p>将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上 — vue官方文档<br>$nextTick 是vue 实例的方法</p></blockquote><ul><li>参数: {Function} [callback]</li></ul><p>通俗的讲就是,当vue实例的数据更新之后,dom会发生变化,dom更新数据之后采购执行 $nextTick 的回调。</p><p>不使用 $nextTick,data更改之后直接使用dom元素获取 dom 的 innerText</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><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"><template></span><br><span class="line"> <div class="main"></span><br><span class="line"> <p id="test_data">测试dom:{{ name }}</p></span><br><span class="line"> <button @click="onClickSetData">点击更改为->456</button></span><br><span class="line"> </div></span><br><span class="line"></template></span><br><span class="line"><script></span><br><span class="line">export default {</span><br><span class="line"> name: 'TestNextTick',</span><br><span class="line"> data () {</span><br><span class="line"> return {</span><br><span class="line"> name: '123',</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"> methods: {</span><br><span class="line"> onClickSetData() {</span><br><span class="line"> this.name = '456';</span><br><span class="line"> console.log(document.getElementById('test_data').innerText);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></script></span><br></pre></td></tr></table></figure><p>控制台打印结果:</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">测试dom:123</span><br></pre></td></tr></table></figure><p>结果表明,修改了vue 实例的data后,直接获取 dom 的 innerText,获取结果依旧是更改data之前的内容;<br>使用 $nextTick,更改 methods</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="function"><span class="title">onClickSetData</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="built_in">this</span>.name = <span class="string">'456'</span>;</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="built_in">document</span>.getElementById(<span class="string">'test_data'</span>).innerText);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>控制台打印结果:</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">测试dom:456</span><br></pre></td></tr></table></figure><h3 id="nextTick-的使用场景"><a href="#nextTick-的使用场景" class="headerlink" title="$nextTick 的使用场景"></a>$nextTick 的使用场景</h3><ul><li>生命周期 created 内需要操作dom时,需要使用 $nextTick;</li><li>生命周期 mounted 内需要操作 dom 时,推荐使用 $nextTick;官方文档描述,mounted 不会保证所有的子组件也都被挂载完成,所以在此生命周期需要操作dom时候,推荐使用 $nextTick;</li><li>数据更新之后需要操作 dom,需要使用 $nextTick,保证 此时操作的 dom 是最终渲染完毕的;</li></ul><h3 id="注意"><a href="#注意" class="headerlink" title="注意"></a>注意</h3><p>$nextTick 在官方文档最后,有参考异步更新队列。<br>当 vue 实例的 data 被修改,组件并不会立即重新渲染 DOM。这个过程是异步的,vue会开启一个队列,这个事件会被推入队列(中间也做了去除重复数据渲染这样不必要的操作)。</p><blockquote><p>当你设置 vm.someData = ‘new value’,该组件不会立即重新渲染。当刷新队列时,组件会在下一个事件循环“tick”中更新。多数情况我们不需要关心这个过程,但是如果你想基于更新后的 DOM 状态来做点什么,这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员使用“数据驱动”的方式思考,避免直接接触 DOM,但是有时我们必须要这么做。为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用 Vue.nextTick(callback)。这样回调函数将在 DOM 更新完成后被调用 — vue官方文档</p></blockquote><h2 id="slot"><a href="#slot" class="headerlink" title="slot"></a>slot</h2><p>插槽</p><h2 id="动态异步组件"><a href="#动态异步组件" class="headerlink" title="动态异步组件"></a>动态异步组件</h2><h2 id="keep-alive"><a href="#keep-alive" class="headerlink" title="keep-alive"></a>keep-alive</h2><h2 id="mixin"><a href="#mixin" class="headerlink" title="mixin"></a>mixin</h2><p>当有多个组件有部分公用的 vue 实例方法时,可以使用mixin 将通用的部分提取出来。</p>]]></content>
<summary type="html"><p>复习vue特性: 自定义v-model、$nextTick、slot、动态异步组件、keep-alive、mixin</p></summary>
<category term="Vue" scheme="https://blog.magicyou.cn/categories/Vue/"/>
<category term="Vue" scheme="https://blog.magicyou.cn/tags/Vue/"/>
</entry>
<entry>
<title>计算机基础-进制转换</title>
<link href="https://blog.magicyou.cn/2021/12/10/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80-%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/"/>
<id>https://blog.magicyou.cn/2021/12/10/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80-%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/</id>
<published>2021-12-10T05:34:12.000Z</published>
<updated>2021-12-10T05:34:23.000Z</updated>
<content type="html"><![CDATA[<!-- 什么是标识符:包、类、变量、方法...等等,只要是起名字的地方吗,那个名字就是标识符 --><p>计算机只识别二进制,何为二进制?我们为什么生活中只用十进制?还有十六进制?如何计算,相互转换?</p><span id="more"></span><h2 id="什么是二进制"><a href="#什么是二进制" class="headerlink" title="什么是二进制"></a>什么是二进制</h2><p>二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”。</p><p>附言:同样的,8进制就是“逢8进1”;十六进制就是“逢16进1”</p><h2 id="如何计算呢"><a href="#如何计算呢" class="headerlink" title="如何计算呢"></a>如何计算呢</h2><h3 id="十进制转换为二进制"><a href="#十进制转换为二进制" class="headerlink" title="十进制转换为二进制"></a>十进制转换为二进制</h3><p><img src="/static/img/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80-%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2_01.jpg" alt="计算机基础-进制转换_01"></p><p>由上图计算方式,得出的余数倒过来,就是该数字对应的二进制:</p><table><thead><tr><th>十进制</th><th>二进制</th></tr></thead><tbody><tr><td>14</td><td>1110</td></tr><tr><td>18</td><td>10010</td></tr><tr><td>8</td><td>1000</td></tr><tr><td>12</td><td>1100</td></tr></tbody></table><h3 id="十进制转换为八进制"><a href="#十进制转换为八进制" class="headerlink" title="十进制转换为八进制"></a>十进制转换为八进制</h3><p><img src="/static/img/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80-%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2_02.jpg" alt="计算机基础-进制转换_01"></p><p>由上图计算方式,得出的余数倒过来,就是该数字对应的八进制:</p><table><thead><tr><th>十进制</th><th>八进制</th></tr></thead><tbody><tr><td>16</td><td>20</td></tr><tr><td>127</td><td>177</td></tr><tr><td>188</td><td>274</td></tr><tr><td>32</td><td>40</td></tr></tbody></table><h3 id="二进制和八进制如何转换回十进制呢?"><a href="#二进制和八进制如何转换回十进制呢?" class="headerlink" title="二进制和八进制如何转换回十进制呢?"></a>二进制和八进制如何转换回十进制呢?</h3><h4 id="二进制转换成十进制"><a href="#二进制转换成十进制" class="headerlink" title="二进制转换成十进制"></a>二进制转换成十进制</h4><p>按照二进制,索引从后往前,每一位数字与乘以2的当前索引次方(当前数字 * 2^索引),然后相加得出的和就是该二进制数字的十进制<br>1110(二进制)-> ?(十进制)<br>(1 * 2 ** 3) + (1 * 2 ** 2) + (1 * 2 ** 1) + (0 * 2 ** 0) = 8 + 4 + 2 + 0 = 14</p><p>10010(二进制)-> ?(十进制)<br>(1 * 2 ** 4) + (0 * 2 ** 3) + (0 * 2 ** 2) + (1 * 2 ** 1) + (0 * 2 ** 0)= 16 + 0 + 0 + 2 + 0 = 18</p><p>1000(二进制)-> ?(十进制)<br>(1 * 2 ** 3) + (0 * 2 ** 2) + (0 * 2 ** 1) + (0 * 2 ** 0) = 8 + 0 + 0 + 0 = 8</p><p>1100(二进制)-> ?(十进制)<br>(1 * 2 ** 3) + (1 * 2 ** 2) + (0 * 2 ** 1) + (0 * 2 ** 0) = 8 + 4 + 0 + 0 = 12</p><h4 id="八进制转换成十进制"><a href="#八进制转换成十进制" class="headerlink" title="八进制转换成十进制"></a>八进制转换成十进制</h4><p>参照二进制算法,八进制,索引从后往前,每一位数字与乘以8的当前索引次方(当前数字 * 8^索引),然后相加得出的和就是该八进制数字的十进制<br>20(八进制)-> ?(十进制)<br> (2 * 8 ** 1) + (0 * 8 ** 0) = 16 + 0 = 16</p><p>177(八进制)-> ?(十进制)<br>(1 * 8 ** 2) + (7 * 8 ** 1) + (7 * 2 ** 0)= 64 + 56 + 7 = 127</p><p>274(八进制)-> ?(十进制)<br>(2 * 8 ** 2) + (7 * 8 ** 1) + (4 * 2 ** 0)= 128 + 56 + 4 = 188</p><p>40(八进制)-> ?(十进制)<br> (4 * 8 ** 1) + (0 * 8 ** 0) = 32 + 0 = 32</p><h2 id="负数的二进制?"><a href="#负数的二进制?" class="headerlink" title="负数的二进制?"></a>负数的二进制?</h2><p>以上通过两组数字知道八进制和二进制,二进制和十进制 如何相互转换,十六进制十四进制应该知道如何计算了。<br>但是发现上面计算的都是正数,那负数的二进制该如何计算?</p>]]></content>
<summary type="html"><!-- 什么是标识符:包、类、变量、方法...等等,只要是起名字的地方吗,那个名字就是标识符 -->
<p>计算机只识别二进制,何为二进制?我们为什么生活中只用十进制?还有十六进制?如何计算,相互转换?</p></summary>
<category term="计算机基础" scheme="https://blog.magicyou.cn/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/"/>
<category term="计算机基础" scheme="https://blog.magicyou.cn/tags/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/"/>
</entry>
<entry>
<title>vue-通信方式</title>
<link href="https://blog.magicyou.cn/2021/11/15/vue-%E9%80%9A%E4%BF%A1%E6%96%B9%E5%BC%8F/"/>
<id>https://blog.magicyou.cn/2021/11/15/vue-%E9%80%9A%E4%BF%A1%E6%96%B9%E5%BC%8F/</id>
<published>2021-11-15T14:13:02.000Z</published>
<updated>2021-11-15T14:13:04.000Z</updated>
<content type="html"><![CDATA[<p>复习vue通信方式</p><span id="more"></span><p>主要参考来源:</p><ul><li><a href="https://cn.vuejs.org/v2/api">https://cn.vuejs.org/v2/api</a></li></ul>]]></content>
<summary type="html"><p>复习vue通信方式</p></summary>
<category term="Vue" scheme="https://blog.magicyou.cn/categories/Vue/"/>
<category term="Vue" scheme="https://blog.magicyou.cn/tags/Vue/"/>
</entry>
<entry>
<title>vue-重新研究生命周期</title>
<link href="https://blog.magicyou.cn/2021/10/11/vue-%E9%87%8D%E6%96%B0%E7%A0%94%E7%A9%B6%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/"/>
<id>https://blog.magicyou.cn/2021/10/11/vue-%E9%87%8D%E6%96%B0%E7%A0%94%E7%A9%B6%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/</id>
<published>2021-10-11T14:13:02.000Z</published>
<updated>2021-10-11T14:13:04.000Z</updated>
<content type="html"><![CDATA[<p> Vue 的生命周期:beforeCreate,created,beforeMount,beforeUpdate, mounted,beforeUpdate,updated,updated, beforeDestroy,destroy</p><span id="more"></span><p>主要参考来源:</p><ul><li><a href="https://vuex.vuejs.org/zh/">https://vuex.vuejs.org/zh/</a></li></ul><h2 id="Vue-的生命周期是个啥?"><a href="#Vue-的生命周期是个啥?" class="headerlink" title="Vue 的生命周期是个啥?"></a>Vue 的生命周期是个啥?</h2><p>每个 Vue 组件都是一个个的 Vue 实例,当一个 Vue 实例被创建时,都会有一系列的初始化过程,每个过程都会执行一些特定的方法。<br>学过 JAVA 或者 PHP 的都应该知道,对象在被实例化和被销毁的时候也有一个过程,期间会调用构造函数,析构函数;这个和 Vue 生命周期类似。</p><h2 id="官网的示意图"><a href="#官网的示意图" class="headerlink" title="官网的示意图"></a>官网的示意图</h2><p><img src="/static/img/vue-%E9%87%8D%E6%96%B0%E7%A0%94%E7%A9%B6%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F_01.png" alt="vue-重新研究生命周期_01"></p><h2 id="复习每个生命周期钩子"><a href="#复习每个生命周期钩子" class="headerlink" title="复习每个生命周期钩子"></a>复习每个生命周期钩子</h2><ul><li><p><strong>beforeCreate(创建前)</strong><br>在实例初始化之后,进行数据侦听和事件/侦听器的配置之前同步调用。<br>此时组件上的对象还未被创建,el 和 data 都没有初始化,也不能调用 methods,data,computed,等方法和数据</p></li><li><p><strong>create(创建后)</strong><br>在实例创建完成后被立即同步调用。在这一步中,实例已完成对选项的处理,意味着以下内容已被配置完毕:数据侦听、计算属性、方法、事件/侦听器的回调函数。然而,挂载阶段还没开始,且 $el property 目前尚不可用。<br>总之就是,除了页面还没有开始渲染,其他的工作已经准备就绪,包括数据观测,树形和方法调用,watch/event事件回调,data初始化。<strong>可以进行 ajax 请求数据了,但是最好不要</strong>,毕竟此时的页面还是空白</p></li><li><p><strong>beforeMount</strong><br>在挂载开始之前被调用:相关的 render 函数首次被调用。<br>实例已完成以下的配置: 编译模板,把data里面的数据和模板生成html,完成了el和data 初始化,但是此时还没有挂在html到页面上,还是没有 dom。</p></li><li><p><strong>mounted</strong><br>挂载完成了,html已经渲染到了document。可以进行ajax请求了。<br>官方温馨提示: <strong>mounted 不会保证所有的子组件也都被挂载完成。如果你希望等到整个视图都渲染完毕再执行某些操作,可以在 mounted 内部使用 vm.$nextTick</strong></p></li><li><p><strong>beforeUpdate</strong><br>数据更新之后,dom 被更新之前调用。注意官方的一句话:<strong>这里适合在现有 DOM 将要被更新之前访问它,比如移除手动添加的事件监听器</strong></p></li><li><p><strong>updated</strong><br>在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用。这个时候dom已经更新完毕,可以进行依赖于dom的操作,但是,<strong>你应该避免在此期间更改状态。如果要相应状态改变,因为这可能会导致更新无限循环</strong></p></li><li><p><strong>beforeDestroy</strong><br>实例销毁之前调用。在这一步,实例仍然完全可用。</p><ol><li>这一步还可以用this来获取实例</li><li>一般在这一步做一些重置的操作,比如清除掉组件中的定时器 和 监听的dom事件</li></ol></li><li><p><strong>destroyed</strong><br>实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁</p></li></ul><p>以上复习了生命周期钩子函数在各个阶段都干了什么。然后用实例来验证加强记忆一下,顺便探讨父子组件的生命周期表现是什么样的。</p><h2 id="单组件的生命周期"><a href="#单组件的生命周期" class="headerlink" title="单组件的生命周期"></a>单组件的生命周期</h2><h3 id="简单两个组件"><a href="#简单两个组件" class="headerlink" title="简单两个组件"></a>简单两个组件</h3><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><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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">template</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"main"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">span</span> <span class="attr">id</span>=<span class="string">"tip_text"</span>></span>我是一个测试生命周期的组件<span class="tag"></<span class="name">span</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"></<span class="name">template</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"><<span class="name">script</span>></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> {</span></span><br><span class="line"><span class="javascript"> name: <span class="string">'LifeCycle'</span>,</span></span><br><span class="line"> data () {</span><br><span class="line"><span class="javascript"> <span class="keyword">return</span> {</span></span><br><span class="line"><span class="javascript"> name: <span class="string">'我是谁'</span></span></span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"><span class="javascript"> <span class="function"><span class="title">beforeCreate</span>(<span class="params"></span>)</span> {</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent beforeCreate'</span>);</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent beforeCreate -this.name:'</span>, <span class="built_in">this</span>.name);</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent beforeCreate -test dom:'</span>, <span class="built_in">document</span>.getElementById(<span class="string">'tip_text'</span>));</span></span><br><span class="line"> },</span><br><span class="line"><span class="javascript"> <span class="function"><span class="title">created</span>(<span class="params"></span>)</span> {</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent created'</span>);</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent created -this.name:'</span>, <span class="built_in">this</span>.name);</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent created -test dom:'</span>, <span class="built_in">document</span>.getElementById(<span class="string">'tip_text'</span>));</span></span><br><span class="line"> },</span><br><span class="line"><span class="javascript"> <span class="function"><span class="title">beforeMount</span>(<span class="params"></span>)</span> {</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent beforeMount'</span>);</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent beforeMount -this.name:'</span>, <span class="built_in">this</span>.name);</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent beforeMount -test dom:'</span>, <span class="built_in">document</span>.getElementById(<span class="string">'tip_text'</span>));</span></span><br><span class="line"> },</span><br><span class="line"><span class="javascript"> <span class="function"><span class="title">mounted</span>(<span class="params"></span>)</span> {</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent mounted'</span>);</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent mounted -this.name:'</span>, <span class="built_in">this</span>.name);</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent mounted -test dom:'</span>, <span class="built_in">document</span>.getElementById(<span class="string">'tip_text'</span>));</span></span><br><span class="line"> },</span><br><span class="line"><span class="javascript"> <span class="function"><span class="title">beforeUpdate</span>(<span class="params"></span>)</span> {</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent beforeUpdate'</span>);</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent beforeUpdate -this.name:'</span>, <span class="built_in">this</span>.name);</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent beforeUpdate -test dom:'</span>, <span class="built_in">document</span>.getElementById(<span class="string">'tip_text'</span>));</span></span><br><span class="line"> },</span><br><span class="line"><span class="javascript"> <span class="function"><span class="title">updated</span>(<span class="params"></span>)</span> {</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent updated'</span>);</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent updated -this.name:'</span>, <span class="built_in">this</span>.name);</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent updated -test dom:'</span>, <span class="built_in">document</span>.getElementById(<span class="string">'tip_text'</span>));</span></span><br><span class="line"> },</span><br><span class="line"><span class="javascript"> <span class="function"><span class="title">beforeDestroy</span>(<span class="params"></span>)</span> {</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent beforeDestroy'</span>);</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent beforeDestroy -this.name:'</span>, <span class="built_in">this</span>.name);</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent beforeDestroy -test dom:'</span>, <span class="built_in">document</span>.getElementById(<span class="string">'tip_text'</span>));</span></span><br><span class="line"> },</span><br><span class="line"><span class="javascript"> <span class="function"><span class="title">destroyed</span>(<span class="params"></span>)</span> {</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent destroyed'</span>);</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent destroyed -this.name:'</span>, <span class="built_in">this</span>.name);</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">'**** parent destroyed -test dom:'</span>, <span class="built_in">document</span>.getElementById(<span class="string">'tip_text'</span>));</span></span><br><span class="line"> },</span><br><span class="line"> methods: {}</span><br><span class="line">}</span><br><span class="line"><span class="tag"></<span class="name">script</span>></span></span><br></pre></td></tr></table></figure><h3 id="模拟页面进入,控制台输出如下:"><a href="#模拟页面进入,控制台输出如下:" class="headerlink" title="模拟页面进入,控制台输出如下:"></a>模拟页面进入,控制台输出如下:</h3><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><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">**** parent beforeCreate</span><br><span class="line">**** parent beforeCreate -this.name: undefined</span><br><span class="line">**** parent beforeCreate -test dom: null</span><br><span class="line">**** parent created</span><br><span class="line">**** parent created -this.name: 我是谁</span><br><span class="line">**** parent created -test dom: null</span><br><span class="line">**** parent beforeMount</span><br><span class="line">**** parent beforeMount -this.name: 我是谁</span><br><span class="line">**** parent beforeMount -test dom: null</span><br><span class="line">**** parent mounted</span><br><span class="line">**** parent mounted -this.name: 我是谁</span><br><span class="line">**** parent mounted -test dom: <span id="tip_text">我是一个测试生命周期的组件</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>从上面可以看到,组件在创建的时候</p><ul><li>依次执行:beforeCreate > created > beforeMount > mounted;</li><li>beforeCreate 期间,不能访问data,而 created之后就可以访问 data 了;</li><li>mounted 时期,不仅能访问data,dom元素也可以正确获取;</li></ul><h3 id="切换路由,模拟页面离开,控制台输出如下:"><a href="#切换路由,模拟页面离开,控制台输出如下:" class="headerlink" title="切换路由,模拟页面离开,控制台输出如下:"></a>切换路由,模拟页面离开,控制台输出如下:</h3><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><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">**** parent beforeDestroy</span><br><span class="line">**** parent beforeDestroy -this.name: 我是谁</span><br><span class="line">**** parent beforeDestroy -test dom: null</span><br><span class="line">**** parent destroyed</span><br><span class="line">**** parent destroyed -this.name: 我是谁</span><br><span class="line">**** parent destroyed -test dom: null</span><br></pre></td></tr></table></figure><p>组件离开被销毁时候,验证出以下观点</p><ul><li>依次执行:beforeDestroy > destroyed;</li><li>beforeDestroy 期间,还能访问 data,但是 dom 此时已经被销毁了;</li><li><strong>destroyed 时期,竟然还能访问data?有点疑惑</strong>;</li></ul><p>发现updated和beforeUpdate并没有参与组件的创建和销毁,尝试加入动作;</p><p>调整组件</p><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><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">template</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"main"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">span</span>></span>我是一个测试生命周期的组件<span class="tag"></<span class="name">span</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">span</span> <span class="attr">id</span>=<span class="string">"tip_text"</span>></span>点击测试 {{ num }} <span class="tag"></<span class="name">span</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"onClickCount"</span>></span>点击<span class="tag"></<span class="name">button</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">div</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"></<span class="name">template</span>></span></span><br><span class="line"><span class="tag"><<span class="name">script</span>></span></span><br><span class="line">{</span><br><span class="line"> data () {</span><br><span class="line"><span class="javascript"> <span class="keyword">return</span> {</span></span><br><span class="line"><span class="javascript"> name: <span class="string">'我是谁'</span>,</span></span><br><span class="line"> num: 1,</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"> methods: {</span><br><span class="line"><span class="javascript"> <span class="function"><span class="title">onClickCount</span>(<span class="params"></span>)</span> {</span></span><br><span class="line"><span class="javascript"> <span class="built_in">this</span>.num++;</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"></span><br></pre></td></tr></table></figure><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><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">**** parent beforeUpdate</span><br><span class="line">**** parent beforeUpdate -this.name: 我是谁</span><br><span class="line">**** parent beforeUpdate -test dom: <span id="tip_text">点击测试 3 </span></span><br><span class="line">**** parent updated</span><br><span class="line">**** parent updated -this.name: 我是谁</span><br><span class="line">**** parent updated -test dom: <span id="tip_text">点击测试 3 </span></span><br></pre></td></tr></table></figure><h2 id="组件嵌套的生命周期会如何表现呢?"><a href="#组件嵌套的生命周期会如何表现呢?" class="headerlink" title="组件嵌套的生命周期会如何表现呢?"></a>组件嵌套的生命周期会如何表现呢?</h2><p>先来两个组件</p><p>父组件</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><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"><template></span><br><span class="line"> <div class="main"></span><br><span class="line"> <span>我是一个测试生命周期的组件</span></span><br><span class="line"> <div></span><br><span class="line"> <span>输入的内容:{{ title || '-' }}</span></span><br><span class="line"> </div></span><br><span class="line"> </span><br><span class="line"> <SlInput @slInput="onSlInput" :title="title"/></span><br><span class="line"> </div></span><br><span class="line"></template></span><br><span class="line"></span><br><span class="line"><script></span><br><span class="line">import SlInput from './SlInput.vue'</span><br><span class="line">export default {</span><br><span class="line"> name: 'LifeCycle',</span><br><span class="line"> components: { SlInput },</span><br><span class="line"> data () {</span><br><span class="line"> return {</span><br><span class="line"> name: '我是谁',</span><br><span class="line"> title: '',</span><br><span class="line"> num: 1,</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"> beforeCreate() {</span><br><span class="line"> console.log('**** parent beforeCreate');</span><br><span class="line"> },</span><br><span class="line"> created() {</span><br><span class="line"> console.log('**** parent created');</span><br><span class="line"> },</span><br><span class="line"> beforeMount() {</span><br><span class="line"> console.log('**** parent beforeMount');</span><br><span class="line"> },</span><br><span class="line"> mounted() {</span><br><span class="line"> console.log('**** parent mounted');</span><br><span class="line"> },</span><br><span class="line"> beforeUpdate() {</span><br><span class="line"> console.log('**** parent beforeUpdate');</span><br><span class="line"> },</span><br><span class="line"> updated() {</span><br><span class="line"> console.log('**** parent updated');</span><br><span class="line"> },</span><br><span class="line"> beforeDestroy() {</span><br><span class="line"> console.log('**** parent beforeDestroy');</span><br><span class="line"> },</span><br><span class="line"> destroyed() {</span><br><span class="line"> console.log('**** parent destroyed');</span><br><span class="line"> },</span><br><span class="line"> methods: {</span><br><span class="line"> </span><br><span class="line"> onSlInput(value) {</span><br><span class="line"> this.title = value</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></script></span><br></pre></td></tr></table></figure><p>子组件</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><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></pre></td><td class="code"><pre><span class="line"><template></span><br><span class="line"> <input type="text" :value="title" @input="onInput"></span><br><span class="line"></template></span><br><span class="line"></span><br><span class="line"><script></span><br><span class="line">export default {</span><br><span class="line"> name: 'SlInput',</span><br><span class="line"> data() {</span><br><span class="line"> return {}</span><br><span class="line"> },</span><br><span class="line"> props: ['title'],</span><br><span class="line"> beforeCreate() {</span><br><span class="line"> console.log('**** children beforeCreate');</span><br><span class="line"> },</span><br><span class="line"> created() {</span><br><span class="line"> console.log('**** children created');</span><br><span class="line"> },</span><br><span class="line"> beforeMount() {</span><br><span class="line"> console.log('**** children beforeMount');</span><br><span class="line"> },</span><br><span class="line"> mounted() {</span><br><span class="line"> console.log('**** children mounted');</span><br><span class="line"> },</span><br><span class="line"> beforeUpdate() {</span><br><span class="line"> console.log('**** children beforeUpdate');</span><br><span class="line"> },</span><br><span class="line"> updated() {</span><br><span class="line"> console.log('**** children updated');</span><br><span class="line"> },</span><br><span class="line"> beforeDestroy() {</span><br><span class="line"> console.log('**** children beforeDestroy');</span><br><span class="line"> },</span><br><span class="line"> destroyed() {</span><br><span class="line"> console.log('**** children destroyed');</span><br><span class="line"> },</span><br><span class="line"> methods: {</span><br><span class="line"> onInput(event) {</span><br><span class="line"> this.$emit('slInput', event.target.value)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></script></span><br></pre></td></tr></table></figure><h3 id="同样再次模拟页面进入,控制台输出如下:"><a href="#同样再次模拟页面进入,控制台输出如下:" class="headerlink" title="同样再次模拟页面进入,控制台输出如下:"></a>同样再次模拟页面进入,控制台输出如下:</h3><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><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">**** parent beforeCreate</span><br><span class="line">**** parent created</span><br><span class="line">**** parent beforeMount</span><br><span class="line">**** children beforeCreate</span><br><span class="line">**** children created</span><br><span class="line">**** children beforeMount</span><br><span class="line">**** children mounted</span><br><span class="line">**** parent mounted</span><br></pre></td></tr></table></figure><p>可以发现,父子组件嵌套情况下,组件实例化时:</p><ul><li>父组件先进行实例化,在模板挂载之前,进行子组件实例化,父组件会等待子组件实例化完毕,再进行父组件自己的模板挂载<br>beforeCreate ><br>created ><br>beforeMount ><br>children-beforeCreate ><br>children-created ><br>children-beforeMount ><br>children-mounted ><br>mounted</li></ul><h3 id="模拟页面离开,控制台输出如下:"><a href="#模拟页面离开,控制台输出如下:" class="headerlink" title="模拟页面离开,控制台输出如下:"></a>模拟页面离开,控制台输出如下:</h3><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">**** parent beforeDestroy</span><br><span class="line">**** children beforeDestroy</span><br><span class="line">**** children destroyed</span><br><span class="line">**** parent destroyed</span><br></pre></td></tr></table></figure><p>父子组件嵌套,父组件在销毁时:</p><ul><li>父组件先准备进行销毁,进入 调用钩子 beforeDestroy,等待子组件销毁完毕,父组件继续执行销毁,调用钩子 destroyed,执行顺序如下:<br>parent beforeDestroy ><br>children-beforeDestroy ><br>children-destroyed ><br>destroyed</li></ul><h3 id="何时调用-update-呢?"><a href="#何时调用-update-呢?" class="headerlink" title="何时调用 update 呢?"></a>何时调用 update 呢?</h3><h4 id="尝试子组件和父组件通信,修改父组件的-data"><a href="#尝试子组件和父组件通信,修改父组件的-data" class="headerlink" title="尝试子组件和父组件通信,修改父组件的 data"></a>尝试子组件和父组件通信,修改父组件的 data</h4><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">**** parent beforeUpdate</span><br><span class="line">**** children beforeUpdate</span><br><span class="line">**** children updated</span><br><span class="line">**** parent updated</span><br></pre></td></tr></table></figure><h4 id="尝试父组件修改子组件data"><a href="#尝试父组件修改子组件data" class="headerlink" title="尝试父组件修改子组件data"></a>尝试父组件修改子组件data</h4><p>父组件组件添加以下内容:</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><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"> <div></span><br><span class="line"> <button @click="onClickSetChildrenCount">点击修改子组件data</button></span><br><span class="line"> </div></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"> methods: {</span><br><span class="line"> onClickSetChildrenCount() {</span><br><span class="line"> this.$refs.SlInput.childrenCount++</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></script> </span><br></pre></td></tr></table></figure><p>子组件:</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><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"> <div></span><br><span class="line"> 子组件data修改测试:{{ childrenCount }}</span><br><span class="line"></div></span><br><span class="line"></span><br><span class="line"><script> </span><br><span class="line">{</span><br><span class="line"> data() {</span><br><span class="line"> return {</span><br><span class="line"> childrenCount: 1</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></script> </span><br></pre></td></tr></table></figure><p>点击按钮触发,修改子组件的data,控制台输出如下</p><figure class="highlight plain"><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">**** children beforeUpdate</span><br><span class="line">**** children updated</span><br></pre></td></tr></table></figure><p>此时没有父组件的参与</p><h4 id="单修改父组件data,会触发子组件的-update-吗?"><a href="#单修改父组件data,会触发子组件的-update-吗?" class="headerlink" title="单修改父组件data,会触发子组件的 update 吗?"></a>单修改父组件data,会触发子组件的 update 吗?</h4><p>还是那个点击测试</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><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"><div></span><br><span class="line"> <span id="tip_text">点击测试 {{ num }} </span></span><br><span class="line"> <button @click="onClickCount">点击</button></span><br><span class="line"> </div></span><br><span class="line"><script> </span><br><span class="line">{</span><br><span class="line"> data() {</span><br><span class="line"> return {</span><br><span class="line"> childrenCount: 1</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> methods: {</span><br><span class="line"> onClickCount() {</span><br><span class="line"> this.num++;</span><br><span class="line"> },</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></script> </span><br></pre></td></tr></table></figure><p>点击触发事件,控制台输出</p><figure class="highlight plain"><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">**** parent beforeUpdate</span><br><span class="line">**** parent updated</span><br></pre></td></tr></table></figure><p>此时没有子组件的参与</p><h3 id="子组件创建和销毁,父组件生命周期是个什么表现?"><a href="#子组件创建和销毁,父组件生命周期是个什么表现?" class="headerlink" title="子组件创建和销毁,父组件生命周期是个什么表现?"></a>子组件创建和销毁,父组件生命周期是个什么表现?</h3><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><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"><template></span><br><span class="line"> <div class="main"></span><br><span class="line"> <h1>我是一个测试生命周期的组件</h1></span><br><span class="line"></span><br><span class="line"> <hr /></span><br><span class="line"> 子组件在这:</span><br><span class="line"> <SlInput id="tip_text" :title="title" v-if="isShow" /></span><br><span class="line"> <hr /></span><br><span class="line"> <div></span><br><span class="line"> <button @click="onClickToggle">点击{{ isShow ? '隐藏' : '显示' }}</button></span><br><span class="line"> </div></span><br><span class="line"> </div></span><br><span class="line"></template></span><br><span class="line"><script> </span><br><span class="line">{</span><br><span class="line"> data() {</span><br><span class="line"> return {</span><br><span class="line"> isShow: true</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> methods: {</span><br><span class="line"> onClickToggle() {</span><br><span class="line"> this.isShow = !this.isShow</span><br><span class="line"> },</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></script> </span><br></pre></td></tr></table></figure><p>点击隐藏子组件</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><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">**** parent beforeUpdate</span><br><span class="line">**** parent beforeUpdate -test dom: <div id="tip_text">…</div></span><br><span class="line">**** children beforeDestroy</span><br><span class="line">**** children destroyed</span><br><span class="line">**** parent updated</span><br><span class="line">**** parent updated -test dom: null</span><br></pre></td></tr></table></figure><p>模拟子组件销毁,可以看出:</p><ul><li>子组件销毁之前,父组件进入 beforeUpdate;</li><li>等子组件销毁完毕,继续进行父组件的 updated,父组件更新完毕;</li></ul><p>点击显示子组件</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><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">**** parent beforeUpdate</span><br><span class="line">**** parent beforeUpdate -test dom: null</span><br><span class="line">**** children beforeCreate</span><br><span class="line">**** children created</span><br><span class="line">**** children beforeMount</span><br><span class="line">**** children mounted</span><br><span class="line">**** parent updated</span><br><span class="line">**** parent updated -test dom: <div id="tip_text">…</div></span><br></pre></td></tr></table></figure><p>父组件内,模拟初始化子组件,可以看出:</p><ul><li>子组件实例化之前,父组件进入 beforeUpdate;</li><li>等子组件挂载完毕,继续进行父组件的 updated,父组件更新完毕;</li></ul><h2 id="组件嵌套时,生命周期总结"><a href="#组件嵌套时,生命周期总结" class="headerlink" title="组件嵌套时,生命周期总结"></a>组件嵌套时,生命周期总结</h2><ul><li>子组件的创建销毁会触发父组件的 update;</li><li>子组件的 update,不一定会触发父组件的 update; </li><li>父组件的 update,不一定会触发子组件的 update; </li></ul>]]></content>
<summary type="html"><p> Vue 的生命周期:beforeCreate,created,beforeMount,beforeUpdate, mounted,beforeUpdate,updated,updated, beforeDestroy,destroy</p></summary>
<category term="Vue" scheme="https://blog.magicyou.cn/categories/Vue/"/>
<category term="Vue" scheme="https://blog.magicyou.cn/tags/Vue/"/>
</entry>
<entry>
<title>算法-四数之和</title>
<link href="https://blog.magicyou.cn/2021/09/28/%E7%AE%97%E6%B3%95-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/"/>
<id>https://blog.magicyou.cn/2021/09/28/%E7%AE%97%E6%B3%95-%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C/</id>
<published>2021-09-28T13:00:02.000Z</published>
<updated>2021-09-28T13:00:02.000Z</updated>
<content type="html"><![CDATA[<p>leetcode-四数之和<br><a href="https://leetcode-cn.com/problems/4sum/">https://leetcode-cn.com/problems/4sum/</a><br>坚持每天进步</p><span id="more"></span><h3 id="四数之和"><a href="#四数之和" class="headerlink" title="四数之和"></a>四数之和</h3><p>给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] :</p><p>0 <= a, b, c, d < n<br>a、b、c 和 d 互不相同<br>nums[a] + nums[b] + nums[c] + nums[d] == target<br>你可以按 任意顺序 返回答案 。</p><p>示例 1:</p><figure class="highlight plain"><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">输入:nums = [1,0,-1,0,-2,2], target = 0</span><br><span class="line">输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]</span><br></pre></td></tr></table></figure><p>示例 2:</p><figure class="highlight plain"><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">输入:nums = [2,2,2,2,2], target = 8</span><br><span class="line">输出:[[2,2,2,2]]</span><br></pre></td></tr></table></figure><p>提示:</p><ul><li>1 <= nums.length <= 200</li><li>-109 <= nums[i] <= 109</li><li>-109 <= target <= 109</li></ul><p>解题思路</p><ul><li>定义双指针,避免暴力循环解题;</li></ul><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><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><br><span class="line"> * @param {number[]} nums</span><br><span class="line"> * @param {number} target</span><br><span class="line"> * @return {number[][]}</span><br><span class="line"> */</span><br><span class="line">var fourSum = function (nums, target) {</span><br><span class="line"></span><br><span class="line"> nums = nums.sort((a, b) => (a - b));</span><br><span class="line"> let res = [];</span><br><span class="line"> let len = nums.length;</span><br><span class="line"> for (let i = 0; i < len - 2; i++) {</span><br><span class="line"> </span><br><span class="line"> if (i > 0 && nums[i] == nums[i - 1]) {</span><br><span class="line"> continue;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> for (let j = i + 1; j < len - 2; j++) {</span><br><span class="line"> </span><br><span class="line"> if (j > i + 1 && nums[j] == nums[j - 1]) {</span><br><span class="line"> continue;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> let firstNum = nums[i];</span><br><span class="line"> let secondNum = nums[j];</span><br><span class="line"></span><br><span class="line"> const restVal = target - firstNum - secondNum</span><br><span class="line"></span><br><span class="line"> let leftIndex = j + 1;</span><br><span class="line"> let rightIndex = len - 1;</span><br><span class="line"> while(leftIndex < rightIndex) {</span><br><span class="line"> let sum = nums[leftIndex] + nums[rightIndex];</span><br><span class="line"> if (restVal === sum) {</span><br><span class="line"></span><br><span class="line"> res.push([firstNum, secondNum, nums[leftIndex], nums[rightIndex]]);</span><br><span class="line"></span><br><span class="line"> while (nums[leftIndex] === nums[leftIndex + 1]) {</span><br><span class="line"> leftIndex++;</span><br><span class="line"> }</span><br><span class="line"> while (nums[rightIndex] === nums[rightIndex - 1]) {</span><br><span class="line"> rightIndex--;</span><br><span class="line"> }</span><br><span class="line"> leftIndex++;</span><br><span class="line"> rightIndex--;</span><br><span class="line"> } else if (sum < restVal) {</span><br><span class="line"> leftIndex++;</span><br><span class="line"> } else if (sum > restVal) {</span><br><span class="line"> rightIndex--;</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"> return res;</span><br><span class="line"></span><br><span class="line">};</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><p>leetcode-四数之和<br><a href="https://leetcode-cn.com/problems/4sum/">https://leetcode-cn.com/problems/4sum/</a><br>坚持每天进步</p></summary>
<category term="算法" scheme="https://blog.magicyou.cn/categories/%E7%AE%97%E6%B3%95/"/>
<category term="算法" scheme="https://blog.magicyou.cn/tags/%E7%AE%97%E6%B3%95/"/>
</entry>
<entry>
<title>算法-最接近的三数之和</title>
<link href="https://blog.magicyou.cn/2021/09/27/%E7%AE%97%E6%B3%95-%E6%9C%80%E6%8E%A5%E8%BF%91%E7%9A%84%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C/"/>
<id>https://blog.magicyou.cn/2021/09/27/%E7%AE%97%E6%B3%95-%E6%9C%80%E6%8E%A5%E8%BF%91%E7%9A%84%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C/</id>
<published>2021-09-27T13:00:02.000Z</published>
<updated>2021-09-27T13:00:02.000Z</updated>
<content type="html"><![CDATA[<p>leetcode-最接近的三数之和<br><a href="https://leetcode-cn.com/problems/3sum-closest/">https://leetcode-cn.com/problems/3sum-closest/</a><br>坚持每天进步</p><span id="more"></span><h3 id="最接近的三数之和"><a href="#最接近的三数之和" class="headerlink" title="最接近的三数之和"></a>最接近的三数之和</h3><p>给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。</p><p>示例:</p><figure class="highlight plain"><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">输入:nums = [-1,2,1,-4], target = 1</span><br><span class="line">输出:2</span><br></pre></td></tr></table></figure><p>解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。</p><p>提示:</p><ul><li>3 <= nums.length <= 10^3</li><li>-10^3 <= nums[i] <= 10^3</li><li>-10^4 <= target <= 10^4</li></ul><p>解题思路</p><ul><li>定义双指针,避免暴力循环解题;</li></ul><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><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></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * @param {number[]} nums</span><br><span class="line"> * @param {number} target</span><br><span class="line"> * @return {number}</span><br><span class="line"> */</span><br><span class="line">var threeSumClosest = function (nums, target) {</span><br><span class="line"> nums = nums.sort((a, b) => (a - b));</span><br><span class="line"> let min = target;</span><br><span class="line"> let res = 0;</span><br><span class="line"> for (let len = nums.length, i = 0; i < len - 2; i++) {</span><br><span class="line"> const currNum = nums[i];</span><br><span class="line"> let leftIndex = i + 1;</span><br><span class="line"> let rightIndex = len - 1;</span><br><span class="line"></span><br><span class="line"> if (i === 0) {</span><br><span class="line"> min = Math.abs(target - (currNum + nums[1] + nums[2]));</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> while (leftIndex < rightIndex) {</span><br><span class="line"> const sum = (currNum + nums[leftIndex] + nums[rightIndex]);</span><br><span class="line"> const cha = target - sum;</span><br><span class="line"> const chaAbs = Math.abs(cha);</span><br><span class="line"></span><br><span class="line"> if (chaAbs == 0) {</span><br><span class="line"> res = sum;</span><br><span class="line"> min = 0;</span><br><span class="line"> break;</span><br><span class="line"> } else if (chaAbs <= min) {</span><br><span class="line"> min = chaAbs;</span><br><span class="line"> res = sum;</span><br><span class="line"> }</span><br><span class="line"> if (cha > 0) {</span><br><span class="line"> leftIndex++;</span><br><span class="line"> } else if (cha < 0) {</span><br><span class="line"> rightIndex--;</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"> return res;</span><br><span class="line">};</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><p>leetcode-最接近的三数之和<br><a href="https://leetcode-cn.com/problems/3sum-closest/">https://leetcode-cn.com/problems/3sum-closest/</a><br>坚持每天进步</p></summary>
<category term="算法" scheme="https://blog.magicyou.cn/categories/%E7%AE%97%E6%B3%95/"/>
<category term="算法" scheme="https://blog.magicyou.cn/tags/%E7%AE%97%E6%B3%95/"/>
</entry>
<entry>
<title>算法-20210926-三数之和</title>
<link href="https://blog.magicyou.cn/2021/09/26/%E7%AE%97%E6%B3%95-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C/"/>
<id>https://blog.magicyou.cn/2021/09/26/%E7%AE%97%E6%B3%95-%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C/</id>
<published>2021-09-26T13:00:02.000Z</published>
<updated>2021-09-26T13:00:02.000Z</updated>
<content type="html"><![CDATA[<p>leetcode-三数之和<br><a href="https://leetcode-cn.com/problems/3sum/">https://leetcode-cn.com/problems/3sum/</a><br>坚持每天进步</p><span id="more"></span><h3 id="三数之和"><a href="#三数之和" class="headerlink" title="三数之和"></a>三数之和</h3><p>给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。</p><p>注意:答案中不可以包含重复的三元组。</p><p>示例 1:</p><figure class="highlight plain"><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">输入:nums = [-1,0,1,2,-1,-4]</span><br><span class="line">输出:[[-1,-1,2],[-1,0,1]]</span><br></pre></td></tr></table></figure><p>示例 2:</p><figure class="highlight plain"><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">输入:nums = []</span><br><span class="line">输出:[]</span><br></pre></td></tr></table></figure><p>示例 3:</p><figure class="highlight plain"><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">输入:nums = [0]</span><br><span class="line">输出:[]</span><br></pre></td></tr></table></figure><p>提示:</p><ul><li>0 <= nums.length <= 3000</li><li>-105 <= nums[i] <= 105</li></ul><p>解题思路</p><ul><li>定义双指针,避免暴力循环解题;</li><li>使用逻辑判断,有效的避免重复数据,同事提高循环效率;</li></ul><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><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><br><span class="line"> * @param {number[]} nums</span><br><span class="line"> * @return {number[][]}</span><br><span class="line"> */</span><br><span class="line">var threeSum = function (nums) {</span><br><span class="line"> let res = [];</span><br><span class="line"> const len = nums.length;</span><br><span class="line"> nums = nums.sort((a, b) => (a - b));</span><br><span class="line"> for (let i = 0; i < len - 2; i++) {</span><br><span class="line"></span><br><span class="line"> if (i > 0 && nums[i] === nums[i - 1]) {</span><br><span class="line"> continue;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> // 定义双指针</span><br><span class="line"> let leftIndex = i + 1;</span><br><span class="line"> let rightIndex = len - 1;</span><br><span class="line"></span><br><span class="line"> while (leftIndex < rightIndex) {</span><br><span class="line"> const sum = nums[i] + nums[leftIndex] + nums[rightIndex];</span><br><span class="line"> if (sum === 0) {</span><br><span class="line"> res.push([</span><br><span class="line"> nums[i], nums[leftIndex], nums[rightIndex]</span><br><span class="line"> ]);</span><br><span class="line"> while (nums[leftIndex] == nums[leftIndex + 1]) {</span><br><span class="line"> leftIndex++;</span><br><span class="line"> }</span><br><span class="line"> while (nums[rightIndex] == nums[rightIndex - 1]) {</span><br><span class="line"> rightIndex--;</span><br><span class="line"> }</span><br><span class="line"> leftIndex++;</span><br><span class="line"> rightIndex--;</span><br><span class="line"> } else if (sum > 0) {</span><br><span class="line"> rightIndex--;</span><br><span class="line"> } else if (sum < 0) {</span><br><span class="line"> leftIndex++;</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"> return res;</span><br><span class="line">};</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><p>leetcode-三数之和<br><a href="https://leetcode-cn.com/problems/3sum/">https://leetcode-cn.com/problems/3sum/</a><br>坚持每天进步</p></summary>
<category term="算法" scheme="https://blog.magicyou.cn/categories/%E7%AE%97%E6%B3%95/"/>
<category term="算法" scheme="https://blog.magicyou.cn/tags/%E7%AE%97%E6%B3%95/"/>
</entry>
<entry>
<title>算法-最长公共前缀</title>
<link href="https://blog.magicyou.cn/2021/09/25/%E7%AE%97%E6%B3%95-%E6%9C%80%E9%95%BF%E5%85%AC%E5%85%B1%E5%89%8D%E7%BC%80/"/>
<id>https://blog.magicyou.cn/2021/09/25/%E7%AE%97%E6%B3%95-%E6%9C%80%E9%95%BF%E5%85%AC%E5%85%B1%E5%89%8D%E7%BC%80/</id>
<published>2021-09-25T13:00:02.000Z</published>
<updated>2021-09-25T13:00:02.000Z</updated>
<content type="html"><![CDATA[<p>leetcode-最长公共前缀<br><a href="https://leetcode-cn.com/problems/longest-common-prefix/">https://leetcode-cn.com/problems/longest-common-prefix/</a><br>坚持每天进步</p><span id="more"></span><h3 id="最长公共前缀"><a href="#最长公共前缀" class="headerlink" title="最长公共前缀"></a>最长公共前缀</h3><p>编写一个函数来查找字符串数组中的最长公共前缀。</p><p>如果不存在公共前缀,返回空字符串 “”。</p><p>示例 1:</p><figure class="highlight plain"><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">输入:strs = ["flower","flow","flight"]</span><br><span class="line">输出:"fl"</span><br></pre></td></tr></table></figure><p>示例 2:</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></pre></td><td class="code"><pre><span class="line">输入:strs = ["dog","racecar","car"]</span><br><span class="line">输出:""</span><br><span class="line">解释:输入不存在公共前缀。</span><br></pre></td></tr></table></figure><p>提示:</p><ul><li>1 <= strs.length <= 200</li><li>0 <= strs[i].length <= 200</li><li>strs[i] 仅由小写英文字母组成</li></ul><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><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><br><span class="line"> * @param {string[]} strs</span><br><span class="line"> * @return {string}</span><br><span class="line"> */</span><br><span class="line">var longestCommonPrefix = function (strs) {</span><br><span class="line"> if (strs.length === 1) {</span><br><span class="line"> return strs[0]</span><br><span class="line"> }</span><br><span class="line"> let prefix = '';</span><br><span class="line"> let firstStr = strs[0];</span><br><span class="line"> for (let len = firstStr.length + 1, i = 1; i < len; i++) {</span><br><span class="line"> const temPrefix = firstStr.slice(0, i);</span><br><span class="line"> // console.log('temPrefix:', temPrefix);</span><br><span class="line"> let hasFlag = true;</span><br><span class="line"> for (let len2 = strs.length, j = 1; j < len2; j++) {</span><br><span class="line"> if (strs[j].indexOf(temPrefix) !== 0) {</span><br><span class="line"> hasFlag = false;</span><br><span class="line"> break;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> if (!hasFlag) {</span><br><span class="line"> break;</span><br><span class="line"> } else {</span><br><span class="line"> prefix = temPrefix;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> return prefix;</span><br><span class="line">};</span><br></pre></td></tr></table></figure><p>暂时没有更好的办法,暴力解题</p>]]></content>
<summary type="html"><p>leetcode-最长公共前缀<br><a href="https://leetcode-cn.com/problems/longest-common-prefix/">https://leetcode-cn.com/problems/longest-common-prefix/</a><br>坚持每天进步</p></summary>
<category term="算法" scheme="https://blog.magicyou.cn/categories/%E7%AE%97%E6%B3%95/"/>
<category term="算法" scheme="https://blog.magicyou.cn/tags/%E7%AE%97%E6%B3%95/"/>
</entry>
<entry>
<title>算法-20210924-盛最多水的容器</title>
<link href="https://blog.magicyou.cn/2021/09/24/%E7%AE%97%E6%B3%95-%E7%9B%9B%E6%9C%80%E5%A4%9A%E6%B0%B4%E7%9A%84%E5%AE%B9%E5%99%A8/"/>
<id>https://blog.magicyou.cn/2021/09/24/%E7%AE%97%E6%B3%95-%E7%9B%9B%E6%9C%80%E5%A4%9A%E6%B0%B4%E7%9A%84%E5%AE%B9%E5%99%A8/</id>
<published>2021-09-24T13:00:02.000Z</published>
<updated>2021-09-24T13:00:02.000Z</updated>
<content type="html"><![CDATA[<p>leetcode-盛最多水的容器<br><a href="https://leetcode-cn.com/problems/container-with-most-water/">https://leetcode-cn.com/problems/container-with-most-water/</a><br>坚持每天进步</p><span id="more"></span><h3 id="盛最多水的容器"><a href="#盛最多水的容器" class="headerlink" title="盛最多水的容器"></a>盛最多水的容器</h3><p>给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。</p><p>说明:你不能倾斜容器。</p><p>示例 1:</p><p><img src="/static/img/%E7%9B%9B%E6%9C%80%E5%A4%9A%E6%B0%B4%E7%9A%84%E5%AE%B9%E5%99%A8.jpg" alt="盛最多水的容器"></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></pre></td><td class="code"><pre><span class="line">输入:[1,8,6,2,5,4,8,3,7]</span><br><span class="line">输出:49 </span><br><span class="line">解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。</span><br></pre></td></tr></table></figure><p>示例 2:</p><figure class="highlight plain"><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">输入:height = [1,1]</span><br><span class="line">输出:1</span><br></pre></td></tr></table></figure><p>示例 3:</p><figure class="highlight plain"><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">输入:height = [4,3,2,1,4]</span><br><span class="line">输出:16</span><br></pre></td></tr></table></figure><p>示例 4:</p><figure class="highlight plain"><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">输入:height = [1,2,1]</span><br><span class="line">输出:2</span><br></pre></td></tr></table></figure><p>提示:</p><ul><li>n == height.length</li><li>2 <= n <= 105</li><li>0 <= height[i] <= 104</li></ul><h3 id="解题"><a href="#解题" class="headerlink" title="解题"></a>解题</h3><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><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></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * @param {number[]} height</span><br><span class="line"> * @return {number}</span><br><span class="line"> */</span><br><span class="line">var maxArea = function (height) {</span><br><span class="line"></span><br><span class="line"> let max = 0;</span><br><span class="line"> const length = height.length;</span><br><span class="line"> let startIndex = 0;</span><br><span class="line"> let endIndex = length - 1;</span><br><span class="line"> while (startIndex < endIndex) {</span><br><span class="line"> let len = endIndex - startIndex;</span><br><span class="line"> let h = height[startIndex];</span><br><span class="line"> if (height[startIndex] > height[endIndex]) {</span><br><span class="line"> h = height[endIndex];</span><br><span class="line"> endIndex--;</span><br><span class="line"> } else {</span><br><span class="line"> h = height[startIndex];</span><br><span class="line"> startIndex++;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> const sum = len * h;</span><br><span class="line"> if (sum > max) {</span><br><span class="line"> max = sum</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> return max;</span><br><span class="line"></span><br><span class="line">};</span><br></pre></td></tr></table></figure><p>前后两个游标向中间移动寻求最优解</p>]]></content>
<summary type="html"><p>leetcode-盛最多水的容器<br><a href="https://leetcode-cn.com/problems/container-with-most-water/">https://leetcode-cn.com/problems/container-with-most-water/</a><br>坚持每天进步</p></summary>
<category term="算法" scheme="https://blog.magicyou.cn/categories/%E7%AE%97%E6%B3%95/"/>
<category term="算法" scheme="https://blog.magicyou.cn/tags/%E7%AE%97%E6%B3%95/"/>
</entry>
<entry>
<title>算法-整数转罗马数字</title>
<link href="https://blog.magicyou.cn/2021/09/23/%E7%AE%97%E6%B3%95-%E6%95%B4%E6%95%B0%E8%BD%AC%E7%BD%97%E9%A9%AC%E6%95%B0%E5%AD%97/"/>
<id>https://blog.magicyou.cn/2021/09/23/%E7%AE%97%E6%B3%95-%E6%95%B4%E6%95%B0%E8%BD%AC%E7%BD%97%E9%A9%AC%E6%95%B0%E5%AD%97/</id>
<published>2021-09-23T13:00:02.000Z</published>
<updated>2021-09-23T13:00:02.000Z</updated>
<content type="html"><![CDATA[<p>leetcode-整数转罗马数字<br><a href="https://leetcode-cn.com/problems/integer-to-roman/">https://leetcode-cn.com/problems/integer-to-roman/</a><br>坚持每天进步</p><span id="more"></span><h3 id="整数转罗马数字"><a href="#整数转罗马数字" class="headerlink" title="整数转罗马数字"></a>整数转罗马数字</h3><p>罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。</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><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">I 1</span><br><span class="line">V 5</span><br><span class="line">X 10</span><br><span class="line">L 50</span><br><span class="line">C 100</span><br><span class="line">D 500</span><br><span class="line">M 1000</span><br></pre></td></tr></table></figure><p>例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。</p><p>通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:</p><p>I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。<br>X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。<br>C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。<br>给你一个整数,将其转为罗马数字。</p><p>示例 1:</p><figure class="highlight plain"><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">输入: num = 3</span><br><span class="line">输出: "III"</span><br></pre></td></tr></table></figure><p>示例 2:</p><figure class="highlight plain"><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">输入: num = 4</span><br><span class="line">输出: "IV"</span><br></pre></td></tr></table></figure><p>示例 3:</p><figure class="highlight plain"><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">输入: num = 9</span><br><span class="line">输出: "IX"</span><br></pre></td></tr></table></figure><p>示例 4:</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></pre></td><td class="code"><pre><span class="line">输入: num = 58</span><br><span class="line">输出: "LVIII"</span><br><span class="line">解释: L = 50, V = 5, III = 3.</span><br></pre></td></tr></table></figure><p>示例 5:</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></pre></td><td class="code"><pre><span class="line">输入: num = 1994</span><br><span class="line">输出: "MCMXCIV"</span><br><span class="line">解释: M = 1000, CM = 900, XC = 90, IV = 4.</span><br></pre></td></tr></table></figure><p>提示:</p><ul><li>1 <= num <= 3999</li></ul><h3 id="解题"><a href="#解题" class="headerlink" title="解题"></a>解题</h3><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><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"> * @param {number} num</span><br><span class="line"> * @return {string}</span><br><span class="line"> */</span><br><span class="line">var intToRoman = function (num) {</span><br><span class="line"> let list1 = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]</span><br><span class="line"> let list2 = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']</span><br><span class="line"></span><br><span class="line"> let len = list1.length, index = 0;</span><br><span class="line"> let res = '';</span><br><span class="line"> while (index < len) {</span><br><span class="line"> while (num >= list1[index]) {</span><br><span class="line"> res += list2[index];</span><br><span class="line"> num -= list1[index];</span><br><span class="line"> }</span><br><span class="line"> index++;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> return res;</span><br><span class="line">};</span><br></pre></td></tr></table></figure><p>贪心算法?</p>]]></content>
<summary type="html"><p>leetcode-整数转罗马数字<br><a href="https://leetcode-cn.com/problems/integer-to-roman/">https://leetcode-cn.com/problems/integer-to-roman/</a><br>坚持每天进步</p></summary>
<category term="算法" scheme="https://blog.magicyou.cn/categories/%E7%AE%97%E6%B3%95/"/>
<category term="算法" scheme="https://blog.magicyou.cn/tags/%E7%AE%97%E6%B3%95/"/>
</entry>
<entry>
<title>React 简单入门</title>
<link href="https://blog.magicyou.cn/2021/04/13/react-%E7%AE%80%E5%8D%95%E5%85%A5%E9%97%A8/"/>
<id>https://blog.magicyou.cn/2021/04/13/react-%E7%AE%80%E5%8D%95%E5%85%A5%E9%97%A8/</id>
<published>2021-04-13T13:33:00.000Z</published>
<updated>2021-04-13T13:33:00.000Z</updated>
<content type="html"><![CDATA[<p>React 简单入门</p><span id="more"></span><hr><p>目标: </p><blockquote><ul><li>类比vue入门 react</li><li>简单入门,着重react使用方法</li><li>教程暂时不议论 <strong>redux</strong></li></ul></blockquote><hr><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><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></pre></td><td class="code"><pre><span class="line">npx create-react-app my-app</span><br><span class="line">cd my-app</span><br><span class="line">npm start</span><br></pre></td></tr></table></figure><blockquote><p><strong>注意:</strong><br>第一行的 <code>npx</code> 不是拼写错误 —— 它是 <a href="https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b">npm 5.2+ 附带的 package 运行工具</a>。</p></blockquote><p>安装结束之后,的 app.js , 一起见识一下 <strong>JSX</strong></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><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">import logo from './logo.svg';</span><br><span class="line">import './App.css';</span><br><span class="line"></span><br><span class="line">function App() {</span><br><span class="line"> return (</span><br><span class="line"> <div className="App"></span><br><span class="line"> <header className="App-header"></span><br><span class="line"> <img src={logo} className="App-logo" alt="logo" /></span><br><span class="line"> <p></span><br><span class="line"> Edit <code>src/App.js</code> and save to reload.</span><br><span class="line"> </p></span><br><span class="line"> <a</span><br><span class="line"> className="App-link"</span><br><span class="line"> href="https://reactjs.org"</span><br><span class="line"> target="_blank"</span><br><span class="line"> rel="noopener noreferrer"</span><br><span class="line"> ></span><br><span class="line"> Learn React</span><br><span class="line"> </a></span><br><span class="line"> </header></span><br><span class="line"> </div></span><br><span class="line"> );</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">export default App;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="认识-JSX"><a href="#认识-JSX" class="headerlink" title="认识 JSX"></a>认识 JSX</h2><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">const element = <h1>Hello, world!</h1>;</span><br></pre></td></tr></table></figure><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><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">const element = (</span><br><span class="line"> <div></span><br><span class="line"> <h1>Hello!</h1></span><br><span class="line"> <h2>Good to see you here.</h2></span><br><span class="line"> </div></span><br><span class="line">);</span><br></pre></td></tr></table></figure><p>按照管官方的话说:既不是字符串也不是 HTML</p><ul><li>React 认为渲染逻辑本质上与其他 UI 逻辑内在耦合</li><li>在 JavaScript 代码中将 JSX 和 UI 放在一起时,会在视觉上有辅助作用</li><li>eact DOM 在渲染所有输入内容之前,默认会进行转义, 可以有效地防止 XSS(cross-site-scripting, 跨站脚本)攻击,防止注入攻击</li></ul><h3 id="1-在-JSX-中-可以在大括号内放置任何有效的-JavaScript-表达式"><a href="#1-在-JSX-中-可以在大括号内放置任何有效的-JavaScript-表达式" class="headerlink" title="1. 在 JSX 中, 可以在大括号内放置任何有效的 JavaScript 表达式"></a>1. 在 JSX 中, 可以在大括号内放置任何有效的 JavaScript 表达式</h3><pre><code><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> name = <span class="string">'lxl'</span>;</span><br><span class="line"><span class="keyword">const</span> element = (</span><br><span class="line"> <h1></span><br><span class="line"> Hello, {name}!</span><br><span class="line"> </h1></span><br><span class="line">);</span><br></pre></td></tr></table></figure></code></pre><h3 id="2-JSX-特定属性"><a href="#2-JSX-特定属性" class="headerlink" title="2. JSX 特定属性"></a>2. JSX 特定属性</h3><ul><li><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> element = <span class="xml"><span class="tag"><<span class="name">div</span> <span class="attr">tabIndex</span>=<span class="string">"0"</span>></span><span class="tag"></<span class="name">div</span>></span></span>;</span><br></pre></td></tr></table></figure></li><li><p>使用大括号,来在属性值中插入一个 JavaScript 表达式</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> element = <span class="xml"><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">{user.avatarUrl}</span>></span><span class="tag"></<span class="name">img</span>></span></span>;</span><br></pre></td></tr></table></figure><blockquote><p>注意: </p><ul><li>在属性中嵌入 JavaScript 表达式时,不要在大括号外面加上引号。你应该仅使用引号(对于字符串值)或大括号(对于表达式)中的一个,对于同一属性不能同时使用这两种符号</li><li>因为 JSX 语法上更接近 JavaScript 而不是 HTML,所以 React DOM 使用 camelCase(小驼峰命名)来定义属性的名称,而不使用 HTML 属性名称的命名约定,例如:data-id 写为 dataId</li><li>JSX 里的 class 是个关键字,所以使用 className 代替 class。</li></ul></blockquote></li></ul><h2 id="JSX-原理"><a href="#JSX-原理" class="headerlink" title="JSX 原理"></a>JSX 原理</h2><p>简单来说就是对象,和vue的虚拟DOM一样,你写的想模板的jsx代码会转换成类似下边的结构</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><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">const element = {</span><br><span class="line"> type: 'h1',</span><br><span class="line"> props: {</span><br><span class="line"> className: 'greeting',</span><br><span class="line"> children: 'Hello, world!'</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><p>Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用</p><p>等效的写法</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><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">const element = (</span><br><span class="line"> <h1 className="greeting"></span><br><span class="line"> Hello, world!</span><br><span class="line"> </h1></span><br><span class="line">);</span><br></pre></td></tr></table></figure><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><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">const element = React.createElement(</span><br><span class="line"> 'h1',</span><br><span class="line"> {className: 'greeting'},</span><br><span class="line"> 'Hello, world!'</span><br><span class="line">);</span><br></pre></td></tr></table></figure><h1 id="函数组件与-class-组件"><a href="#函数组件与-class-组件" class="headerlink" title="函数组件与 class 组件"></a>函数组件与 class 组件</h1><h2 id="函数组件"><a href="#函数组件" class="headerlink" title="函数组件"></a>函数组件</h2><p>最先安装好 react 后的 app.js,就是一个简单的函数组件,本质上就是一个函数,同样也能接收参数</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></pre></td><td class="code"><pre><span class="line">function Welcome(props) {</span><br><span class="line"> return <h1>Hello, {props.name}</h1>;</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><p>上文说的 jsx 特性里 ‘JSX 里的 class 是个关键字,所以使用 className 代替 class’,是有点误解,事实上 class 是 ES6 的关键词,声明一个 <strong>类</strong>:</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><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">class Welcome extends React.Component {</span><br><span class="line"> render() {</span><br><span class="line"> return <h1>Hello, {this.props.name}</h1>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h1 id="State"><a href="#State" class="headerlink" title="State"></a>State</h1><p>和vue一样,react也需要存储很多状态,通常是一些页面需要渲染的数据、响应页面元素的变量等,react的状态需要 __state__管理(高阶可以结合redux):</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></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserInfo</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span> </span>{</span><br><span class="line"> <span class="function"><span class="title">constructor</span>(<span class="params">props</span>)</span> {</span><br><span class="line"> <span class="built_in">super</span>(props);</span><br><span class="line"> <span class="built_in">this</span>.state = {<span class="attr">name</span>: <span class="string">'lxl'</span>, <span class="attr">age</span>: <span class="number">18</span>};</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="title">render</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> <h1>User Info</h1></span><br><span class="line"> <h2>name: {<span class="built_in">this</span>.state.name}.</h2></span><br><span class="line"> <h2>age: {<span class="built_in">this</span>.state.age}.</h2></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>与vue不同,state并没有被组件或者对象双向绑定,无法响应式的直接‘this.state.name = ‘www’’,设置name,这样是错误的,需要调用 setState:</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></pre></td><td class="code"><pre><span class="line">this.setState({</span><br><span class="line"> date: new Date()</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p> this.setState({<br> date: new Date()<br> });</p><h2 id="数据自顶向下流动"><a href="#数据自顶向下流动" class="headerlink" title="数据自顶向下流动"></a>数据自顶向下流动</h2><p>引用一下菜鸟的文字:</p><blockquote><ul><li>父组件或子组件都不能知道某个组件是有状态还是无状态,并且它们不应该关心某组件是被定义为一个函数还是一个类。这就是为什么状态通常被称为局部或封装。 除了拥有并设置它的组件外,其它组件不可访问。</li><li>任何状态始终由某些特定组件所有,并且从该状态导出的任何数据或 UI 只能影响树中下方的组件</li></ul></blockquote><h1 id="生命周期"><a href="#生命周期" class="headerlink" title="生命周期"></a>生命周期</h1><p>React v16.3之前组件的生命周期可分成三个状态:</p><ul><li>Mounting:已插入真实 DOM</li><li>Updating:正在被重新渲染</li><li>Unmounting:已移出真实 DOM</li></ul><pre><code>| 生命周期 | 描述 || ------------------------- | ------------------------------------------------------------ || componentWillMount | 只会在装载之前调用一次,在 `render` 之前调用,你可以在这个方法里面调用 `setState` 改变状态,并且不会导致额外调用一次 `render` || componentDidMount | 只会在装载完成之后调用一次,在 `render` 之后调用,从这里开始可以通过 `ReactDOM.findDOMNode(this)` 获取到组件的 DOM 节点。以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。 || componentWillReceiveProps | 更新组件触发,在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。 || shouldComponentUpdate | 更新组件触发,返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。<br/>可以在你确认不需要更新组件时使用。 || componentWillUpdate | 更新组件触发,在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。 || componentDidUpdate | 更新组件触发在组件完成更新后立即调用。在初始化时不会被调用。 || componentWillUnmount | 卸载组件触发,在组件从 DOM 中移除之前立刻被调用。 |</code></pre><p>React v16.3 之后,引入了两个新的生命周期函数:</p><ul><li>getDerivedStateFromProps</li><li>getSnapshotBeforeUpdate</li></ul><p>同时deprecate了一组生命周期API,包括:</p><ul><li>componentWillReceiveProps</li><li>componentWillMount</li><li>componentWillUpdate</li></ul><p>看例子,userInfo。</p><h1 id="事件处理"><a href="#事件处理" class="headerlink" title="事件处理"></a>事件处理</h1><p>事件处理上和 DOM 元素的很相似,不同的是:</p><ul><li>React 事件的命名采用小驼峰式(camelCase),而不是纯小写。<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></pre></td><td class="code"><pre><span class="line"><button onClick={activateLasers}></span><br><span class="line"> Activate Lasers</span><br><span class="line"></button></span><br></pre></td></tr></table></figure>onBlur、onInput …</li><li>使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。</li></ul><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><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">function ActionLink() {</span><br><span class="line"> function handleClick(e) {</span><br><span class="line"> e.preventDefault();</span><br><span class="line"> console.log('The link was clicked.');</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> return (</span><br><span class="line"> <a href="#" onClick={handleClick}></span><br><span class="line"> Click me</span><br><span class="line"> </a></span><br><span class="line"> );</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>来自官方忠告:</p><blockquote><p>你必须谨慎对待 JSX 回调函数中的 this,在 JavaScript 中,class 的方法默认不会绑定 this。如果你忘记绑定 this.handleClick 并把它传入了 onClick,当你调用这个函数的时候 this 的值为 undefined。<br>这并不是 React 特有的行为;这其实与 JavaScript 函数工作原理有关。通常情况下,如果你没有在方法后面添加 (),例如 onClick={this.handleClick},你应该为这个方法绑定 this。 </p></blockquote><p>如果觉得使用 bind 很麻烦,这里有两种方式可以解决。</p><ul><li><ol><li>如果你正在使用实验性的 public class fields 语法,你可以使用 class fields 正确的绑定回调函数</li></ol> <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><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">class LoggingButton extends React.Component {</span><br><span class="line">// 此语法确保 `handleClick` 内的 `this` 已被绑定。</span><br><span class="line">// 注意: 这是 *实验性* 语法。</span><br><span class="line">handleClick = () => {</span><br><span class="line"> console.log('this is:', this);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">render() {</span><br><span class="line"> return (</span><br><span class="line"> <button onClick={this.handleClick}></span><br><span class="line"> Click me</span><br><span class="line"> </button></span><br><span class="line"> );</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><ol start="2"><li>如果你没有使用 class fields 语法,你可以在回调中使用箭头函数</li></ol> <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><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">class LoggingButton extends React.Component {</span><br><span class="line">handleClick() {</span><br><span class="line"> console.log('this is:', this);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">render() {</span><br><span class="line"> // 此语法确保 `handleClick` 内的 `this` 已被绑定。</span><br><span class="line"> return (</span><br><span class="line"> <button onClick={() => this.handleClick()}></span><br><span class="line"> Click me</span><br><span class="line"> </button></span><br><span class="line"> );</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><blockquote><p><strong>注意</strong>:<br>此语法问题在于每次渲染 LoggingButton 时都会创建不同的回调函数。在大多数情况下,这没什么问题,但如果该回调函数作为 prop 传入子组件时,这些组件可能会进行额外的重新渲染。我们通常建议在构造器中绑定或使用 class fields 语法来避免这类性能问题</p></blockquote><h1 id="条件渲染"><a href="#条件渲染" class="headerlink" title="条件渲染"></a>条件渲染</h1><ul><li><p>可以直接三目运算符:</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><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">render() {</span><br><span class="line"> const showUser = false;</span><br><span class="line"> return (</span><br><span class="line"> <div></span><br><span class="line"> {showUser ? <UserInfo userData={userData}/> : <span>啥也没有</span>}</span><br><span class="line"> </div></span><br><span class="line"> )</span><br><span class="line"> }</span><br></pre></td></tr></table></figure></li><li><p>可以if else:</p></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">toggleUserInfo () {</span><br><span class="line"> <span class="keyword">const</span> showUser = <span class="literal">false</span>;</span><br><span class="line"> <span class="keyword">if</span> (showUser) {</span><br><span class="line"> <span class="keyword">return</span> <span class="xml"><span class="tag"><<span class="name">UserInfo</span> /></span></span>;</span><br><span class="line"> } <span class="keyword">else</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><span class="line"><span class="function"><span class="title">render</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> {toggleUserInfo}</span><br><span class="line"> </div></span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="title">render</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="keyword">const</span> showUser = <span class="literal">false</span>;</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> {showUser && <span class="xml"><span class="tag"><<span class="name">UserInfo</span> <span class="attr">userData</span>=<span class="string">{userData}/</span>></span></span>}</span><br><span class="line"> </div></span><br><span class="line"> )</span><br><span class="line"> }</span><br></pre></td></tr></table></figure></li></ul><p>没有做不到,只有想不到</p><h1 id="列表渲染"><a href="#列表渲染" class="headerlink" title="列表渲染"></a>列表渲染</h1><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">render () {</span><br><span class="line"> <span class="keyword">const</span> links = [</span><br><span class="line"> {<span class="string">'name'</span>: <span class="string">'Blog'</span>, <span class="attr">icon</span>:<span class="string">'iconbiji'</span>, <span class="attr">linkUrl</span>: <span class="string">'https://blog.magicyou.cn/'</span>},</span><br><span class="line"> {<span class="string">'name'</span>: <span class="string">'Cloud'</span>, <span class="attr">icon</span>:<span class="string">'iconwenjianjia'</span>, <span class="attr">linkUrl</span>: <span class="string">''</span>},</span><br><span class="line"> {<span class="string">'name'</span>: <span class="string">'Frp'</span>, <span class="attr">icon</span>:<span class="string">'icondiannao'</span>, <span class="attr">linkUrl</span>: <span class="string">''</span>},</span><br><span class="line"> {<span class="string">'name'</span>: <span class="string">'Pi'</span>, <span class="attr">icon</span>:<span class="string">'iconcaomeigan'</span>, <span class="attr">linkUrl</span>: <span class="string">'http://pi.magicyou.cn/'</span>},</span><br><span class="line"> ];</span><br><span class="line"></span><br><span class="line"> <Row></span><br><span class="line"> {links.map(<span class="function">(<span class="params">item, index</span>) =></span> (</span><br><span class="line"> <Col className=<span class="string">"gutter-row"</span> span={<span class="number">6</span>} key={index}></span><br><span class="line"> <p className=<span class="string">"height-100"</span>>{ item.name }</p></span><br><span class="line"> </Col></span><br><span class="line"> ))}</span><br><span class="line"> </Row></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h1 id="状态提升"><a href="#状态提升" class="headerlink" title="状态提升"></a>状态提升</h1><p>在 React 中,将多个组件中需要共享的 state 向上移动到它们的最近共同父组件中,便可实现共享 state,这就是所谓的“状态提升”。</p><p>查看温度换算例子</p><h1 id="包含关系"><a href="#包含关系" class="headerlink" title="包含关系"></a>包含关系</h1><p>有些组件无法提前知晓它们子组件的具体内容。在 Sidebar(侧边栏)和 Dialog(对话框)等展现通用容器(box)的组件中特别容易遇到这种情况</p><p>查看组合组件弹窗示例</p><h1 id="路由"><a href="#路由" class="headerlink" title="路由"></a>路由</h1><p><a href="http://react-guide.github.io/react-router-cn/docs/guides/basics/RouteConfiguration.html">http://react-guide.github.io/react-router-cn/docs/guides/basics/RouteConfiguration.html</a></p>]]></content>
<summary type="html"><p>React 简单入门</p></summary>
<category term="JavaScript" scheme="https://blog.magicyou.cn/tags/JavaScript/"/>
<category term="react" scheme="https://blog.magicyou.cn/tags/react/"/>
</entry>
<entry>
<title>Linux-安装git及秘钥生成</title>
<link href="https://blog.magicyou.cn/2021/02/03/Linux-%E5%AE%89%E8%A3%85git%E5%8F%8A%E7%A7%98%E9%92%A5%E7%94%9F%E6%88%90/"/>
<id>https://blog.magicyou.cn/2021/02/03/Linux-%E5%AE%89%E8%A3%85git%E5%8F%8A%E7%A7%98%E9%92%A5%E7%94%9F%E6%88%90/</id>
<published>2021-02-03T10:23:00.000Z</published>
<updated>2021-02-03T10:23:00.000Z</updated>
<content type="html"><![CDATA[<p>在Linux系统上安装Git</p><span id="more"></span><h5 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h5><p>Git是目前流行的非常好用的版本控制工具,这里介绍安装和生成秘钥</p><h5 id="1-yum安装git"><a href="#1-yum安装git" class="headerlink" title="1. yum安装git"></a>1. yum安装git</h5><p>在Linux上是有yum安装Git,非常简单,只需要一行命令</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">yum -y install git</span><br></pre></td></tr></table></figure><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><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></pre></td><td class="code"><pre><span class="line">.......</span><br><span class="line">.......</span><br><span class="line">.......</span><br><span class="line">.......</span><br><span class="line">(4/5): git-core-doc-2.27.0-1.el8.noarch.rpm 15 MB/s | 2.5 MB 00:00 </span><br><span class="line">(5/5): git-core-2.27.0-1.el8.x86_64.rpm 22 MB/s | 5.7 MB 00:00 </span><br><span class="line">--------------------------------------------------------------------------------------------------------------------------------------------------------------</span><br><span class="line">Total 33 MB/s | 8.5 MB 00:00 </span><br><span class="line">Running transaction check</span><br><span class="line">Transaction check succeeded.</span><br><span class="line">Running transaction test</span><br><span class="line">Transaction test succeeded.</span><br><span class="line">Running transaction</span><br><span class="line"> Preparing : 1/1 </span><br><span class="line"> Installing : git-core-2.27.0-1.el8.x86_64 1/5 </span><br><span class="line"> Installing : git-core-doc-2.27.0-1.el8.noarch 2/5 </span><br><span class="line"> Installing : perl-Error-1:0.17025-2.el8.noarch 3/5 </span><br><span class="line"> Installing : perl-Git-2.27.0-1.el8.noarch 4/5 </span><br><span class="line"> Installing : git-2.27.0-1.el8.x86_64 5/5 </span><br><span class="line"> Running scriptlet: git-2.27.0-1.el8.x86_64 5/5 </span><br><span class="line"> Verifying : git-2.27.0-1.el8.x86_64 1/5 </span><br><span class="line"> Verifying : git-core-2.27.0-1.el8.x86_64 2/5 </span><br><span class="line"> Verifying : git-core-doc-2.27.0-1.el8.noarch 3/5 </span><br><span class="line"> Verifying : perl-Error-1:0.17025-2.el8.noarch 4/5 </span><br><span class="line"> Verifying : perl-Git-2.27.0-1.el8.noarch 5/5 </span><br><span class="line"></span><br><span class="line">Installed:</span><br><span class="line"> git-2.27.0-1.el8.x86_64 git-core-2.27.0-1.el8.x86_64 git-core-doc-2.27.0-1.el8.noarch perl-Error-1:0.17025-2.el8.noarch perl-Git-2.27.0-1.el8.noarch </span><br><span class="line"></span><br><span class="line">Complete!</span><br></pre></td></tr></table></figure><h5 id="2-生成公钥"><a href="#2-生成公钥" class="headerlink" title="2. 生成公钥"></a>2. 生成公钥</h5><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><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">ssh-keygen -t rsa -C "[email protected]" #-C注释为了区分秘钥,也可以不写</span><br><span class="line"></span><br><span class="line"># Generating public/private rsa key pair...</span><br><span class="line"># 三次回车即可生成 ssh key</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>查看生成的公钥</p><figure class="highlight plain"><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">cat ~/.ssh/id_rsa.pub</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><p>在Linux系统上安装Git</p></summary>
<category term="Linux" scheme="https://blog.magicyou.cn/categories/Linux/"/>
<category term="Linux" scheme="https://blog.magicyou.cn/tags/Linux/"/>
<category term="Centos" scheme="https://blog.magicyou.cn/tags/Centos/"/>
</entry>
<entry>
<title>java-java基础-标识符</title>
<link href="https://blog.magicyou.cn/2020/12/10/java-java%E5%9F%BA%E7%A1%80-%E6%A0%87%E8%AF%86%E7%AC%A6/"/>
<id>https://blog.magicyou.cn/2020/12/10/java-java%E5%9F%BA%E7%A1%80-%E6%A0%87%E8%AF%86%E7%AC%A6/</id>
<published>2020-12-10T05:34:12.000Z</published>
<updated>2020-12-10T05:34:23.000Z</updated>
<content type="html"><![CDATA[<p>什么是标识符:包、类、变量、方法…等等,只要是起名字的地方吗,那个名字就是标识符</p><span id="more"></span><h2 id="什么是标识符"><a href="#什么是标识符" class="headerlink" title="什么是标识符"></a>什么是标识符</h2><p>包、类、变量、方法…等等,只要是起名字的地方吗,那个名字就是标识符</p><h2 id="标识符定义的规则"><a href="#标识符定义的规则" class="headerlink" title="标识符定义的规则"></a>标识符定义的规则</h2><ol><li>四个可以(组成部分)<ul><li>数字</li><li>字母</li><li>下划线_</li><li>美元符号$</li></ul></li></ol><blockquote><p>注意: 字母概念比较宽泛,指的是英文字母,汉子,日语,俄语…,但是我们一般起名字尽量使用英文字母</p></blockquote><ol start="2"><li><p>两个不可以</p><ul><li>不可以以数字开头</li><li>不可以使用java关键字</li></ul></li><li><p>见名知意:增加可读性</p></li><li><p>大小写敏感:int a; int A;</p></li><li><p>遵照驼峰命名:</p><ul><li>类名: 首字母大写,其余遵循驼峰命名</li><li>方法名、变量名:小驼峰</li><li>包名:全部小写,不遵循驼峰命名</li></ul></li><li><p>长度不限制,但不建议太长</p></li></ol>]]></content>
<summary type="html"><p>什么是标识符:包、类、变量、方法…等等,只要是起名字的地方吗,那个名字就是标识符</p></summary>
<category term="JAVA" scheme="https://blog.magicyou.cn/categories/JAVA/"/>
<category term="JAVA" scheme="https://blog.magicyou.cn/tags/JAVA/"/>
</entry>
<entry>
<title>树莓派-内网穿透</title>
<link href="https://blog.magicyou.cn/2020/10/03/%20%E6%A0%91%E8%8E%93%E6%B4%BE-%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F/"/>
<id>https://blog.magicyou.cn/2020/10/03/%20%E6%A0%91%E8%8E%93%E6%B4%BE-%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F/</id>
<published>2020-10-03T13:33:00.000Z</published>
<updated>2020-10-03T13:33:00.000Z</updated>
<content type="html"><![CDATA[<p>树莓派只能在家里玩?当然不是,如何在外网访问家里的树莓派呢?</p><span id="more"></span><p>折腾树莓派,安装了宝塔,有了基本的 web 环境;安装了 homeassistant,没有小米mesh蓝牙网关设备也能在线看到小米温湿度数值;安装了 jenkins,但是不能用各种错误;<br>我想如果不在家也能连上树莓派,有什么方案呢?<br>需要完成这样一个工作:内网穿透。</p><p>参考地址: <a href="https://blog.csdn.net/weixin_44845947/article/details/108160292">https://blog.csdn.net/weixin_44845947/article/details/108160292</a><br>内网穿透有很多种方法,这里主要说以下三种:<br>如果家里有公网IP的话,可以用路由器做映射,进而实现内网穿透;<br>natapp、ngrok等商业化或非商业化内网穿透工具,用的其实是人家的公网IP;<br>买云主机服务器以获得公网IP<br>这三种方法有一个共性就是,要想在公网访问到树莓派,必须要有一个公网的IP,而在这三种方法里,最省钱的无疑是第一种,操作也很简单,最多需要做个动态解析。唯一的问题在于,你很可能没有公网IP,那就无法使用第一种方法了。</p><hr><p>最终选择 frp 内网穿透</p><h2 id="1-下载并部署Frp"><a href="#1-下载并部署Frp" class="headerlink" title="1. 下载并部署Frp"></a>1. 下载并部署Frp</h2><h4 id="下载"><a href="#下载" class="headerlink" title="下载"></a>下载</h4><p><a href="https://github.com/fatedier/frp/releases%EF%BC%8C%E6%89%BE%E5%88%B0%E5%AF%B9%E5%BA%94%E7%9A%84%E7%89%88%E6%9C%AC%EF%BC%8Carm64%E7%89%88%E6%9C%AC%E5%92%8C%E6%99%AE%E9%80%9A%E7%89%88%E6%9C%AC%EF%BC%8C%E5%A6%82%E4%B8%8B%E5%9B%BE%EF%BC%9A">https://github.com/fatedier/frp/releases,找到对应的版本,arm64版本和普通版本,如下图:</a></p><p><img src="https://blog.magicyou.cn/static/img/%E6%A0%91%E8%8E%93%E6%B4%BE-%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F_pic_01.jpg" alt="树莓派-内网穿透_pic_01"></p><h3 id="部署"><a href="#部署" class="headerlink" title="部署"></a>部署</h3><p>分别解压</p><ul><li>将frpc和frpc.ini两个文件传到树莓派上(我放在了/home/pi/目录下)</li><li>frps和frps.ini两个文件放云主机(我放在了/root/目录下)</li></ul><h2 id="2-配置frpc"><a href="#2-配置frpc" class="headerlink" title="2. 配置frpc"></a>2. 配置frpc</h2><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></pre></td><td class="code"><pre><span class="line">[common]</span><br><span class="line">server_addr = XXX.XXX.XXX.XXX</span><br><span class="line">server_port = 7000</span><br><span class="line">privilege_token = 12345678</span><br><span class="line"></span><br><span class="line">log_file = /home/pi/<span class="built_in">log</span>/frpc.log</span><br><span class="line">log_level = info</span><br><span class="line">log_max_days = 3</span><br><span class="line">pool_count = 5</span><br><span class="line">tcp_mux = <span class="literal">true</span></span><br><span class="line"></span><br><span class="line">[ssh]</span><br><span class="line"><span class="built_in">type</span> = tcp</span><br><span class="line">local_ip = 127.0.0.1</span><br><span class="line">local_port = 22</span><br><span class="line">remote_port = 6000</span><br><span class="line"></span><br><span class="line">[vnc]</span><br><span class="line"><span class="built_in">type</span> = tcp</span><br><span class="line">local_ip = 127.0.0.1</span><br><span class="line">local_port = 5900</span><br><span class="line">remote_port = 5901</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>添加日志目录</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">cd /home/pi</span><br><span class="line">mkdir log</span><br><span class="line">cd log</span><br><span class="line">touch frpc.log</span><br></pre></td></tr></table></figure><p>启动frpc</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">./frpc -c ./frpc.ini</span><br></pre></td></tr></table></figure><h2 id="3-配置frps"><a href="#3-配置frps" class="headerlink" title="3. 配置frps"></a>3. 配置frps</h2><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></pre></td><td class="code"><pre><span class="line">[common]</span><br><span class="line">subdomain_host = magicyou.cn</span><br><span class="line">bind_port = 7000</span><br><span class="line">vhost_http_port = 8080</span><br><span class="line">vhost_https_port = 444</span><br><span class="line">dashboard_port = 7500</span><br><span class="line">dashboard_user = user</span><br><span class="line">dashboard_pwd = <span class="built_in">pwd</span></span><br><span class="line">privilege_token = 12345678</span><br><span class="line"></span><br><span class="line">log_file = /root/frps/<span class="built_in">log</span>/frps.log</span><br><span class="line">log_level = info</span><br><span class="line">log_max_days = 3</span><br><span class="line">max_pool_count = 5</span><br><span class="line">authentication_timeout = 900</span><br><span class="line"></span><br><span class="line">tcp_mux = <span class="literal">true</span></span><br></pre></td></tr></table></figure><p>添加日志目录</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">cd /root</span><br><span class="line">mkdir log</span><br><span class="line">cd log</span><br><span class="line">touch frps.log</span><br></pre></td></tr></table></figure><p>启动frps</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">./frps -c ./frps.ini</span><br></pre></td></tr></table></figure><p>注意: privilege_token frps 和 frpc 一致;</p><h2 id="4-端口加入防火墙白名单"><a href="#4-端口加入防火墙白名单" class="headerlink" title="4. 端口加入防火墙白名单"></a>4. 端口加入防火墙白名单</h2><p>以上配置frpc和frps的所有端口都添加入云主机配置的安全组,当然记得在宝塔系统加入端口开放,否则云主机无法和树莓派通信</p><h2 id="5-尝试访问-XXX-XXX-XXX-XXX-7500"><a href="#5-尝试访问-XXX-XXX-XXX-XXX-7500" class="headerlink" title="5. 尝试访问 XXX.XXX.XXX.XXX:7500"></a>5. 尝试访问 XXX.XXX.XXX.XXX:7500</h2><p>输入配置的 dashboard_user,dashboard_pwd;<br><img src="https://blog.magicyou.cn/static/img/%E6%A0%91%E8%8E%93%E6%B4%BE-%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F_pic_02.jpg" alt="树莓派-内网穿透_pic_02"><br><img src="https://blog.magicyou.cn/static/img/%E6%A0%91%E8%8E%93%E6%B4%BE-%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F_pic_03.jpg" alt="树莓派-内网穿透_pic_03"></p><p>可以看到<br><img src="https://blog.magicyou.cn/static/img/%E6%A0%91%E8%8E%93%E6%B4%BE-%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F_pic_04.jpg" alt="树莓派-内网穿透_pic_04"></p><p>到此,内网已经成功穿透,已经可以远程访问家里的树莓派。</p><h2 id="6-添加开机启动项"><a href="#6-添加开机启动项" class="headerlink" title="6. 添加开机启动项"></a>6. 添加开机启动项</h2><p>以云主机 frps 为例。</p><h4 id="创建启动文件"><a href="#创建启动文件" class="headerlink" title="创建启动文件"></a>创建启动文件</h4><figure class="highlight plain"><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">sudo vim /lib/systemd/system/frps.service</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="之后添加下面的内容"><a href="#之后添加下面的内容" class="headerlink" title="之后添加下面的内容"></a>之后添加下面的内容</h4><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><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">[Unit]</span><br><span class="line">Description=frps service</span><br><span class="line">After=network.target network-online.target syslog.target</span><br><span class="line">Wants=network.target network-online.target</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">Type=simple</span><br><span class="line">Restart=on-failure</span><br><span class="line">RestartSec=5s</span><br><span class="line">ExecStart=/root/frps/frps -c /root/frps/frps.ini #对应自己安装的frps路径</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=multi-user.target</span><br></pre></td></tr></table></figure><h4 id="wq保存退出,之后就可以使用如下指令:"><a href="#wq保存退出,之后就可以使用如下指令:" class="headerlink" title="wq保存退出,之后就可以使用如下指令:"></a>wq保存退出,之后就可以使用如下指令:</h4><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><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">sudo systemctl start frps.service#开启frps服务</span><br><span class="line">sudo systemctl enable frps.service#设置开机自启动</span><br><span class="line">sudo systemctl restart frps.service#重启frps</span><br><span class="line">sudo systemctl status frps.service#查看frps状态</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="7-树莓派就顺利的连入了互联网"><a href="#7-树莓派就顺利的连入了互联网" class="headerlink" title="7. 树莓派就顺利的连入了互联网"></a>7. 树莓派就顺利的连入了互联网</h2>]]></content>
<summary type="html"><p>树莓派只能在家里玩?当然不是,如何在外网访问家里的树莓派呢?</p></summary>
<category term="树莓派" scheme="https://blog.magicyou.cn/categories/%E6%A0%91%E8%8E%93%E6%B4%BE/"/>
<category term="树莓派" scheme="https://blog.magicyou.cn/tags/%E6%A0%91%E8%8E%93%E6%B4%BE/"/>
<category term="Linux" scheme="https://blog.magicyou.cn/tags/Linux/"/>
</entry>
<entry>
<title>javascript-单向链表实现</title>
<link href="https://blog.magicyou.cn/2020/08/25/javascript-%E5%8D%95%E5%90%91%E9%93%BE%E8%A1%A8%E5%AE%9E%E7%8E%B0/"/>
<id>https://blog.magicyou.cn/2020/08/25/javascript-%E5%8D%95%E5%90%91%E9%93%BE%E8%A1%A8%E5%AE%9E%E7%8E%B0/</id>
<published>2020-08-25T08:23:56.000Z</published>
<updated>2020-08-26T12:23:56.000Z</updated>
<content type="html"><![CDATA[<p>js 实现一个单向链表</p><span id="more"></span><h4 id="先来复习几个小知识"><a href="#先来复习几个小知识" class="headerlink" title="先来复习几个小知识"></a>先来复习几个小知识</h4><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><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><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br></pre></td><td class="code"><pre><span class="line">class Node {</span><br><span class="line"> constructor(data) {</span><br><span class="line"> this.data = data;</span><br><span class="line"> this.prev = null;</span><br><span class="line"> this.next = null;</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">class SingleList {</span><br><span class="line"> constructor() {</span><br><span class="line"> this.size = 0; // 单链表的长度</span><br><span class="line"> this.head = new Node('head'); // 表头节点</span><br><span class="line"> this.currNode = ''; // 当前节点的指向</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> // 判断单链表是否为空</span><br><span class="line"> isEmpty() {</span><br><span class="line"> return this.size === 0;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> // 获取单链表的最后一个节点</span><br><span class="line"> findLast() {</span><br><span class="line"> let currNode = this.head;</span><br><span class="line"></span><br><span class="line"> while (currNode.next) {</span><br><span class="line"> currNode = currNode.next;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> return currNode;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> // 单链表的遍历显示</span><br><span class="line"> display() {</span><br><span class="line"> let result = '';</span><br><span class="line"> let currNode = this.head;</span><br><span class="line"></span><br><span class="line"> while (currNode) {</span><br><span class="line"> result += currNode.data;</span><br><span class="line"> currNode = currNode.next;</span><br><span class="line"> if (currNode) {</span><br><span class="line"> result += '->';</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> console.log(result);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> // 从当前位置向前移动 n 个节点。</span><br><span class="line"> advance(n, currNode = this.head) {</span><br><span class="line"> this.currNode = currNode;</span><br><span class="line"> while ((n--) && this.currNode.next) {</span><br><span class="line"> this.currNode = this.currNode.next;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> this.remove(currNode.data);</span><br><span class="line"> this.insert(this.currNode.data, currNode.data);</span><br><span class="line"></span><br><span class="line"> return this.currNode;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> // 在单链表中寻找item元素</span><br><span class="line"> find(item) {</span><br><span class="line"> let currNode = this.head;</span><br><span class="line"> while (currNode && (currNode.data !== item)) {</span><br><span class="line"> currNode = currNode.next;</span><br><span class="line"> }</span><br><span class="line"> return currNode;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> // 显示当前节点</span><br><span class="line"> show() {</span><br><span class="line"> console.log(this.currNode.data);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> // 获取单链表的长度</span><br><span class="line"> getLength() {</span><br><span class="line"> return this.size;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> // 向单链表中插入元素</span><br><span class="line"> insert(item, element) {</span><br><span class="line"> let itemNode = this.find(item);</span><br><span class="line"></span><br><span class="line"> if (!itemNode) { // 如果item元素不存在</span><br><span class="line"> return;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> let newNode = new Node(element);</span><br><span class="line"></span><br><span class="line"> newNode.next = itemNode.next; // 若currNode为最后一个节点,则currNode.next为空</span><br><span class="line"> itemNode.next = newNode;</span><br><span class="line"></span><br><span class="line"> this.size++;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> // 在单链表中删除一个节点</span><br><span class="line"> remove(item) {</span><br><span class="line"> if (!this.find(item)) { // item元素在单链表中不存在时</span><br><span class="line"> return;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> // 企图删除头结点</span><br><span class="line"> if (item === 'head') {</span><br><span class="line"> if (!(this.isEmpty())) {</span><br><span class="line"> return;</span><br><span class="line"> } else {</span><br><span class="line"> this.head.next = null;</span><br><span class="line"> return;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> let currNode = this.head;</span><br><span class="line"></span><br><span class="line"> while (currNode.next.data !== item) {</span><br><span class="line"> // 企图删除不存在的节点</span><br><span class="line"> if (!currNode.next) {</span><br><span class="line"> return;</span><br><span class="line"> }</span><br><span class="line"> currNode = currNode.next;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> currNode.next = currNode.next.next;</span><br><span class="line"> this.size--;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> // 在单链表的尾部添加元素</span><br><span class="line"> append(element) {</span><br><span class="line"> let currNode = this.findLast();</span><br><span class="line"> let newNode = new Node(element);</span><br><span class="line"></span><br><span class="line"> currNode.next = newNode;</span><br><span class="line"> this.size++;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> // 清空单链表</span><br><span class="line"> clear() {</span><br><span class="line"> this.head.next = null;</span><br><span class="line"> this.size = 0;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">s</span><br><span class="line"></span><br><span class="line">let myList = new SingleList();</span><br><span class="line">let arr = [3, 4, 5, 6, 7, 8, 9];</span><br><span class="line"></span><br><span class="line">for (let i = 0; i < arr.length; i++) {</span><br><span class="line"> myList.append(arr[i]);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">myList.display(); // head->3->4->5->6->7->8->9</span><br><span class="line"></span><br><span class="line">// const curr = myList.find(3);</span><br><span class="line">// myList.insert(3, 10);</span><br><span class="line">// myList.display();</span><br><span class="line"></span><br><span class="line">// myList.remove(10);</span><br><span class="line">;</span><br><span class="line">// console.log(myList.find(3));</span><br><span class="line">// console.log('===');</span><br><span class="line">console.log(myList.advance(2, myList.find(5)));</span><br><span class="line">;</span><br><span class="line">myList.show();</span><br><span class="line">myList.display();</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><p>js 实现一个单向链表</p></summary>
<category term="JavaScript" scheme="https://blog.magicyou.cn/categories/JavaScript/"/>
<category term="JavaScript" scheme="https://blog.magicyou.cn/tags/JavaScript/"/>
</entry>
<entry>
<title>树莓派-配置免密登录云主机</title>
<link href="https://blog.magicyou.cn/2020/08/03/%20%E6%A0%91%E8%8E%93%E6%B4%BE-%E9%85%8D%E7%BD%AE%E5%85%8D%E5%AF%86%E7%99%BB%E5%BD%95%E4%BA%91%E4%B8%BB%E6%9C%BA/"/>
<id>https://blog.magicyou.cn/2020/08/03/%20%E6%A0%91%E8%8E%93%E6%B4%BE-%E9%85%8D%E7%BD%AE%E5%85%8D%E5%AF%86%E7%99%BB%E5%BD%95%E4%BA%91%E4%B8%BB%E6%9C%BA/</id>
<published>2020-08-03T13:33:00.000Z</published>
<updated>2020-08-03T13:33:00.000Z</updated>
<content type="html"><![CDATA[<p>树莓派频繁登陆腾讯云主机,配置免密登录云主机,省的来回输入密码</p><span id="more"></span><h2 id="知识补充"><a href="#知识补充" class="headerlink" title="知识补充"></a>知识补充</h2><h3 id="1-生成ssh密匙"><a href="#1-生成ssh密匙" class="headerlink" title="1. 生成ssh密匙"></a>1. 生成ssh密匙</h3><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">ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa</span><br></pre></td></tr></table></figure><ul><li>参数说明:<ul><li>-t 加密算法类型,这里是使用rsa算法</li><li>-P 指定私钥的密码,不需要可以不指定</li><li>-f 指定生成秘钥对保持的位置</li></ul></li></ul><h3 id="2-复制SSH密钥到目标主机,开启无密码SSH登录"><a href="#2-复制SSH密钥到目标主机,开启无密码SSH登录" class="headerlink" title="2. 复制SSH密钥到目标主机,开启无密码SSH登录"></a>2. 复制SSH密钥到目标主机,开启无密码SSH登录</h3><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">ssh-copy-id [-i [identity_file]] [user@]machine</span><br></pre></td></tr></table></figure><ul><li>参数说明:<ul><li>-i:指定公钥文件</li></ul></li></ul><h2 id="生成ssh密匙"><a href="#生成ssh密匙" class="headerlink" title="生成ssh密匙"></a>生成ssh密匙</h2><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">ssh-keygen -t rsa</span><br></pre></td></tr></table></figure><p>一路回车</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><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">pi@raspberrypi:~/.ssh $ ssh-keygen -t rsa</span><br><span class="line">Generating public/private rsa key pair.</span><br><span class="line">Enter file in which to save the key (/home/pi/.ssh/id_rsa): </span><br><span class="line">Enter passphrase (empty for no passphrase): </span><br><span class="line">Enter same passphrase again: </span><br><span class="line">Your identification has been saved in /home/pi/.ssh/id_rsa.</span><br><span class="line">Your public key has been saved in /home/pi/.ssh/id_rsa.pub.</span><br><span class="line">The key fingerprint is:</span><br><span class="line">SHA256:fCy8svfejc6O3P7KNvx5xz4b/GT5EizIZbE8IGq0eIU pi@raspberrypi</span><br><span class="line">The key's randomart image is:</span><br><span class="line">+---[RSA 2048]----+</span><br><span class="line">| . |</span><br><span class="line">| E o . . |</span><br><span class="line">| o + . o o |</span><br><span class="line">| . =o . * |</span><br><span class="line">| o S.o+ o |</span><br><span class="line">| +o . + .|</span><br><span class="line">| . . . . *o|</span><br><span class="line">| o.. *+o.=B|</span><br><span class="line">| .. o==@===B|</span><br><span class="line">+----[SHA256]-----+</span><br></pre></td></tr></table></figure><h2 id="copy-公钥到云主机"><a href="#copy-公钥到云主机" class="headerlink" title="copy 公钥到云主机"></a>copy 公钥到云主机</h2><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">ssh-copy-id -i ~/.ssh/id_rsa.pub hostname@host</span><br></pre></td></tr></table></figure><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><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">pi@raspberrypi:~/.ssh $ ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]</span><br><span class="line">/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/pi/.ssh/id_rsa.pub"</span><br><span class="line">/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed</span><br><span class="line">/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys</span><br><span class="line">[email protected]'s password: </span><br><span class="line"></span><br><span class="line">Number of key(s) added: 1</span><br><span class="line"></span><br><span class="line">Now try logging into the machine, with: "ssh '[email protected]'"</span><br><span class="line">and check to make sure that only the key(s) you wanted were added.</span><br></pre></td></tr></table></figure><p>验证</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><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">pi@raspberrypi:~/.ssh $ ssh [email protected]</span><br><span class="line">Last failed login: Thu Mar 18 18:05:56 CST 2021 from 107.175.50.219 on ssh:notty</span><br><span class="line">There were 14 failed login attempts since the last successful login.</span><br><span class="line">Last login: Thu Mar 18 17:54:17 2021 from 120.244.218.59</span><br><span class="line">[root@VM-0-12-centos ~]# </span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><p>树莓派频繁登陆腾讯云主机,配置免密登录云主机,省的来回输入密码</p></summary>
<category term="树莓派" scheme="https://blog.magicyou.cn/categories/%E6%A0%91%E8%8E%93%E6%B4%BE/"/>
<category term="树莓派" scheme="https://blog.magicyou.cn/tags/%E6%A0%91%E8%8E%93%E6%B4%BE/"/>
<category term="Linux" scheme="https://blog.magicyou.cn/tags/Linux/"/>
</entry>
<entry>
<title>javascript复习:变量提升</title>
<link href="https://blog.magicyou.cn/2020/06/30/javascript%E5%A4%8D%E4%B9%A0%EF%BC%9A%E5%8F%98%E9%87%8F%E6%8F%90%E5%8D%87/"/>
<id>https://blog.magicyou.cn/2020/06/30/javascript%E5%A4%8D%E4%B9%A0%EF%BC%9A%E5%8F%98%E9%87%8F%E6%8F%90%E5%8D%87/</id>
<published>2020-06-30T12:24:02.000Z</published>
<updated>2020-06-30T12:24:02.000Z</updated>
<content type="html"><![CDATA[<p>什么是变量提升,为什么会发生变量提升?<br>这个问题还是挺经典的,让我们深度的研究一下。</p><span id="more"></span><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> str = <span class="string">'hello world'</span>;</span><br><span class="line"><span class="built_in">console</span>.log(str);</span><br><span class="line"><span class="comment">// 输出: </span></span><br></pre></td></tr></table></figure><p>以上代码输出 “hello world”,和预期的一样。</p><p>实例 2:</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="built_in">console</span>.log(str2);</span><br><span class="line"><span class="keyword">var</span> str2 = <span class="string">'hello world'</span>;</span><br><span class="line"><span class="comment">// 输出: undefined</span></span><br></pre></td></tr></table></figure><p>代码没报错,输出了 “undefined”,按照正常的代码执行操作,不应该是没有定义 “str2”,会报错的么。问题是出在“var str2 = ‘hello world’;”。这就是javascript的变量提升。</p><h3 id="深入了解一下"><a href="#深入了解一下" class="headerlink" title="深入了解一下"></a>深入了解一下</h3><blockquote><p>“变量提升”意味着变量和函数的声明会在物理层面移动到代码的最前面,但这么说并不准确。实际上变量和函数声明在代码里的位置是不会动的,而是在编译阶段被放入内存中。</p></blockquote><p>”在编译阶段被放入内存“,这句话道出了变量提升的发生原因。实例 2 在打印 ”str2“的时候内存中已经有”str2“,只是只提升了声明,赋值并没有被提前。就像如下例子:</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="built_in">console</span>.log(num); <span class="comment">// Returns undefined</span></span><br><span class="line"><span class="keyword">var</span> num;</span><br><span class="line">num = <span class="number">6</span>;</span><br></pre></td></tr></table></figure><h3 id="表达式与函数声明提升时的差异"><a href="#表达式与函数声明提升时的差异" class="headerlink" title="表达式与函数声明提升时的差异"></a>表达式与函数声明提升时的差异</h3><h4 id="1-函数声明提升时,函数本身也会提升到当前作用域的最前面"><a href="#1-函数声明提升时,函数本身也会提升到当前作用域的最前面" class="headerlink" title="1. 函数声明提升时,函数本身也会提升到当前作用域的最前面"></a>1. 函数声明提升时,函数本身也会提升到当前作用域的最前面</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></pre></td><td class="code"><pre><span class="line">foo() <span class="comment">// 1</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'1'</span>)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="2-函数表达式执行时-只会将变量提升"><a href="#2-函数表达式执行时-只会将变量提升" class="headerlink" title="2. 函数表达式执行时,只会将变量提升"></a>2. 函数表达式执行时,只会将变量提升</h4><p>函数表达式执行时则不然,只会将变量提升,暂赋值undefined,赋值或其他逻辑运行会留在原地</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">foo() <span class="comment">// Uncaught TypeError: foo is not a function, 此时的foo为undefined</span></span><br><span class="line"><span class="keyword">var</span> foo = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'1'</span>)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="javascript-语法为何如此松散凌乱?怎么解决这样的变量提升导致的莫名报错?"><a href="#javascript-语法为何如此松散凌乱?怎么解决这样的变量提升导致的莫名报错?" class="headerlink" title="javascript 语法为何如此松散凌乱?怎么解决这样的变量提升导致的莫名报错?"></a>javascript 语法为何如此松散凌乱?怎么解决这样的变量提升导致的莫名报错?</h3><p>变量提升这个概念只有 js 里才有,可能是语言设计的导致。es6之后,有了新的变量声明关键词”let,const“;</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="built_in">console</span>.log(num); <span class="comment">// Uncaught ReferenceError: num is not defined</span></span><br><span class="line"><span class="keyword">let</span> num;</span><br><span class="line">num = <span class="number">6</span>;</span><br></pre></td></tr></table></figure><p>变量提升”消失“了,”let“ 关键词发挥了作用</p><h3 id="附上一份面试题及答案"><a href="#附上一份面试题及答案" class="headerlink" title="附上一份面试题及答案"></a>附上一份面试题及答案</h3><p>选自 <a href="https://zhuanlan.zhihu.com/p/139644982">https://zhuanlan.zhihu.com/p/139644982</a></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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Foo</span>(<span class="params"></span>) </span>{</span><br><span class="line"> getName = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{ alert (<span class="number">1</span>); };</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>;</span><br><span class="line">}</span><br><span class="line">Foo.getName = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{ alert (<span class="number">2</span>);};</span><br><span class="line">Foo.prototype.getName = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{ alert (<span class="number">3</span>);};</span><br><span class="line"><span class="keyword">var</span> getName = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{ alert (<span class="number">4</span>);};</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getName</span>(<span class="params"></span>) </span>{ alert (<span class="number">5</span>);}</span><br><span class="line"></span><br><span class="line"><span class="comment">//请写出以下输出结果:</span></span><br><span class="line">Foo.getName(); <span class="comment">// 2 => Foo的静态属性getName</span></span><br><span class="line">getName(); <span class="comment">// 4 => 执行全局环境下的getName</span></span><br><span class="line">Foo().getName(); <span class="comment">// 1 <=>window.getName()</span></span><br><span class="line">getName(); <span class="comment">// 1 => 执行全局环境下的getName</span></span><br><span class="line"><span class="keyword">new</span> Foo.getName(); <span class="comment">// 2 => 执行Foo的静态属性getName的构造函数</span></span><br><span class="line"><span class="keyword">new</span> Foo().getName(); <span class="comment">// 3 相当于Foo实例原型上的getName</span></span><br><span class="line"><span class="keyword">new</span> <span class="keyword">new</span> Foo().getName(); <span class="comment">// 3 相当于Foo实例原型上的getName的构造函数</span></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><p>什么是变量提升,为什么会发生变量提升?<br>这个问题还是挺经典的,让我们深度的研究一下。</p></summary>
<category term="JavaScript" scheme="https://blog.magicyou.cn/categories/JavaScript/"/>
<category term="JavaScript" scheme="https://blog.magicyou.cn/tags/JavaScript/"/>
</entry>
<entry>
<title>javascript复习:web安全</title>
<link href="https://blog.magicyou.cn/2020/04/07/javascript%E5%A4%8D%E4%B9%A0%EF%BC%9Aweb%E5%AE%89%E5%85%A8/"/>
<id>https://blog.magicyou.cn/2020/04/07/javascript%E5%A4%8D%E4%B9%A0%EF%BC%9Aweb%E5%AE%89%E5%85%A8/</id>
<published>2020-04-07T13:00:02.000Z</published>
<updated>2020-04-07T13:00:02.000Z</updated>
<content type="html"><![CDATA[<p>web安全: XSS 跨站攻击,XSRF 跨站请求伪造</p><span id="more"></span><p>常见的web 端攻击方式</p><ul><li><p>XSS 跨站攻击<br>即Cross Site Script Execution(通常简写为<a href="https://baike.baidu.com/item/XSS/917356">XSS</a>)是指攻击者利用网站程序对用户输入过滤不足,输入可以显示在页面上对其他用户造成影响的<a href="https://baike.baidu.com/item/HTML%E4%BB%A3%E7%A0%81/1604640">HTML代码</a>,从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。</p></li><li><p>XSRF 跨站请求伪造<br>(英语:Cross-site request forgery),也被称为 <strong>one-click attack</strong> 或者 <strong>session riding</strong>,通常缩写为 <strong>CSRF <strong>或者 <strong>XSRF</strong>, 是一种挟制用户在当前已登录的Web<a href="https://baike.baidu.com/item/%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F/5985445">应用程序</a>上执行非本意的操作的攻击方法。跟<a href="https://baike.baidu.com/item/%E8%B7%A8%E7%BD%91%E7%AB%99%E8%84%9A%E6%9C%AC/23316003">跨网站脚本</a>(XSS)相比,</strong>XSS</strong> 利用的是用户对指定网站的信任,CSRF 利用的是<a href="https://baike.baidu.com/item/%E7%BD%91%E7%AB%99/155722">网站</a>对用户<a href="https://baike.baidu.com/item/%E7%BD%91%E9%A1%B5%E6%B5%8F%E8%A7%88%E5%99%A8/8309940">网页浏览器</a>的信任。</p></li></ul><h3 id="XSS-跨站攻击"><a href="#XSS-跨站攻击" class="headerlink" title="XSS 跨站攻击"></a>XSS 跨站攻击</h3><p>场景</p><ul><li>一个博客网站,我发表一篇文章,其中嵌入 ‘&ltscript&gt’ 脚本</li><li>脚本内容:获取cookie,发送到我的服务器(服务器配合跨域)</li><li>发布这篇博客,有人查看他,我就轻松收割访问者的cookie<br>XSS 预防</li><li>替换特殊字符,如 ‘<’ 变为 ‘<’,‘>’ 变为 ‘>’;</li><li>‘&ltscript&gt’ 变为 ‘ &ltscript>’,直接显示,而不会作为脚本执行</li><li>前端要替换,后端也要替换,都做总不会错</li></ul><h3 id="XSRF攻击"><a href="#XSRF攻击" class="headerlink" title="XSRF攻击"></a>XSRF攻击</h3><p>场景</p><ul><li>你正在购物看中了某个商品,商品id是100</li><li>付费接口是 xxx.com/pay?id=100,但没有任何验证</li><li>我是攻击者。我看中了一个商品,id是200</li><li>我想你的发送一封电子邮件,邮件标题很吸引人</li><li>但邮件正文隐藏着 <img src="xxx.com/pay?id=200" /></li><li>你一查看邮件,就帮我购买了id是 200 的商品</li></ul><p>XSRF 预防</p><ul><li>使用post接口</li><li>增加验证,例如密码,短信验证码,指纹等</li></ul>]]></content>
<summary type="html"><p>web安全: XSS 跨站攻击,XSRF 跨站请求伪造</p></summary>
<category term="JavaScript" scheme="https://blog.magicyou.cn/categories/JavaScript/"/>
<category term="JavaScript" scheme="https://blog.magicyou.cn/tags/JavaScript/"/>
</entry>
<entry>
<title>javascript复习:性能优化</title>
<link href="https://blog.magicyou.cn/2020/04/07/javascript%E5%A4%8D%E4%B9%A0%EF%BC%9A%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/"/>
<id>https://blog.magicyou.cn/2020/04/07/javascript%E5%A4%8D%E4%B9%A0%EF%BC%9A%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/</id>
<published>2020-04-07T12:00:02.000Z</published>
<updated>2020-04-07T12:00:02.000Z</updated>
<content type="html"><![CDATA[<h3 id="性能优化原则"><a href="#性能优化原则" class="headerlink" title="性能优化原则"></a>性能优化原则</h3><ul><li>多食用内存,缓存或其他方法</li><li>减少CPU 计算量,减少网络加载耗时</li><li>(适用于所有编程的性能优化 —- 空间换时间)<span id="more"></span></li></ul><h3 id="从何入手"><a href="#从何入手" class="headerlink" title="从何入手"></a>从何入手</h3><ul><li>让加载更快<ul><li>减少资源体积,压缩代码</li><li>减少访问次数:合并代码,SSR 服务器端渲染,缓存 </li><li>使用更快的网络: CDN</li></ul></li><li>让渲染更快<ul><li>CSS 放在head,JS 放在body 最下面</li><li>尽早开始执行JS,用DOMContentLoaded 触发</li><li>懒加载(图片懒加载,上滑加载更多) </li><li>对 DOM 查询进行缓存</li><li>频繁DOM 操作,合并到一起插入DOM 结构</li><li>节流 throttle,防抖 debounce</li></ul></li></ul><h3 id="缓存"><a href="#缓存" class="headerlink" title="缓存"></a>缓存</h3><ul><li>静态资源加hash后缀,根据文件内容计算hash</li><li>文件内容不变,则hash不变,则url不变</li><li>url 和文件不变,则会自动触发http缓存机制,返回304</li></ul><h3 id="SSR"><a href="#SSR" class="headerlink" title="SSR"></a>SSR</h3><ul><li>服务器端渲染:将网页和数据一起加载,一起渲染</li><li>非SSR(前后端分离):先加载网页,再加载数据,再渲染数据</li><li>早先的 jsp,asp,php,现在的vue React SSR,都是SSR</li></ul><h3 id="防抖-debounce"><a href="#防抖-debounce" class="headerlink" title="防抖 debounce"></a>防抖 debounce</h3><ul><li>监听一个输入框,文字变化后触发change事件</li><li>直接用keyup事件,则会频繁触发change事件</li><li>防抖:用户输入完毕触发change事件<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><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">const input = document.getElementById('input');</span><br><span class="line"></span><br><span class="line">function debounce(fn, delay = 500) {</span><br><span class="line"> // timer 是闭包中的</span><br><span class="line"> let timer = null;</span><br><span class="line"> return function () {</span><br><span class="line"> if (timer) {</span><br><span class="line"> clearTimeout(timer);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> timer = setTimeout(() => {</span><br><span class="line"> fn.apply(this, arguments);</span><br><span class="line"> timer = null;</span><br><span class="line"> }, delay);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">input.addEventListener('keyup', debounce(() => {</span><br><span class="line"> console.log(input.value);</span><br><span class="line">}, 600));</span><br></pre></td></tr></table></figure></li></ul><h3 id="节流-throttle"><a href="#节流-throttle" class="headerlink" title="节流 throttle"></a>节流 throttle</h3><ul><li>拖拽一个元素,要随时拿到该元素被拖拽的位置</li><li>直接用 drag 事件,则会频繁触发,很容易导致卡顿</li><li>节流:无论拖拽速度多快,都会每隔100ms触发一次</li></ul><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><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">const div1 = document.getElementById('div1');</span><br><span class="line">function throttle(fn, delay = 100) {</span><br><span class="line"></span><br><span class="line"> // timer 是闭包中的</span><br><span class="line"> let timer = null;</span><br><span class="line"> return function () {</span><br><span class="line"> if (timer) {</span><br><span class="line"> return;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> timer = setTimeout(() => {</span><br><span class="line"> fn.apply(this, arguments);</span><br><span class="line"> timer = null;</span><br><span class="line"> }, delay);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">div1.addEventListener('drag', throttle((e) => {</span><br><span class="line"> console.log(e);</span><br><span class="line">}, 100));</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><h3 id="性能优化原则"><a href="#性能优化原则" class="headerlink" title="性能优化原则"></a>性能优化原则</h3><ul>
<li>多食用内存,缓存或其他方法</li>
<li>减少CPU 计算量,减少网络加载耗时</li>
<li>(适用于所有编程的性能优化 —- 空间换时间)</summary>
<category term="JavaScript" scheme="https://blog.magicyou.cn/categories/JavaScript/"/>
<category term="JavaScript" scheme="https://blog.magicyou.cn/tags/JavaScript/"/>
</entry>
</feed>