-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
490 lines (235 loc) · 308 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>前端性能优化</title>
<link href="/2020/07/31/%E5%89%8D%E7%AB%AF%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/"/>
<url>/2020/07/31/%E5%89%8D%E7%AB%AF%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/</url>
<content type="html"><![CDATA[<p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200731112441.jpeg" alt="img"></p><p>网站性能的好坏可以说直接决定了用户体验的好坏,而互联网的本质还是为人服务,因此极致的用户体验我想是每个公司都在追求的目标</p><a id="more"></a><p><strong>打开一个 url 地址,浏览器都做了什么,只有理解了做了哪些事情,才知道如何针对优化。</strong></p><p>浏览器能访问的资源都是通过 IP 访问的,但是为了方便我们记忆和使用网站都是使用的域名,所以当我们输入一个域名的时候就需要浏览器进行域名解析。</p><ol><li><strong>缓存中查找</strong></li></ol><p>浏览器缓存中查找(浏览器会缓存 DNS 一段时间)–>系统 host 文件缓存中查找–>路由器缓存中查找–></p><ol start="2"><li><strong>DNS 域名解析</strong></li></ol><p>本地域名服务器–>其他服务器查找(根域名服务器,一级域名服务器,二级域名服务器,三级域名服务器)。</p><p>从而解析到对应的 IP,浏览器主机根据 ip 地址与服务器建立 TCP 连接。</p><ol start="3"><li><strong>TCP 三次握手</strong></li></ol><p>域名解析成功之后,客户端和服务器端就会有三次握手,试探链接,用语义化的语言解释就是。</p><blockquote><p>客户端 —-> 服务器端 你好,我们可以链接吗</p><p>服务器端 —->客户端 可以,你确定要连接是吧?</p><p>客户端—->服务器端 确定,我们链接吧</p></blockquote><ol start="4"><li><strong>发送 http 请求,接收 http 响应</strong></li></ol><p>连接成功之后就可以开始传输数据了,传输数据需要将用户输入的 URL 封装成 HTTP Request 请求报文,发送到服务器,服务器收到请求后会发出应答,即响应数据。</p><ol start="5"><li><p><strong>断开 TCP 连接(4 次挥手)</strong></p><p>客户端—> 服务器端 好了,我们断开连接吧?</p></li></ol><p>服务端—> 客户端 好的,我在检查一哈有没有需要在发给你的信息?</p><p>服务端—> 客户端 好了,我们可以断开连接了</p><p>客户端—> 服务端 好的</p><ol start="6"><li><strong>浏览器解析</strong></li></ol><p>浏览器通过解析<code>HTML</code>,生成 DOM 树,解析<code>CSS</code>,生成 CSS 规则树,然后通过 DOM 树和 CSS 规则树生成渲染树。</p><p>根据渲染树布局,计算 CSS 样式,即每个节点在页面中的大小和位置等几何信息。HTML 默认是<code>流式布局</code>的,<strong>CSS 和 js 会打破这种布局</strong>,改变 DOM 的外观样式以及大小和位置。这时就要提到两个重要概念:repaint(重绘)和 reflow(回流)。</p><blockquote><p>repaint:屏幕的一部分重画,不影响整体布局,比如某个 CSS 的背景色变了,但元素的几何尺寸和位置不变。</p><p>reflow: 意味着元件的几何尺寸变了,我们需要重新验证并计算渲染树。是渲染树的一部分或全部发生了变化。这就是 Reflow,或是 Layout。</p></blockquote><h2 id="性能优化工具-LightHouse"><a href="#性能优化工具-LightHouse" class="headerlink" title="性能优化工具 LightHouse"></a>性能优化工具 LightHouse</h2><blockquote><p>LightHouse 是 Google 开源的一个自动化工具,用于改进网络应用的质量。你可以将其作为一个 Chrome 扩展程序运行,或从命令行运行。 当为 Lighthouse 提供一个要审查的网址,它将针对此页面运行一连串的测试,然后生成一个有关页面性能的报告。可以参考失败的测试,看看可以采取哪些措施来改进应用。</p><p>——谷歌应用商店介绍</p></blockquote><ul><li>首先我们可以到谷歌应用商店安装 LightHouse,点击添加至 Chrome 即可</li><li>如果你的浏览器版本较新的话,可以直接打开 Chrome 开发者工具 (F12),然后打开 Audits 面板即可。Audits 面板就是集成了 LightHouse 功能的面板,我们可以根据自己的需要,选择对应的限制条件,运行 Run audits</li></ul><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200731113042.png" alt="image-20200731113042053"></p><p>点击 run audits 就会自动帮我们生成性能优化报告。</p><p>这里推荐我们使用下一代图片格式化的技术,原因是 JPEG 2000、JPEG XR 和 WebP 等图像格式通常比 PNG 或 JPEG 提供更好的压缩,这意味着更快的下载速度和更少的数据消耗。</p><h2 id="网络部分"><a href="#网络部分" class="headerlink" title="网络部分"></a>网络部分</h2><h3 id="DNS-Prefetch-优化"><a href="#DNS-Prefetch-优化" class="headerlink" title="DNS Prefetch 优化"></a>DNS Prefetch 优化</h3><p><strong>原理</strong></p><p>当我们访问<a href="https://www.baidu.com的时候,首先就需要把域名转化为对应的IP地址,DNS本身的解析是一个非常耗时的过程,打开DNS" target="_blank" rel="noopener">https://www.baidu.com的时候,首先就需要把域名转化为对应的IP地址,DNS本身的解析是一个非常耗时的过程,打开DNS</a> Prefetch 之后,浏览器会在空闲时间提前将这些域名转化为对应的 IP 地址,这里为了防止 DNS Prefetch 阻塞页面渲染影响用户体验,Chrome 浏览器的引擎并没有使用它的网络堆栈去进行预解析,而是单独开了 8 个完全异步的 Worker 线程专门负责 DNS Prefetch。</p><p><strong>如何使用</strong></p><ul><li><p><strong>浏览器自动解析:</strong>浏览器引擎在解析 HTML 页面的时候,会自动获取当前页面所有的 a 标签 herf 属性当中的域名,然后进行 DNS Prefetch。这里需要注意的是如果你的页面是 HTTPS,那么浏览器为了确保安全是不会开启自动解析的,这个时候我们就需要在页面头部添加如下的 meta 标签:</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">meta</span> <span class="attr">http-equiv</span>=<span class="string">"x-dns-prefetch-control"</span> <span class="attr">content</span>=<span class="string">"on"</span> /></span></span><br></pre></td></tr></table></figure><p>如果你不希望浏览器开启自动解析,我们添加如下 meta 标签:</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">meta</span> <span class="attr">http-equiv</span>=<span class="string">"x-dns-prefetch-control"</span> <span class="attr">content</span>=<span class="string">"off"</span> /></span></span><br></pre></td></tr></table></figure></li><li><p><strong>手动解析:</strong>直接添加如下 link 标签即可:</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">link</span> <span class="attr">rel</span>=<span class="string">"dns-prefetch"</span> <span class="attr">href</span>=<span class="string">"//www.baidu.com"</span> /></span></span><br></pre></td></tr></table></figure></li></ul><blockquote><p>DNS Prefetch 通过提前解析我们用到的一些常见域名,大大减少了实际访问时所花费的时间,是一个非常好的解决方案,而且如果你所在的公司有国际化的业务,合理地运用 DNS Prefetch 相信可以带来不错的效果。最后这里要说明一点,DNS Prefetch 的数量不是越多越好,大多数情况下我们设置 3-5 个常用的即可,多了反而会适得其反,毕竟 DNS Prefetch 也是会占用设备宽带。</p></blockquote><h3 id="Webpack-性能优化"><a href="#Webpack-性能优化" class="headerlink" title="Webpack 性能优化"></a>Webpack 性能优化</h3><h4 id="构建速度优化"><a href="#构建速度优化" class="headerlink" title="构建速度优化"></a><strong>构建速度优化</strong></h4><ul><li>npm install 过程中的优化</li></ul><p>现在一个普通的前端项目中就有几百个包,加上每个包都有相关的依赖,可想而知工作量有多大。优化的办法也很简单,就是增加版本描述文件。</p><ul><li>具体仓库地址的选择</li></ul><p>推荐使用淘宝提供的 npm 仓库</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">npm config <span class="keyword">set</span> registry https://registry.npm.taobao.org</span><br></pre></td></tr></table></figure><ul><li>提升 Webpack 构建速度</li></ul><blockquote><p>Webpack 的打包流程</p><p>可以将其理解为一个函数,配置文件则是其参数,传入合理的参数后,运行函数就能得到我们想要的结果。</p></blockquote><ol><li>减少不必要的编译,我们在使用 loader 处理文件的时候,应该尽量把文件范围缩小,对于一些不需要处理的文件直接忽略。</li></ol><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">module</span>: {</span><br><span class="line"> rules: [</span><br><span class="line"> {</span><br><span class="line"> <span class="comment">//处理后缀名为js的文件</span></span><br><span class="line"> test: <span class="regexp">/\.js$/</span>,</span><br><span class="line"> <span class="comment">//exclude去掉不需要转译的第三方包 && 或者这里使用include去声明哪些文件需要被处理</span></span><br><span class="line"> exclude: <span class="regexp">/(node_modules|bower_components)/</span>,</span><br><span class="line"> <span class="comment">//babel的常用配置项</span></span><br><span class="line"> use: {</span><br><span class="line"> loader: <span class="string">"babel-loader"</span>,</span><br><span class="line"> options: {</span><br><span class="line"> presets: [<span class="string">"@babel/preset-env"</span>],</span><br><span class="line"> <span class="comment">//缓存设置为开启</span></span><br><span class="line"> cacheDirectory: <span class="literal">true</span>,</span><br><span class="line"> },</span><br><span class="line"> },</span><br><span class="line"> },</span><br><span class="line"> ];</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>这里我们对于不需要处理的第三方包直接使用 exclude 属性排除在外,或者需要处理的文件使用 include 属性去包含,此外上面我们在 options 配置当中增加了 cacheDirectory: true,这样对于转译结果就可以直接缓存到文件系统当中,在我们下次需要的时候直接到缓存当中读取即可。</p><ol start="2"><li>使用模块热替换(HMR),传统的如果我们没有配置模块热替换,则需要每次刷新整个页面,效率很低。而使用模块热替换之后,我们只需要重新编译发生变化的模块,不需要编译所有模块,速度上面大大提高。具体配置方法如下:</li></ol><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></pre></td><td class="code"><pre><span class="line"><span class="built_in">module</span>.exports = {</span><br><span class="line"> ......</span><br><span class="line"> plugins: [</span><br><span class="line"> <span class="keyword">new</span> webpack.HotModuleReplacementPlugin(), <span class="comment">// 引入模块热替换插件</span></span><br><span class="line"> ],</span><br><span class="line"> devServer: {</span><br><span class="line"> hot: <span class="literal">true</span> <span class="comment">// 开启模块热替换模式</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol start="3"><li><p>由于现在的项目都会引用大量的第三方包,这些包基本都是不会变的,我们完全把他们打包到单独的文件当中,这就涉及到了公共代码的提取,optimization.splitChunks 插件</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">optimization: {</span><br><span class="line"> splitChunks: {</span><br><span class="line"> <span class="comment">//设置那些代码用于分割</span></span><br><span class="line"> chunks: <span class="string">"all"</span>,</span><br><span class="line"> <span class="comment">// 指定最小共享模块数(与CommonsChunkPlugin的minChunks类似)</span></span><br><span class="line"> minChunks: <span class="number">1</span>,</span><br><span class="line"> <span class="comment">// 形成一个新代码块最小的体积</span></span><br><span class="line"> minSize: <span class="number">0</span>,</span><br><span class="line"> cacheGroups: {</span><br><span class="line"> framework: {</span><br><span class="line"> test: <span class="regexp">/lodash/</span>,</span><br><span class="line"> name: <span class="string">"vendor"</span>,</span><br><span class="line"> enforce: <span class="literal">true</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br></pre></td></tr></table></figure></li></ol><h4 id="打包文件质量优化"><a href="#打包文件质量优化" class="headerlink" title="打包文件质量优化"></a>打包文件质量优化</h4><p>如何使打包出的文件尽可能的小,这样我们在加载文件的时候才能更快。</p><p>1.压缩 JavaScript 代码,在压缩 JavaScript 代码的时候我们需要先将代码解析成<a href="https://segmentfault.com/a/1190000016231512?utm_source=tag-newest" target="_blank" rel="noopener">AST 语法树</a>,这个过程计算量非常大,我们常用的插件是 webpack-uglify-parallel 。通过 webpack-uglify-parallel 我们可以将每个资源的压缩过程交给单独的进程,以此来提升整体的压缩效率。这个插件并不在 Webpack 内部,需要我们单独安装。配置方法也比较简单,如下:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> os = <span class="built_in">require</span>(<span class="string">"os"</span>);</span><br><span class="line"><span class="keyword">const</span> UglifyJsParallelPlugin = <span class="built_in">require</span>(<span class="string">"webpack-uglify-parallel"</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">new</span> UglifyJsParallelPlugin({</span><br><span class="line"> <span class="comment">//开启多进程</span></span><br><span class="line"> workers: os.cpus().length,</span><br><span class="line"> mangle: <span class="literal">true</span>,</span><br><span class="line"> compressor: {</span><br><span class="line"> <span class="comment">//忽略警告</span></span><br><span class="line"> warnings: <span class="literal">false</span>,</span><br><span class="line"> <span class="comment">//打开console</span></span><br><span class="line"> drop_console: <span class="literal">true</span>,</span><br><span class="line"> <span class="comment">//打开debugger</span></span><br><span class="line"> drop_debugger: <span class="literal">true</span>,</span><br><span class="line"> },</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>2.压缩 CSS 代码,上面我们介绍了压缩 JavaScript 代码的方法, 同样 CSS 代码同样也可以被压缩。WebPack4.x 我们用 MiniCssExtractPlugin 和 OptimizeCSSAssetsPlugin,具体配置如下:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> OptimizeCSSAssetsPlugin = <span class="built_in">require</span>(<span class="string">"optimize-css-assets-webpack-plugin"</span>);</span><br><span class="line"><span class="keyword">const</span> MiniCssExtractPlugin = <span class="built_in">require</span>(<span class="string">"mini-css-extract-plugin"</span>);</span><br><span class="line"><span class="built_in">module</span>.exports = {</span><br><span class="line"> <span class="built_in">module</span>: {</span><br><span class="line"> rules: [</span><br><span class="line"> {</span><br><span class="line"> test: <span class="regexp">/\.css$/</span>,</span><br><span class="line"> use: [</span><br><span class="line"> MiniCssExtractPlugin.loader, <span class="comment">// 分离css代码</span></span><br><span class="line"> <span class="string">"css-loader"</span>,</span><br><span class="line"> ],</span><br><span class="line"> },</span><br><span class="line"> ],</span><br><span class="line"> },</span><br><span class="line"> plugins: [</span><br><span class="line"> <span class="keyword">new</span> MiniCssExtractPlugin({</span><br><span class="line"> filename: <span class="string">"static/css/[name].[contenthash:8].css"</span>, <span class="comment">//提取css存放目录</span></span><br><span class="line"> }),</span><br><span class="line"> <span class="keyword">new</span> OptimizeCssAssetsPlugin(), <span class="comment">// 使用OptimizeCssAssetsPlugin对CSS进行压缩</span></span><br><span class="line"> ],</span><br><span class="line">};</span><br></pre></td></tr></table></figure><p>3.压缩图片,图片在一般项目当中都是最大的静态资源,所以图片的压缩就显得非常重要。图片压缩插件我们常用的是 imagemin-webpack-plugin。配置较为简单,如下:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> ImageminPlugin = <span class="built_in">require</span>(<span class="string">"imagemin-webpack-plugin"</span>).default;</span><br><span class="line"><span class="built_in">module</span>.exports = {</span><br><span class="line"> plugins: [</span><br><span class="line"> <span class="keyword">new</span> ImageminPlugin({</span><br><span class="line"> pngquant: {</span><br><span class="line"> <span class="comment">//指定压缩后的图片质量</span></span><br><span class="line"> quality: <span class="string">"95-100"</span>,</span><br><span class="line"> },</span><br><span class="line"> }),</span><br><span class="line"> ],</span><br><span class="line">};</span><br></pre></td></tr></table></figure><ol start="4"><li>及时升级你的 Webpack 版本来获得更优的打包速度</li></ol><h3 id="图片优化"><a href="#图片优化" class="headerlink" title="图片优化"></a>图片优化</h3><h4 id="图片格式介绍"><a href="#图片格式介绍" class="headerlink" title="图片格式介绍"></a>图片格式介绍</h4><ul><li><strong>PNG</strong>:是一种无损压缩的位图图形格式,因此 PNG 格式的图片色彩表现力要比其他格式的图片更好,PNG 下又细分为 PNG-8、PNG-24、PNG-32。</li><li><strong>JPG/JPEG</strong>:一种有损压缩的格式,在不影响人们可分辨图片质量的前提下,尽可能的压缩文件的大小,因此图片大小不会太大,图片质量也适中,换句话说,就是可以用最少的磁盘空间得到较好的图像质量。</li><li><strong>GIF</strong>:一种基于 LZW 算法的连续色调的无损压缩格式,应用场景主要是一些动画的展示。</li><li><strong>APNG</strong>:使用多个单张 PNG 连接起来的动画图片格式,支持全透明通道动画。相比于 GIF 动画,没有毛刺,质量更高,色彩效果也更好,而且它的体积相比 GIF 来说也小很多,但目前支持的浏览器并不完全。</li></ul><p><img src="https://img-blog.csdnimg.cn/20200801114411828.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1cGVyS00=,size_16,color_FFFFFF,t_70" alt=""></p><ul><li><p><strong>SVG</strong>:是一种基于 XML 语法的图像格式,全称是可缩放矢量图。SVG 本身是可编程性的语言(支持直接插入 DOM 当中),可被非常多的工具读取和修改。SVG 与 JPEG 和 GIF 图像比起来,尺寸更小,且可压缩性更强,而且 SVG 图像可在任何的分辨率下被高质量地打印,SVG 可在图像质量不下降的情况下被放大,SVG 图像中的文本也是可选的,同时也是可搜索的(很适合制作地图)。</p></li><li><p><strong>WebP</strong>:谷歌开发的一种旨在加快图片加载速度的图片格式,WebP 为网络图片提供了无损和有损压缩能力,同时在有损条件下支持透明通道。据官方实验显示:无损 WebP 相比 PNG 减少 26%大小;有损 WebP 在相同的 SSIM(Structural Similarity Index,结构相似性)下相比 JPG/JPEG 减少 25%~34%的大小;有损 WebP 也支持透明通道,大小通常约为对应 PNG 的 1/3。支持动图能力,并且也占用更小空间,更适应移动网络的动图播放。但是好东西兼容性往往都不好。</p></li><li><p><strong>Base64</strong>:一种基于 64 个可打印字符来表示二进制数据的方法。实际上是一种“二进制到文本”的编码方法,它能够将给定的任意二进制数据转换(映射)为 ASCII 字符串的形式,以便在只支持文本的环境中也能够顺利地传输二进制数据。</p></li><li><p><strong>BPG</strong>: 是一个新的图片格式。用来代替 jpeg 和 webp 的方案,缺点–浏览器对其的支持程度是非常低的,目前还没有大范围使用</p><p><strong>优势</strong></p><ul><li>压缩比高。对于类似的质量,文件比 JPEG 小得多。</li><li>支持与 JPEG(灰度,YCbCr 4:2:0,4:2:2,4:4:4)相同的色度格式,以减少转换过程中的损耗。支持 Alpha 通道。还支持 RGB,YCgCo 和 CMYK 颜色空间。</li><li>支持无损压缩。</li><li>可以包括各种元数据(例如 EXIF,ICC 配置文件,XMP)。</li><li>动画支持。</li><li>相近画质前提下比 webp 更小性能。</li><li>据 mozilla 的研究,bpg 使用的 HEVC 编码比原生的 HEVC 性能更好,因为 BPG 的头部比 HEVC 的头部更小。</li><li>BPG 可以用于硬件上支持 HEVC 编解码器这种图片格式目前还没有被浏览器支持,需要 JavaScript 解码,但其优势非常明显。</li></ul></li></ul><h4 id="优化方法:"><a href="#优化方法:" class="headerlink" title="优化方法:"></a>优化方法:</h4><p><strong>图片懒加载</strong></p><p>图片懒加载是现在最常用的性能优化手段之一,对于首屏用不到的图片,我们完全可以使用懒加载在用户下拉到对应位置的时候再进行加载,避免网页打开时一下子加载过多资源。</p><p><strong>图片渐进显示</strong></p><p>JPEG 还可以细分为 Baseline JPEG(标准型)、Progressive JPEG(渐进式)。</p><p>Baseline JPEG 格式:</p><p><img src="http://img1.sycdn.imooc.com/5d27f7a60001205c03100008.gif" alt="img"></p><p>Progressive JPEG(渐进式):使用了渐进显示</p><p><img src="https://img-blog.csdnimg.cn/20200801120801213.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1cGVyS00=,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p><p>使用 Progressive JPEG 格式图片,直接使用 Photoshop,然后在保存为 JPEG 格式的时候,将连续这个选项勾选即可。</p><h2 id="缓存优化"><a href="#缓存优化" class="headerlink" title="缓存优化"></a>缓存优化</h2><h3 id="CDN-缓存"><a href="#CDN-缓存" class="headerlink" title="CDN 缓存"></a>CDN 缓存</h3><p>CDN 的全称是 Content Delivery Network,即内容分发网络,基本原理是避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容能够传输的更快,更加稳定。</p><p><strong>原理:</strong>通过在各个地方部署相应的服务器,形成 CDN 集群,从而提高访问速度。</p><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200802154615.jpeg" alt="img"></p><p>客户端在获得 IP 地址之后,访问最近的边缘节点。边缘节点是最小的,规模也是最小的,不会缓存所有东西。如果没有找到对应资源就会去它的上一层区域节点去寻找,如果依然没有则去中心节点寻找,如果中心节点也没有,最后再去原网站去访问。这一层一层向上找的过程我们称为<strong>回源</strong>。</p><p><strong>优化方案:</strong></p><ul><li>使用<a href="https://www.bootcdn.cn/" target="_blank" rel="noopener">第三方的 CDN 服务</a>不妨也是一个好的选择。</li><li>CDN 进行静态资源缓存</li><li>直播传送</li></ul><h3 id="本地缓存"><a href="#本地缓存" class="headerlink" title="本地缓存"></a>本地缓存</h3><h4 id="LocalStorage"><a href="#LocalStorage" class="headerlink" title="LocalStorage"></a>LocalStorage</h4><p><strong>优势</strong></p><ul><li>大小方面相比,LocalStorage 突破了 4KB 大小体积限制,一般是 5MB(不同的浏览器大小有所区别),这相当于一个 5MB 大小的数据库提供给我们来使用,我们可以存储更多信息,这方面我们可以有更多的想象;</li><li>LocalStorage 是持久存储,它并不会随着页面的关闭而消失,除非我们主动去清理,不然它会一直在本地,不会过期;</li><li>仅仅存储于本地,不会像 Cookie 那样,每次的 HTTP 请求都会携带。</li></ul><p><strong>劣势</strong></p><ul><li>浏览器兼容性问题,IE 只有在 IE8 以上的版本才会支持;</li><li>如果浏览器设置为隐私模式,那么我们无法读取 LocalStorage;</li><li>LocalStorage 受同源策略的限制,即协议、端口、主机地址有任何一个不同,则无法访问。</li></ul><h4 id="SessionStorage"><a href="#SessionStorage" class="headerlink" title="SessionStorage"></a>SessionStorage</h4><p>SessionStorage 只在当前会话下才会起作用,一旦我们关闭当前的 Tab,SessionStorage 也就失效了。因此,SessionStorage 是一个有时效性的存储方案。</p><p>使用场景:由于 SessionStorage 具有时效性,常用的业务场景比如网站常见的游客登录,就可以存储在 SessionStorage 当中,还有网站的一些临时浏览记录都可以使用 SessionStorage 来进行记录。</p><h4 id="Cookie"><a href="#Cookie" class="headerlink" title="Cookie"></a>Cookie</h4><p>Cookie 的大小最大只有 4KB,而且它是纯文本的文件,我们每次发起 HTTP 请求都会携带 Cookie。</p><p><strong>特性</strong></p><ul><li>Cookie 一旦创建成功,那么名字无法进行修改;</li><li>Cookie 无法跨域名,这是由 Cookie 隐私安全性所决定的,这样能够阻止非法获取其它网站的 Cookie;</li><li>每个单独的域名下面的 Cookie 数量不能超过 20 个。</li></ul><h4 id="IndexedDB"><a href="#IndexedDB" class="headerlink" title="IndexedDB"></a>IndexedDB</h4><p>IndexedDB 是非关系型数据库(类 NOSQL),其实它和我们当下非常流行的 MongoDB 非常相似,我们直接使用 JavaScript 语言就可以直接进行相关的操作,不需要别的语言,大大降低了学习成本。</p><blockquote><p><strong>合理利用缓存是前端工程师的必修课</strong></p></blockquote><h3 id="HTTP-缓存策略"><a href="#HTTP-缓存策略" class="headerlink" title="HTTP 缓存策略"></a>HTTP 缓存策略</h3><p>在概念层面 HTTP 缓存策略又细分为强制缓存和协商缓存</p><p>最完美的效果就是我们发起请求然后取到相应的静态资源。如果服务端的静态资源没有更新,我们就下次访问的时候直接从本地读取即可;如果服务端的静态资源已经更新,那么我们再次请求的时候就要到服务器请求最新的资源,然后进行拉取。</p><h4 id="强制缓存"><a href="#强制缓存" class="headerlink" title="强制缓存"></a>强制缓存</h4><p>强缓存直接从缓存数据库中取出资源,无需再发送请求到服务器上</p><ul><li>*<em>expires *</em></li></ul><p>expires 是 HTTP1.0 的字段,通过指定一个具体的绝对时间值作为缓存资源的过期时间</p><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200802181956.jpeg" alt="img"></p><ul><li><strong>Cache-Control</strong></li></ul><p>Cache-Control 是 HTTP1.1 才有的字段,Cache-Control 设置的是一个相对时间,单位是秒,可以更加精准地控制资源缓存</p><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200802182325.jpeg" alt="img"></p><p>Cache-Control 可设置的字段值较多,下面我们一一来介绍。</p><ul><li>public:设置了该字段值的资源表示可以被任何对象(包括:发送请求的客户端、代理服务器等等)缓存。这个字段值不常用,一般还是使用<strong>max-age=</strong>来精确控制;</li><li>private:设置了该字段值的资源只能被用户浏览器缓存,不允许任何代理服务器缓存。在实际开发当中,对于一些含有用户信息的 HTML,通常都要设置这个字段值,避免代理服务器(CDN)缓存;</li><li>no-cache:设置了该字段需要先和服务端确认返回的资源是否发生了变化,如果资源未发生变化,则直接使用缓存好的资源;</li><li>no-store:设置了该字段表示禁止任何缓存,每次都会向服务端发起新的请求,拉取最新的资源;</li><li>max-age=:设置缓存的最大有效期,单位为秒;</li><li>s-maxage=:优先级高于 max-age=,仅适用于共享缓存(CDN),优先级高于<code>max-age</code>或者<code>Expires</code>头;</li><li>max-stale[=]:设置了该字段表明客户端愿意接收已经过期的资源,但是不能超过给定的时间限制。</li></ul><p>上面就是强制缓存的常用字段,实际开发当中 expires 和 Cache-Control 一般都要进行设置,这是为了兼容不支持 HTTP1.1 的环境。两者同时存在,Cache-Control 的优先级要高于 expires。</p><p><strong>强缓存状态码为<code>200</code></strong></p><ul><li>from memory cache(缓存资源在内存中)</li><li>from disk cache(缓存资源在硬盘中)</li></ul><p><img src="https://img-blog.csdnimg.cn/20200802182647710.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1cGVyS00=,size_16,color_FFFFFF,t_70" alt=""></p><h4 id="协商缓存"><a href="#协商缓存" class="headerlink" title="协商缓存"></a>协商缓存</h4><p>对比缓存是需要经过服务器确认是否使用缓存的机制,其 http 状态码为<code>304</code>,意为<code>not modified</code>。</p><p>如果没有命中强制缓存,如果设置了协商缓存,这个时候协商缓存就会发挥作用了。</p><ul><li><strong>Last-Modified/If-Modified-Since</strong></li></ul><p>最后一次的修改时间,设置方法和我们上面讲的强制缓存的设置方法一样,都是设置一个时间戳,同样它也是由服务端放到 Response Headers 返回给我们</p><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200802183724.png" alt="image-20200802183724257"></p><p>如果有设置协商缓存,我们在首次请求的时候,返回的 Response Headers 会带有 Last-Modified。当再次请求没有命中强制缓存的时候,这个时候我们的 Request Headers 就会携带 If-Modified-Since 字段,它的值就是我们第一次请求返回给我们的 Last-Modified 值。服务端接收到资源请求之后,根据 If-Modified-Since 的字段值和服务端资源最后的修改时间是否一致来判断资源是否有修改。<strong>如果没有修改,则返回的状态码为 304;如果有修改,则返回新的资源,状态码为 200</strong>。</p><p><strong>缺陷</strong></p><ol><li>服务端对 Last-Modified 标注的最后修改时间只能精确到秒级,如果某些文件在 1 秒钟以内被修改多次的话,这个时候服务端无法准确标注文件的修改时间。</li><li>服务端有时候会定期生成一些文件,有时候文件的内容并没有任何变化,但这个时候 Last-Modified 会发生改变,导致文件无法使用缓存。</li></ol><ul><li><strong>Etag/If-None-Match</strong></li></ul><p>通常是根据文件的具体内容计算出一个 hash 值,只要文件的内容不变,它就不会发生改变,保证了唯一性,这一点可以类比人的指纹。</p><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200802184000.png" alt="image-20200802184000092"></p><p>如果我们有设置协商缓存,在首次请求的时候,返回的 Response Headers 会带有 Etag 值。当再次请求没有命中强制缓存的时候,这个时候我们的 Request Headers 就会携带 If-None-Match 字段,它的值就是我们第一次请求返回给我们的 Etag 值。服务端再用 Etag 来进行比较,如果相同就直接使用缓存,如果不同再从服务端拉取新的资源。</p><h4 id="nginx-缓存配置"><a href="#nginx-缓存配置" class="headerlink" title="nginx 缓存配置"></a>nginx 缓存配置</h4><ul><li><strong>expires 和 cache-control</strong></li></ul><p>打开 Nginx 的配置文件 nginx.conf</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><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">// expires:给图片设置过期时间30天,这里也可以设置其它类型文件</span><br><span class="line"><span class="attribute">location</span> <span class="regexp">~ \.(gif|jpg|jpeg|png)$</span> {</span><br><span class="line"> <span class="attribute">root</span> /var/www/img/;</span><br><span class="line"> <span class="attribute">expires</span> <span class="number">30d</span>;</span><br><span class="line">}</span><br><span class="line">// cache-control:给图片设置过期时间36秒,这里也可以设置其它类型文件</span><br><span class="line"><span class="attribute">location</span> <span class="regexp">~ \.(gif|jpg|jpeg|png)$</span> {</span><br><span class="line"> <span class="attribute">root</span> /var/www/img/;</span><br><span class="line"> <span class="attribute">add_header</span> Cache-Control max-age=<span class="number">3600</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li><strong>Last-Modified 和 Etag</strong></li></ul><p>Last-Modified 在 Nginx 当中是默认启用的。</p><p>Etag 需要单独配置</p><p>需要先安装 Etag 模块;安装成功之后,仍然打开 nginx.conf 文件,确保当中没有出现 etgoff,然后添加如下配置,即可开启 Etag:</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><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="attribute">location</span> <span class="regexp">~ .*\.(gif|jpg|jpeg|png)$</span> {</span><br><span class="line"> <span class="attribute">FileETag</span> <span class="literal">on</span>;</span><br><span class="line"> etag_format "%X%X%X"; //这里格式化规则可以修改</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h4 id="webpack-打包缓存配置"><a href="#webpack-打包缓存配置" class="headerlink" title="webpack 打包缓存配置"></a>webpack 打包缓存配置</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="built_in">module</span>.exports = {</span><br><span class="line"> entry: {</span><br><span class="line"> index: <span class="string">'./test/test.js'</span>,</span><br><span class="line"> about: <span class="string">'./test/about.js'</span></span><br><span class="line"> },</span><br><span class="line"> output: {</span><br><span class="line"> <span class="comment">// 打包出来的JavaScript文件用chunkhash</span></span><br><span class="line"> filename: <span class="string">'[name].[chunkhash:8].js'</span>,</span><br><span class="line"> path: path.resolve(__dirname, <span class="string">'dist'</span>)</span><br><span class="line"> },</span><br><span class="line"> <span class="built_in">module</span>: {</span><br><span class="line"> rules: [</span><br><span class="line"> {</span><br><span class="line"> test: <span class="regexp">/\.css$/</span>,</span><br><span class="line"> use: [{<span class="attr">loader</span>: MiniCssExtractPlugin.loader},<span class="string">'css-loader'</span>]</span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> test: <span class="regexp">/\.(png|jpe?g|gif|svg)(\?.*)?$/</span>,</span><br><span class="line"> loader: <span class="string">'file-loader'</span>,</span><br><span class="line"> query: {</span><br><span class="line"> <span class="comment">// 图片文件使用hash</span></span><br><span class="line"> name: <span class="string">'[name].[ext]?[hash]'</span>,</span><br><span class="line"> outputPath: <span class="string">'static/img/'</span>,</span><br><span class="line"> publicPath: <span class="string">'/dist/static/img/'</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> ]</span><br><span class="line"> },</span><br><span class="line"> plugins: [</span><br><span class="line"> <span class="keyword">new</span> CleanWebpackPlugin(),</span><br><span class="line"> <span class="keyword">new</span> MiniCssExtractPlugin({</span><br><span class="line"> <span class="comment">// 抽离的CSS文件用contenthash</span></span><br><span class="line"> filename: <span class="string">'[name].[contenthash:8].css'</span>,</span><br><span class="line"> chunkFilename: <span class="string">'[id].css'</span></span><br><span class="line"> }),</span><br><span class="line"> ]</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="渲染与性能优化"><a href="#渲染与性能优化" class="headerlink" title="渲染与性能优化"></a>渲染与性能优化</h2><p>浏览器的渲染引擎</p><ul><li>IE(Trident)</li><li>Chrome(Blink)</li><li>Firefox(Gecko)</li><li>Opera(Blink)</li><li>Safari(Webkit)</li><li>UC(U3)</li><li>QQ 浏览器微信(X5/Blink)</li></ul><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200802191520.jpeg" alt="img"></p><p>解析 HTML 和解析 CSS 是并行处理的,如果遇到 <code><script></code>标签会停止解析,先执行标签当中 JavaScript;如果是外联方式,也需要等待下载并且执行完对应的 JavaScript 代码,然后才能够继续执行解析 HTML 的工作。</p><h3 id="针对渲染原理进行相关优化"><a href="#针对渲染原理进行相关优化" class="headerlink" title="针对渲染原理进行相关优化"></a>针对渲染原理进行相关优化</h3><h4 id="css-优化"><a href="#css-优化" class="headerlink" title="css 优化"></a>css 优化</h4><p>CSS 解析和 HTML 解析是同步进行的,那么一个 HTML 文档首先解析的肯定是 HTML,然后才是 CSS,这就导致了 HTML 解析完成后,往往需要等待 CSS 解析。如果 CSS 没有解析完成,我们就需要一直等,这里就是 CSS 阻塞了相关的渲染。因此针对这种情况,我们往往把 CSS 样式表全部通过 <code><style></code> 标签内联到网页当中</p><h4 id="js-优化"><a href="#js-优化" class="headerlink" title="js 优化"></a>js 优化</h4><p>JavaScript 既会阻塞 HTML 解析,也会阻塞 CSS 解析。因此我们可以改变 JavaScript 的加载方式或者加载时机来进行优化:</p><ol><li>尽量将 JavaScript 文件放在 body 的底部;</li><li>body 中间尽量不要写 <code><script></code> 标签;</li><li>我们都知道通过 <code><script></code> 标签引入 JavaScript 代码的方式共有 3 种,一个就是直接引入,另外两种分别用添加 async 属性和 defer 属性的方式引入。如果设置为 defer,那么整个 JavaScript 的加载是异步的,并且在 DOMContentLoaded 事件之后才会执行当中的代码;如果设置为 async,整个 JavaScript 的加载是异步的,但是不会阻塞浏览器的任何操作,加载完成后执行相关代码。所以这里的最佳实践是 async 执行时机不确定,不建议用于业务代码,但可用于单独的代码,如第三方统计代码。而 defer 是在 DOMContentLoaded 事件之后执行,所以 defer 一般用于业务代码。</li></ol><h3 id="首屏空白优化"><a href="#首屏空白优化" class="headerlink" title="首屏空白优化"></a>首屏空白优化</h3><p>随着 React、Vue 等框架的流行,SPA 应用越来越多,由于 SPA 应用打包生成的 JavaScript 文件非常大,首屏都是等这个巨大的 JavaScript 文件加载完成之后,才能够开始渲染,这就导致首屏加载必然会出现白屏问题。</p><h4 id="骨架屏"><a href="#骨架屏" class="headerlink" title="骨架屏"></a>骨架屏</h4><p>骨架屏就是我们页面在未完成加载的时候,先用一些简单图形大概勾勒出整个页面,给用户视觉上更好的体验,而不是整个页面都是白屏。等到资源加载完毕,再把骨架屏替换掉即可。整个过程我们用一张图来表示就非常容易理解</p><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200802192923.jpeg" alt="img"></p><p>目前使用比较广泛的是 <a href="https://github.com/ElemeFE/page-skeleton-webpack-plugin" target="_blank" rel="noopener"><strong>page-skeleton-webpack-plugin</strong></a> 这个插件,它是一个 Webpack 插件,可以根据具体的页面生成对应的骨架屏。具体的<a href="https://github.com/ElemeFE/page-skeleton-webpack-plugin" target="_blank" rel="noopener">配置方案</a>这里写得非常详细,这里不再详细罗列,而且它支持动态调试,对于多个页面的使用非常方便。</p><h4 id="使用-Code-Splitting"><a href="#使用-Code-Splitting" class="headerlink" title="使用 Code Splitting"></a><strong>使用 Code Splitting</strong></h4><p>代码分割(Code Splitting)是指将项目代码构建打包(Bundling)后,根据指定规则分割成多个 bundles(输出文件),这些模块文件可以被按需动态加载或者并行加载,可以用来优化代码加载时的资源大小及优先级。正确使用代码分割,可以优化提升资源加载效率。</p><p>使用按需加载。按需加载的方案非常多,最常用的就是使用 ES6 新增的 import() 方法。使用方法也非常简单,我们只需要在我们的路由文件当中引入即可,如下:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> Test1 = <span class="function"><span class="params">()</span> =></span></span><br><span class="line"> <span class="keyword">import</span>(</span><br><span class="line"> <span class="comment">/* webpackChunkName: "Test1" */</span></span><br><span class="line"> <span class="string">"./pages/Test1.vue"</span></span><br><span class="line"> );</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> Test2 = <span class="function"><span class="params">()</span> =></span></span><br><span class="line"> <span class="keyword">import</span>(</span><br><span class="line"> <span class="comment">/* webpackChunkName: "Test2" */</span></span><br><span class="line"> <span class="string">"./pages/Test2.vue"</span></span><br><span class="line"> );</span><br></pre></td></tr></table></figure><p>这里 Webpack 配置的输出也要做对应的修改,如下:</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></pre></td><td class="code"><pre><span class="line"><span class="built_in">module</span>.exports = {</span><br><span class="line"> output: {</span><br><span class="line"> chunkFilename: <span class="string">"[name].chunk.js"</span>,</span><br><span class="line"> },</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h4 id="使用资源预加载"><a href="#使用资源预加载" class="headerlink" title="使用资源预加载"></a><strong>使用资源预加载</strong></h4><p>简单来说就是在当前页面加载完成后或者其它空闲时间,我们可以加载下面页面会用到的资源。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><link rel=<span class="string">"preload"</span> href=<span class="string">"style.css"</span> <span class="keyword">as</span>=<span class="string">"style"</span>></span><br><span class="line"><link rel=<span class="string">"preload"</span> href=<span class="string">"main.js"</span> <span class="keyword">as</span>=<span class="string">"script"</span>></span><br></pre></td></tr></table></figure><p>我们预加载了 CSS 和 JavaScript 文件。所以在随后的页面渲染中,一旦需要使用它们,它们就会立即可用。</p><h3 id="DOM-的优化"><a href="#DOM-的优化" class="headerlink" title="DOM 的优化"></a>DOM 的优化</h3><p>在日常开发当中,不管我们是否使用框架,书写 HTML 是不可避免的,并且操作 DOM 是非常耗费性能的,如果操作错误还会引起回流。</p><ol><li>注意语义化:有利于浏览器解析时间,而且对搜索引擎的抓取也是十分友好的。</li><li>尽量减少无用的标签:不要嵌套多个无用的 div,对一下没有用的 div 要及时删除,能用 CSS 实现的,尽量不要使用相关的 HTML 元素。</li></ol><h3 id="重绘与回流"><a href="#重绘与回流" class="headerlink" title="重绘与回流"></a>重绘与回流</h3><p>回流:当有元素的大小、布局、结构等发生改变时,就会触发回流,每个页面在首次加载的时候都需要进行至少一次回流。</p><p>重绘:有元素属性需要更新,这些属性只是影响元素的外观、风格,那么则会触发重绘。</p><p><strong>如何减少重绘与回流</strong></p><ul><li>避免使用表格布局方法</li><li>减少触发它们操作的次数</li><li>把相关的属性的缓存起来,然后最后在对其进行处理</li><li>修改样式的时候使用类名的方式一次性进行修改,而不是使用 style 的方式</li><li>对一些涉及到复杂动画的元素,在不影响相关布局的情况下,尽量将其 position 属性设置为 absolute 或者 fixed</li></ul><h3 id="Event-Loop"><a href="#Event-Loop" class="headerlink" title="Event Loop"></a>Event Loop</h3><p>JavaScript 是单线程的语言,它在一个时间点只能处理一件事情,完成一件事情之后才可以继续另外一件事情。JavaScript 为了解决这个问题,于是产生了使用异步这种方式来模拟多线程,而支撑异步的就是 Event Loop。</p><p><img src="http://img1.sycdn.imooc.com/5d522d1000013e8c06830503.png" alt="img"></p><ul><li>heap</li></ul><p>heap 是堆这种数据结构,堆其实就是我们平时所说的二叉树,这里存放的主要是 JavaScript 当中的对象,也是 Event Loop 当中一个重要的环节。</p><ul><li>stack</li></ul><p>栈,后进先出,代码执行的时候,会将代码压入栈中进行执行,当任务完成之后,根据栈后进先出的特点,再将各个任务进行出栈。</p><p>假定没有异步任务的情况下 JavaScript 的执行顺序,当我们遇到异步任务,比如:setTimeout、addEventListener 这类异步任务的时候,这个时候异步任务不会直接被压入到栈中,而是会交给浏览器的 Web API 进行维护,当这些异步任务执行完成之后,会在任务队列当中放置对应事件。当执行栈当中任务为空的时候,然后浏览器读取任务队列,再把对应的异步任务压入到执行栈执行,这就是我们经常说的事件循环。</p><ul><li>Macrotask/Microtask</li></ul><p>任务队列 Microtask 优先级是高于 Macrotask 的,Microtask 当中任务不会一个一个压入执行栈,而是所有任务直接压入栈中,当 Microtask 当中的任务执行完毕后,然后我们再从 Macrotask 中取栈顶的第一个任务进行执行。</p><p>那么哪些任务属于 Microtask,哪些任务属于 Macrotask 呢,这里我做了一个大概的总结,如下:</p><p>Macrotask:<code>setTimeout</code>、<code>setInterval</code>、<code>I/O</code>、<code>UI Rendering</code>、<code>script当中的所有代码</code>、<code>setImmediate(Node)</code></p><p>Microtask:<code>process.nextTick(node)</code> 、<code>Promise</code> 、<code>MutationObserver</code></p><p><strong>优化方法</strong></p><p>当开始执行的时候,首先 script 标签当中的代码出 Macrotask,被压入到执行栈执行,这个时候就会有对应的任务被推入 Macrotask 和 Microtask 当中,上面我们已经说过 Microtask 是所有任务一起执行,而 Macrotask 则是任务一个一个执行,那么页面渲染是在 Microtask 之后才进行的,如果我们在异步操作当中进行 DOM 操作,我们尽量将这个操作用 Microtask 当中的任务包一下,这样我们就可以在页面渲染之前就执行这个 DOM 操作了。</p><h3 id="防抖节流"><a href="#防抖节流" class="headerlink" title="防抖节流"></a>防抖节流</h3><p><a href="http://demo.nimius.net/debounce_throttle/" target="_blank" rel="noopener">点击这里</a>可以体验防抖和节流的效果</p><h4 id="节流-throttle"><a href="#节流-throttle" class="headerlink" title="节流(throttle)"></a>节流(throttle)</h4><p>不管你在一段时间内如何不停地触发事件,只要设置了节流,就会每隔一段时间执行一次</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//防抖</span></span><br><span class="line"><span class="keyword">const</span> debounce = <span class="function">(<span class="params">(</span>) =></span> {</span><br><span class="line"> <span class="keyword">let</span> timeout;</span><br><span class="line"> <span class="keyword">return</span> <span class="function">(<span class="params">callback, wait</span>) =></span> {</span><br><span class="line"> <span class="keyword">if</span> (timeout) clearTimeout(timeout);</span><br><span class="line"> timeout = setTimeout(callback, wait);</span><br><span class="line"> };</span><br><span class="line">})();</span><br></pre></td></tr></table></figure><h4 id="防抖-debounce"><a href="#防抖-debounce" class="headerlink" title="防抖(debounce)"></a>防抖(debounce)</h4><p>防抖的原理则是不管你在一段时间内如何不停的触发事件,只要设置了防抖,则只在触发 n 秒后才执行。</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="comment">// 防抖</span></span><br><span class="line"><span class="keyword">const</span> debounce = <span class="function">(<span class="params">(</span>) =></span> {</span><br><span class="line"> <span class="keyword">let</span> timer = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="function">(<span class="params">callback, wait</span>) =></span> {</span><br><span class="line"> clearTimeout(timer);</span><br><span class="line"> timer = setTimeout(callback, wait);</span><br><span class="line"> };</span><br><span class="line">})();</span><br></pre></td></tr></table></figure><h3 id="服务端渲染"><a href="#服务端渲染" class="headerlink" title="服务端渲染"></a>服务端渲染</h3><blockquote><p>服务端渲染在一般场景下其实是无需使用的,虽然它可以解决白屏问题以及 SEO 优化,但是它对服务端要求非常高</p></blockquote><ul><li><strong>客户端渲染(CSR)</strong></li></ul><p>页面初始加载的 HTML 文档中无内容,需要下载执行 JS 文件,由浏览器动态生成页面,并通过 JavaScript 进行页面交互事件与状态管理,这样的页面渲染采用的就是客户端渲染。</p><ul><li><strong>服务端渲染(SSR)</strong></li></ul><p>在服务器端执行一次,用于实现服务器端渲染(首屏直出);在客户端再执行一次,用于接管页面交互。这样页面渲染采用的就是服务端渲染。</p><ul><li><strong>本地离线渲染(NSR)</strong></li></ul><p>通过离线资源和预加载的方式,native 提前完成渲染页面并放入缓存,等用户点击的时候瞬间呈现页面</p>]]></content>
<categories>
<category> 性能优化 </category>
</categories>
<tags>
<tag> 性能优化 </tag>
</tags>
</entry>
<entry>
<title>数据结构与算法</title>
<link href="/2020/07/27/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/"/>
<url>/2020/07/27/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/</url>
<content type="html"><![CDATA[<p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L2doL3N1cGVybGllYmUvcGljR28vMjAyMDA3MjcwOTUxNDIuanBlZw?x-oss-process=image/format,png" alt="img"></p><p>数据结构:数组,链表,栈和队列,散列表,字典,集合,堆,树,图</p><p>算法:冒泡排序,选择排序,快速排序,插入排序,计数排序,基数排序,归并排序,桶排序,堆排序,搜索,动态规划,贪心算法,回溯算法</p><a id="more"></a><p><strong>常见时间复杂度</strong></p><table><thead><tr><th align="left">复杂度</th><th align="left">级别</th><th align="left">描述</th></tr></thead><tbody><tr><td align="left">O(1)<em>O</em>(1)</td><td align="left">常数级</td><td align="left">最优,执行时间不受数据多少限制</td></tr><tr><td align="left">O(log_n)<em>O</em>(<em>l<strong>o</strong>g**n</em>)</td><td align="left">对数级</td><td align="left">相当好,例如:二分查找算法</td></tr><tr><td align="left">O( n )<em>O</em>(<em>n</em>)</td><td align="left">线性级</td><td align="left">还不错,执行时间等于元素个数</td></tr><tr><td align="left">O(n log_nm)<em>O</em>(<em>n<strong>l</strong>o<strong>g</strong>n**m</em>)</td><td align="left">线性对数</td><td align="left">还可以,比上一稍差</td></tr><tr><td align="left">O(n^2)<em>O</em>(<em>n</em>2)</td><td align="left">二次幂</td><td align="left">有点慢,例如:双层for循环</td></tr><tr><td align="left">O(n^3)<em>O</em>(<em>n</em>3)</td><td align="left">三次幂</td><td align="left">特别慢,例如:矩阵乘法</td></tr><tr><td align="left">O(2^n)<em>O</em>(2<em>n</em>)</td><td align="left">指数级</td><td align="left">超级慢,添加一点数据就会将时间拖的特别长</td></tr><tr><td align="left">O!<em>O</em>!</td><td align="left">灾难级</td><td align="left">奇慢无比,例如:旅行商问题</td></tr></tbody></table><p><strong>注</strong>:<strong>算法的时间复杂度是衡量一个算法好坏的重要指标。</strong></p><h2 id="数据结构"><a href="#数据结构" class="headerlink" title="数据结构"></a>数据结构</h2><h3 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h3><p>数组是属于<strong>线性结构</strong>,是顺序存储数据的结构</p><p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L2doL3N1cGVybGllYmUvcGljR28vMjAyMDA3MjcwOTU5MDEuanBlZw?x-oss-process=image/format,png" alt="img"></p><p><strong>数组的优劣和操作的时间复杂度</strong></p><p><strong>优点:更新查找快</strong>,由于数组是线性查存储,所以我们只需要给到我们想要的元素下标,就可以方便的更新元素和查找元素。</p><p><strong>缺点:增删慢</strong>,还是因为数组的线性存储,举个比较简单的例子,比如说我们的书桌上堆放着一摞书,我想要拿第 5 本,我需要动前 4 本才可以拿到想要的。如果书我想把一本书放在中间位置,同样需要动中间位置之前的所有书才可以。”</p><p><strong>时间复杂度:</strong>由于更新查找的时候只需要提供下标,所以时间复杂度是O(1)。增加和删除的时候需要改动数组中的其他元素,所以时间复杂度是O(n)。</p><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">arr.sort(<span class="function">(<span class="params">a,b</span>)=></span> <span class="built_in">Math</span>.random()><span class="number">.5</span>?<span class="number">-1</span>:<span class="number">1</span>)</span><br></pre></td></tr></table></figure><h3 id="链表"><a href="#链表" class="headerlink" title="链表"></a>链表</h3><ol><li>链表是线性结构;</li><li>链表的存储方式是不连续的,是将零散的内存块串联起来;</li><li>每个内存块成为节点 Node,除了存储数据,还需要存储指向下一个内存块的指针;</li><li>存储方式为:以 head 为头节点,头结点可以不存放任何数据,它是链表的开始,指向链表中第一个节点,而每个节点都有一个 next 的向下引用,指向下一个节点,直到最后一个节点。每一个节点由两部分组成,包括 data(存放数据),next(指向下一个节点)。</li></ol><p>常见链表分为以下几种:</p><ul><li>单向链表</li></ul><p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L2doL3N1cGVybGllYmUvcGljR28vMjAyMDA3MjcxMDI5MjkuanBlZw?x-oss-process=image/format,png" alt=""></p><ul><li>单向循环链表</li></ul><p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L2doL3N1cGVybGllYmUvcGljR28vMjAyMDA3MjcxMDI5MjEuanBlZw?x-oss-process=image/format,png" alt=""></p><ul><li>双向列表</li></ul><p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L2doL3N1cGVybGllYmUvcGljR28vMjAyMDA3MjcxMDMwMDYuanBlZw?x-oss-process=image/format,png" alt=""></p><ul><li><p>双向循环列表</p><p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L2doL3N1cGVybGllYmUvcGljR28vMjAyMDA3MjcxMDMwMjYuanBlZw?x-oss-process=image/format,png" alt=""></p></li></ul><p>js链表数据图</p><p><img src="https://img-blog.csdnimg.cn/20200727165241655.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1cGVyS00=,size_16,color_FFFFFF,t_70" alt=""></p><p><strong>链表中的环是什么</strong></p><p>链表中 5 这个节点的后继指针指向了 3 这个节点,所以在 3,4,5 这个区间内形成了一个环状链表。于循环链表不同的是环节点并不是首元结点,所以只能说这个链表中有环,但是不能说这是个循环链表。</p><p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L2doL3N1cGVybGllYmUvcGljR28vMjAyMDA3MjcxNzA2MjMucG5n?x-oss-process=image/format,png" alt=""></p><p>如何判断是否存在环</p><p>定义两个指针从头节点开始遍历链表,如果两个指针有相遇,则说明链表中有环</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">judge</span>(<span class="params">list</span>)</span>{</span><br><span class="line"> <span class="keyword">let</span> fast = list.next.next; <span class="comment">// 快指针,每次走两步</span></span><br><span class="line"> <span class="keyword">let</span> slow = list.next; <span class="comment">// 慢指针,每次走一步</span></span><br><span class="line"> <span class="keyword">while</span>(list){</span><br><span class="line"> <span class="keyword">if</span>(fast === slow) { <span class="comment">// 如果快慢指针相遇,表示有环2</span></span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> }</span><br><span class="line"> fast = fast.next.next;</span><br><span class="line"> slow = slow.next;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="栈和队列"><a href="#栈和队列" class="headerlink" title="栈和队列"></a>栈和队列</h3><p><strong>栈和队列</strong>是计算机科学中使用的比较广泛的两种数据结构,如:程序的递归是使用栈来实现的,操作系统中进程调度网络管理中的打印服务等都是通过队列来实现的。</p><blockquote><p>栈–先入后出</p></blockquote><ol><li>又叫堆栈</li><li>受限操作:<strong>限定只能在表尾进行增加和删除操作。可进行操作的一端成为 栈顶 。不可操作的一端成为 栈底 。</strong></li><li>增加元素的操作又称为<strong>进栈</strong>、<strong>入栈</strong>或者<strong>压栈</strong>。意思是把元素添加到栈顶的位置。</li><li>删除元素的操作又称为<strong>出栈</strong>或者<strong>退栈</strong>。意思是把元素从栈顶移除。使其相邻元素成为栈顶元素。</li></ol><p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L2doL3N1cGVybGllYmUvcGljR28vMjAyMDA3MjcxNzA2MTQuanBlZw?x-oss-process=image/format,png" alt="img"></p><blockquote><p>队列–先入先出</p></blockquote><ol><li>受限操作:<strong>限定只能在表的前端进行删除操作,只能在表的后端进行插入操作。</strong></li><li>进行插入操作的一端称为队尾,进行删除操作的一端称为队头。</li><li>增加元素的操作称为<strong>入队列</strong> ,意思是把元素添加到队尾的位置。</li><li>删除元素的操作称为<strong>出队列</strong> ,意思是把元素从队头位置移除。</li></ol><p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L2doL3N1cGVybGllYmUvcGljR28vMjAyMDA3MjcxNzA1NDMuanBlZw?x-oss-process=image/format,png" alt="img"></p><p><strong>栈溢出</strong></p><p>栈溢出一般指的是,我们定义的数据所需要占用的内存超过了栈的大小时,就会发生栈溢出</p><p>解决方案:尾递归优化</p><p>函数在最后一步调用其他函数,称为尾调用。</p><p><strong>队列溢出</strong></p><ul><li>真溢出</li></ul><p>指的是由于存储空间不够而产生的溢出叫真溢出;</p><p>解决方式:扩容的方式解决。</p><ul><li><p>假溢出</p><p>队列中尚余有足够的空间,但元素却不能入队。一般是由于队列的存储结构或操作方式的选择不当所致。</p></li></ul><p>解决方式:删除元素后将所有元素向前移动一位。</p><blockquote><p>未完待续…</p></blockquote>]]></content>
<categories>
<category> 数据结构 </category>
</categories>
<tags>
<tag> 算法 </tag>
</tags>
</entry>
<entry>
<title>typescript未来可期</title>
<link href="/2020/07/24/typescript%E6%96%87%E6%A1%A3/"/>
<url>/2020/07/24/typescript%E6%96%87%E6%A1%A3/</url>
<content type="html"><![CDATA[<p><img src="https://img-blog.csdnimg.cn/2020072410392078.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1cGVyS00=,size_16,color_FFFFFF,t_70" alt=""></p><p>vue3源码采用了大量ts的写法,掌握ts技巧也是前端进阶的必经之路,肝起来~</p><a id="more"></a><h3 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h3><h4 id="特点"><a href="#特点" class="headerlink" title="特点"></a>特点</h4><ul><li>JavaScript 的超集</li><li>增加了静态类型系统</li><li>为大型软件开发而设计的</li><li>最终编译产生 JavaScript</li></ul><h4 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h4><p>全局安装typetypescript</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">cnpm install -g typescript</span><br></pre></td></tr></table></figure><p>安装成功后使用 <code>tsc -v</code> 查看版本号</p><p><img src="https://img-blog.csdnimg.cn/20200724104450318.png" alt=""></p><p>编译过程</p><ul><li>在后缀名为.ts的文件中编写typescript代码</li><li>使用tsc 将ts文件编译成js代码</li><li>在浏览器中执行或者node中执行</li></ul><h4 id="vscode-自动编译"><a href="#vscode-自动编译" class="headerlink" title="vscode 自动编译"></a>vscode 自动编译</h4><p><strong>点击菜单 终端-运行任务</strong>或者<strong>在vscode中按 Ctrl + Shift + B</strong>,每次保存后就会自动编译成对应的js文件</p><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200724144337.png" alt=""></p><h3 id="ts基础语法"><a href="#ts基础语法" class="headerlink" title="ts基础语法"></a>ts基础语法</h3><h4 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h4><p>指定类型后,该值只能是类型的值。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// let 变量名:变量类型 = 值;</span></span><br><span class="line"><span class="keyword">let</span> name1:string=<span class="string">"张三"</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//如果不定义:string,ts会自动根据值来判断类型</span></span><br><span class="line"><span class="keyword">let</span> name2=<span class="string">"张三"</span>;<span class="comment">//等价于 let name2:string="张三";</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//联合类型</span></span><br><span class="line"><span class="keyword">let</span> name3:string|number = <span class="string">"哈哈"</span></span><br></pre></td></tr></table></figure><h4 id="常见类型"><a href="#常见类型" class="headerlink" title="常见类型"></a>常见类型</h4><ul><li>原有类型</li></ul><p>string、number、 boolean、array、object、null、undefined、symbol</p><ul><li>新增类型</li></ul><p>tuple 元组、enum 枚举 、any 任意类型、never、void</p><h4 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h4><p>元素类型固定</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 方式一:let 数组名:类型[] =[值] </span></span><br><span class="line"><span class="keyword">let</span> arr1:string[] = [<span class="string">"jake"</span>,<span class="string">"lilei"</span>]</span><br><span class="line"></span><br><span class="line"><span class="comment">//方式二:let 数组名:Array<类型>=[值] </span></span><br><span class="line"><span class="keyword">let</span> arr2:<span class="built_in">Array</span><string> = [<span class="string">"jake"</span>,<span class="string">"lilei"</span>]</span><br></pre></td></tr></table></figure><h4 id="元组"><a href="#元组" class="headerlink" title="元组"></a>元组</h4><p>就是一个规定了 元素数量和元素类型的数组,而每个元素的类型可以不一样</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// let 元组名:[类型1,类型2,类型2] = [值1,值2,值2]</span></span><br><span class="line"><span class="keyword">let</span> arr1:[string,number,boolean]=[<span class="string">"啦啦"</span>,<span class="number">10</span>,<span class="literal">true</span>]</span><br></pre></td></tr></table></figure><h4 id="枚举"><a href="#枚举" class="headerlink" title="枚举"></a>枚举</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><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"><span class="comment">/*</span></span><br><span class="line"><span class="comment">enum 枚举名{</span></span><br><span class="line"><span class="comment"> 枚举项1=枚举值1,</span></span><br><span class="line"><span class="comment"> 枚举项2=枚举值2,</span></span><br><span class="line"><span class="comment"> ...</span></span><br><span class="line"><span class="comment">}</span></span><br><span class="line"><span class="comment">枚举项一般用英文,枚举值一般用数字,如果不写枚举值,默认赋值对应的下标0,1,2...</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">enum person{</span><br><span class="line"> man:<span class="number">1</span>,</span><br><span class="line"> woman:<span class="number">2</span>,</span><br><span class="line"> saiban:<span class="number">3</span>,</span><br><span class="line">} </span><br><span class="line"></span><br><span class="line">enum person2{</span><br><span class="line"> man,<span class="comment">//-->0</span></span><br><span class="line"> woman,<span class="comment">//-->1</span></span><br><span class="line"> saiban,<span class="comment">//-->2</span></span><br><span class="line">} </span><br><span class="line"> </span><br><span class="line"><span class="comment">//取值</span></span><br><span class="line"><span class="keyword">let</span> usersex:person = person.man;</span><br></pre></td></tr></table></figure><h4 id="其他数据类型"><a href="#其他数据类型" class="headerlink" title="其他数据类型"></a>其他数据类型</h4><blockquote><p><strong>any</strong> :any代表任意类型,一般在获取dom时使用</p></blockquote><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">let</span> dom:any = <span class="built_in">document</span>.getElementById(<span class="string">"app"</span>)</span><br></pre></td></tr></table></figure><blockquote><p><strong>void</strong>:void 代表没有类型,一版用在无返回值函数。</p></blockquote><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//有返回值</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">say1</span>(<span class="params"></span>):<span class="title">string</span></span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"hello string"</span></span><br><span class="line">}</span><br><span class="line"><span class="keyword">let</span> ref1= say1();</span><br><span class="line"></span><br><span class="line"><span class="comment">//无返回值</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">say2</span>(<span class="params"></span>):<span class="title">void</span></span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"hello void"</span>)</span><br><span class="line">}</span><br><span class="line">say2();</span><br></pre></td></tr></table></figure><blockquote><p><strong>never</strong>:代表不存在的值的类型,常用作抛出异常或者无限循环的函数返回类型</p></blockquote><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">test</span>(<span class="params"></span>):<span class="title">never</span></span>{</span><br><span class="line"> <span class="keyword">while</span>(<span class="literal">true</span>){</span><br><span class="line"> <span class="comment">//无限循环</span></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">test2</span>(<span class="params"></span>):<span class="title">never</span></span>{</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">Error</span>(<span class="string">"hello never"</span>)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>补充:never类型是ts中的底部类型,所有类型都是never类型的子类,所以never类型的值可以赋值给任意类型的变量</p><h4 id="函数"><a href="#函数" class="headerlink" title="函数"></a>函数</h4><p>特点:实参和形参类型必须保持一致</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> 函数名(<span class="params">形参<span class="number">1</span>:类型,形参<span class="number">2</span>:类型</span>):返回值类型</span>{</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> 变量名:变量类型 = 函数名(实参<span class="number">1</span>,实参<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">//可选参数,可传可不传</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> 函数名(<span class="params">形参<span class="number">1</span>?:类型,形参<span class="number">2</span>?:类型</span>):返回值类型</span>{</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//默认参数,不传则使用默认值,如果想要第一个默认,第二个传参则 第一个传undefined即可</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> 函数名(<span class="params">形参<span class="number">1</span>:类型=默认值<span class="number">1</span>,形参<span class="number">2</span>:类型=默认值<span class="number">1</span></span>):返回值类型</span>{</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//剩余参数,只能定义一个,只能定义为数组,只能写在最后</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> 函数名(<span class="params">形参<span class="number">1</span>:类型,形参<span class="number">2</span>:类型,...形参<span class="number">3</span>:类型<span class="number">3</span>[]</span>):返回值类型</span>{</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="类"><a href="#类" class="headerlink" title="类"></a>类</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><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="class"><span class="keyword">class</span> <span class="title">City</span></span>{</span><br><span class="line"> <span class="comment">//成员变量定义在类中</span></span><br><span class="line"> cname:string=<span class="string">""</span>;</span><br><span class="line"> clevel:string=<span class="string">""</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">constructor</span>(name:string,level:string){</span><br><span class="line"> <span class="comment">//构造函数初始化</span></span><br><span class="line"> <span class="keyword">this</span>.cname=name;</span><br><span class="line"> <span class="keyword">this</span>.clevel= level</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"><span class="comment">//成员方法</span></span><br><span class="line">about(){</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`城市:<span class="subst">${<span class="keyword">this</span>.cname}</span>,等级<span class="subst">${<span class="keyword">this</span>.clevel}</span>`</span>)</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> c1 = <span class="keyword">new</span> City(<span class="string">"p1"</span>,<span class="string">"一级"</span>)</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> typescript </category>
</categories>
<tags>
<tag> typescript </tag>
</tags>
</entry>
<entry>
<title>vue3+vite初探</title>
<link href="/2020/07/20/vue3-vite%E5%88%9D%E6%8E%A2/"/>
<url>/2020/07/20/vue3-vite%E5%88%9D%E6%8E%A2/</url>
<content type="html"><![CDATA[<p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200721180042.png" alt="img"></p><a id="more"></a><h3 id="vue3-0的特性"><a href="#vue3-0的特性" class="headerlink" title="vue3.0的特性"></a>vue3.0的特性</h3><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200721180014.png" alt=""></p><ul><li>按需加载 & 组合api</li><li>TS支持,新增 <strong>Fragment(碎片)、Teleport(全局组件)、Suspense(异步加载)</strong></li><li>性能提升 1.3 ~ 2 倍</li><li>基于Proxyx下,去掉属性的定义,根据拦截直接get返回对应结果,性能得到提升</li><li>更新的时候,只需要更新动态的节点,与静态节点解耦,性能得到提升</li></ul><h3 id="vue3-常用api"><a href="#vue3-常用api" class="headerlink" title="vue3 常用api"></a>vue3 常用api</h3><p>官网已经讲解的很详细了,这里略过😝</p><p><strong><a href="https://composition-api.vuejs.org/zh/#概述" target="_blank" rel="noopener">composition api 官方介绍</a></strong></p><p><strong><a href="https://composition-api.vuejs.org/zh/api.html#setup" target="_blank" rel="noopener">vue3 API 手册</a></strong></p><h3 id="vite介绍"><a href="#vite介绍" class="headerlink" title="vite介绍"></a>vite介绍</h3><p>vite(快的意思),是一个http服务器</p><ol><li>可以在单文件中书写es6语法;</li><li>支持热更新(请求的内容才会被打包更新);</li><li>Rollup打包;</li></ol><p><strong>vue-cli版本一定要是最新的,否则容易报错</strong></p><h4 id="vite-和-webpack的区别"><a href="#vite-和-webpack的区别" class="headerlink" title="vite 和 webpack的区别"></a>vite 和 webpack的区别</h4><table><thead><tr><th>功能</th><th>vite</th><th>webpack</th></tr></thead><tbody><tr><td>启动速度</td><td>快 (不需要提前编译、打包,请求到达服务器才编译,浏览器直接支持 es moudle,最大的好处是引用多少编译多少)</td><td>慢(需要先编译build到内存中,发送到服务器的代码需要require模式)</td></tr><tr><td>打包</td><td>使用 rollup打包,加载时使用原生 es import</td><td>将所有模块打包成一个或多个 bundle</td></tr><tr><td>内置热加载</td><td>react-fast-refresh插件(速度几乎瞬间)</td><td>无(速度较慢)</td></tr><tr><td>配置</td><td>开箱即用</td><td>需要复杂的配置</td></tr><tr><td>打包体积</td><td>更小</td><td>小</td></tr></tbody></table><blockquote><p>未完待续…</p></blockquote>]]></content>
<categories>
<category> vue </category>
<category> vite </category>
</categories>
<tags>
<tag> vite </tag>
</tags>
</entry>
<entry>
<title>pwa渐进式webapp</title>
<link href="/2020/07/17/pwa%E6%B8%90%E8%BF%9B%E5%BC%8Fwebapp/"/>
<url>/2020/07/17/pwa%E6%B8%90%E8%BF%9B%E5%BC%8Fwebapp/</url>
<content type="html"><![CDATA[<p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200721180152.png" alt=""></p><p>PWA(Progressive web apps,渐进式 Web 应用)运用现代的 Web API 以及传统的渐进式增强策略来创建跨平台 Web 应用程序, 是Google 在2016年提出的概念,2017年落地的web技术。目的就是在移动端利用提供的标准化框架,在网页应用中实现和原生应用相近的用户体验的渐进式网页应用。</p><a id="more"></a><h3 id="pwa的优势"><a href="#pwa的优势" class="headerlink" title="pwa的优势"></a>pwa的优势</h3><ol><li><strong>渐进式</strong> - 适用于所有浏览器,因为它是以渐进式增强作为宗旨开发的。</li><li><strong>流畅</strong> - 能够借助 service worker 在离线或者网络不好的条件下访问。</li><li><strong>可安装</strong> - 用户可以添加常用的webapp到桌面上,免去去应用商店下载的麻烦。</li><li><strong>原生体验</strong> - 可以和app一样拥有首屏加载动画,可以隐藏地址栏等沉浸式体验。</li><li><strong>粘性</strong> - 通过离线通知,可以让用户回流。</li></ol><h3 id="manifest-应用程序清单的配置"><a href="#manifest-应用程序清单的配置" class="headerlink" title="manifest 应用程序清单的配置"></a>manifest 应用程序清单的配置</h3><p>manifest是一个可配置的json文件,可以使web添加至桌面,设置启动图标,隐藏地址栏等操作</p><ul><li><p>在html文件中引用配置文件</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">link</span> <span class="attr">rel</span>=<span class="string">"manifest"</span> <span class="attr">href</span>=<span class="string">"manifest.json"</span>></span></span><br></pre></td></tr></table></figure></li><li><p>编写 manifest.json 文件</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"name"</span>:<span class="string">"pwa渐进式web"</span>,</span><br><span class="line"> <span class="attr">"short_name"</span>:<span class="string">"pwa"</span>,</span><br><span class="line"> <span class="attr">"icons"</span>:[{</span><br><span class="line"> <span class="attr">"src"</span>: <span class="string">"./image/icon.png"</span>,</span><br><span class="line"> <span class="attr">"sizes"</span>: <span class="string">"144x144"</span>,</span><br><span class="line"> <span class="attr">"type"</span>: <span class="string">"image/png"</span></span><br><span class="line"> }],</span><br><span class="line"> <span class="attr">"background_color"</span>:<span class="string">"#9b59b6"</span>,</span><br><span class="line"> <span class="attr">"theme_color"</span>:<span class="string">"#34495e"</span>,</span><br><span class="line"> <span class="attr">"display"</span>:<span class="string">"standalone"</span>,</span><br><span class="line"> <span class="attr">"start_url"</span>:<span class="string">"/index.html"</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><p> manifest 属性</p><table><thead><tr><th>属性明</th><th>描述</th></tr></thead><tbody><tr><td>name</td><td>用于指定应用的名称和启动画面的文字</td></tr><tr><td>short_name</td><td>应用的短名称,用于主屏显示</td></tr><tr><td>start_url</td><td>指定应用启动加载的页面</td></tr><tr><td>icons</td><td>指定各种环境中作为应用的图标,最佳144x144</td></tr><tr><td>background_color</td><td>启动动画的背景颜色</td></tr><tr><td>theme_color</td><td>应用程序的主题颜色</td></tr><tr><td>display</td><td>fullscreen:全屏显示,不显示状态栏;standalone:更像一个独立的应用程序;minimal-ui:拥有地址显示栏;</td></tr></tbody></table><p>浏览器中就已经可以看到配置信息了</p><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200717174214.png" alt="image-20200717174214643"></p><h3 id="service-worker"><a href="#service-worker" class="headerlink" title="service worker"></a>service worker</h3><ul><li>一个标准的pwa程序必须包含3个部分<ol><li>https 服务器 或者 <a href="http://localhost" target="_blank" rel="noopener">http://localhost</a></li><li>manifest.josn文件</li><li>service worker</li></ol></li><li>service worker 主要用来做持久的离线化缓存;</li><li>service worker 可以极大提升webapp的用户体验;</li><li>service worker 是一个独立的worker线程,独立于网页进程;</li><li>必须在https下才能正常工作;</li><li>一旦被install后必须手动unregister;</li></ul><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200717175058.png" alt="image-20200717175058142"></p><h4 id="生命周期"><a href="#生命周期" class="headerlink" title="生命周期"></a>生命周期</h4><ul><li><p><strong>install</strong> 注册成功时触发,主要用于缓存资源;</p></li><li><p><strong>acvitate</strong> 激活时触发,主要用于删除旧资源;</p></li><li><p><strong>fetch</strong> 发送请求时触发,主要用于操作缓存和读取网络资源;</p></li></ul><h4 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h4><ul><li>在window.onload中注册service worker ,防止与其他资源竞争;</li><li>老的浏览器版本不兼容,需要使用 <code>if('serviceWorker' in navigator){};</code> ;</li><li>注册service worker , navigator.serviceWork.register(‘./sw.js’),返回一个promise对象;</li><li><code>self.skipWaiting()</code>跳过等待,返回一个promise对象;</li><li><code>event.waitUntil()</code> 方法的扩展参数是一个promise对象,会在promise结束后结束当前生命周期函数,防止浏览器在异步操作;</li><li>service worker 激活后,会在下一次刷新页面的时候生效,可以通过<code>self.clients.claim()</code>立即获取控制权;</li></ul><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">// 页面加载完之后,注册serviceWorker</span><br><span class="line"> window.addEventListener('load',async ()=>{</span><br><span class="line"> // 检测是否可用</span><br><span class="line"> if('serviceWorker' in navigator){</span><br><span class="line"> try{</span><br><span class="line"> const registration = await navigator.serviceWorker.register('./sw.js');</span><br><span class="line"> console.log("注册成功",registration)</span><br><span class="line"> }catch(e){</span><br><span class="line"> console.log("注册失败",e)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> });</span><br></pre></td></tr></table></figure><p>sw.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><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//注册</span></span><br><span class="line">self.addEventListener(<span class="string">'install'</span>, event => {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'----install-----'</span>)</span><br><span class="line"> <span class="built_in">console</span>.log(event)</span><br><span class="line"> <span class="comment">//self.skipWaiting 会让service worker 跳过等待直接进入activate</span></span><br><span class="line"> <span class="comment">//event.waitUntil 等待skipWaiting 结束后才进入activate</span></span><br><span class="line"> event.waitUntil(self.skipWaiting()) </span><br><span class="line">});</span><br><span class="line"><span class="comment">//激活</span></span><br><span class="line">self.addEventListener(<span class="string">'activate'</span>, event => {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'----activate-----'</span>)</span><br><span class="line"> <span class="built_in">console</span>.log(event)</span><br><span class="line"> <span class="comment">//service worker 激活后,立即获取控制权</span></span><br><span class="line"> event.waitUntil(self.clients.claim());</span><br><span class="line">});</span><br><span class="line"><span class="comment">//拦截请求</span></span><br><span class="line">self.addEventListener(<span class="string">'fetch'</span>,event => {</span><br><span class="line"> <span class="comment">//可以抓取到所有网络请求</span></span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'----fetch-----'</span>)</span><br><span class="line"> <span class="built_in">console</span>.log( event)</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>刷新浏览器就可以看到控制台上相应生命周期输出的结果</p><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200718174427.png" alt="image-20200718174427487"></p><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200718174524.png" alt="image-20200718174524089"></p><h4 id="fetch-api"><a href="#fetch-api" class="headerlink" title="fetch api"></a>fetch api</h4><p>类似于ajax,专门用于service worker 中请求数据使用 fetch(url,config)</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></pre></td><td class="code"><pre><span class="line">fetch(<span class="string">"/api/..."</span>).then(<span class="function"><span class="params">res</span>=></span>{</span><br><span class="line"> <span class="comment">//res得到的事响应式内容,是一个二进制流</span></span><br><span class="line"> <span class="comment">//调用res.json 可以把数据转化为可读的json格式</span></span><br><span class="line"> <span class="keyword">return</span> res.json()</span><br><span class="line">}).then(<span class="function"><span class="params">data</span>=></span>{</span><br><span class="line"> <span class="built_in">console</span>.log(data)</span><br><span class="line">})</span><br></pre></td></tr></table></figure><h4 id="notification-通知"><a href="#notification-通知" class="headerlink" title="notification 通知"></a>notification 通知</h4><p>通过推送告诉用户某信息,比如断网/联网的时候要通知到用户,提升用户体验。</p><p><strong>Notification.permission</strong> 可以获取到当前用户通知 的权限</p><ul><li>defalut 默认,未授权</li><li>denied 拒绝授权,无法再次请求授权,无法弹出窗口</li><li>granted 通过授权</li></ul><p><strong>Notification.requestPremission()</strong> 可以请求用户授权。</p><p><strong>new Notification(‘提示的标题’,{body:’提示的内容’,icon:’提示的图标’})</strong> 可以显示通知。</p><p> <img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200718194421.png" alt="image-20200718194420948"></p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//如果一进来我们发现用户没有联网就给用户一个通知</span></span><br><span class="line"><span class="keyword">if</span>(Notification.permission==<span class="string">'defalut'</span>){</span><br><span class="line"> <span class="comment">//授权开启通知</span></span><br><span class="line"> Notification.requestPermission();</span><br><span class="line">}</span><br><span class="line"><span class="keyword">if</span>(!navigator.onLine){</span><br><span class="line"> <span class="comment">//断网</span></span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"断网"</span>)</span><br><span class="line"> <span class="keyword">new</span> Notification(<span class="string">"提示"</span>,{<span class="attr">body</span>:<span class="string">'网络已断开,您访问的是缓存'</span>,<span class="attr">icon</span>:<span class="string">'/image/icon.png'</span>})</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">window</span>.addEventListener(<span class="string">"online"</span>,()=>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"网络已连接"</span>)</span><br><span class="line"> <span class="keyword">new</span> Notification(<span class="string">"提示"</span>,{<span class="attr">body</span>:<span class="string">'网络已连接,请刷新页面获取新的数据'</span>,<span class="attr">icon</span>:<span class="string">'/image/icon.png'</span>})</span><br><span class="line">})</span><br></pre></td></tr></table></figure><h4 id="cache-storage"><a href="#cache-storage" class="headerlink" title="cache storage"></a>cache storage</h4><p>配合service worker 来实现缓存</p><p><strong>caches.api 常用方法</strong></p><ol><li><code>caches.open(cachesName).then(res=>{})</code> 用户打开一个缓存,返回一个匹配cachesNam的catch对象promise,类似于链接数据库操作;</li><li><code>caches.keys()</code> 返回一个promise对象,包括所有缓存的key (数据库名) ;</li><li><code>caches.delete(key)</code> 根据key删除对应的缓存;</li></ol><p><strong>cache 常用方法(单条数据操作)</strong></p><ol><li><code>cache.put(req,res)</code> 把请求当key,并把对应的相应存储起来;</li><li><code>cache.add(url)</code> 根据url发起请求,并把相应结果存储起来;</li><li><code>cache.addAll(url)</code> 抓取一个url数组,并把结果都存起来;</li><li><code>cache.match(req)</code> 获取req对应的response;</li></ol><p><strong>通过caches api 来实现读取离线缓存</strong></p><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200721180228.png" alt="U29h1H.png"></p><p>html中引入对应的资源文件,在页面加载完之后,注册serviceWorker。</p><p>sw.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><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//注册,主要缓存内容</span></span><br><span class="line"><span class="keyword">const</span> CACHE_NAME = <span class="string">'cache_3'</span>; <span class="comment">//定义存储缓存的名字--类似数据库</span></span><br><span class="line"><span class="keyword">const</span> CACHE_URL = [</span><br><span class="line"> <span class="string">'/'</span>,</span><br><span class="line"> <span class="string">'/image/icon.png'</span>,</span><br><span class="line"> <span class="string">'/manifest.json'</span>,</span><br><span class="line"> <span class="string">'/index.css'</span></span><br><span class="line">]</span><br><span class="line">self.addEventListener(<span class="string">'install'</span>, <span class="keyword">async</span> event => {</span><br><span class="line"> <span class="comment">//开启cache缓存,类似连接数据库</span></span><br><span class="line"> <span class="keyword">const</span> cache = <span class="keyword">await</span> caches.open(CACHE_NAME);</span><br><span class="line"> <span class="comment">//cache 添加需要缓存的资源,使用await 等待把所有缓存存起来再进行</span></span><br><span class="line"> <span class="keyword">await</span> cache.addAll(CACHE_URL)</span><br><span class="line"> <span class="comment">//跳过等待直接进入activate</span></span><br><span class="line"> <span class="keyword">await</span> self.skipWaiting();</span><br><span class="line">});</span><br><span class="line"><span class="comment">//激活,主要清除缓存</span></span><br><span class="line">self.addEventListener(<span class="string">'activate'</span>, <span class="keyword">async</span> event => {</span><br><span class="line"> <span class="comment">//获取到左右资源的key</span></span><br><span class="line"> <span class="keyword">const</span> keys = <span class="keyword">await</span> caches.keys()</span><br><span class="line"> keys.forEach(<span class="function"><span class="params">key</span> =></span> {</span><br><span class="line"> <span class="keyword">if</span> (key != CACHE_NAME) {</span><br><span class="line"> <span class="comment">//旧资源</span></span><br><span class="line"> caches.delete(key)</span><br><span class="line"> }</span><br><span class="line"> })</span><br><span class="line"> <span class="comment">//service worker 激活后,立即获取控制权</span></span><br><span class="line"> <span class="keyword">await</span> self.clients.claim();</span><br><span class="line">});</span><br><span class="line"><span class="comment">//监听请求,判断资源是否能够请求成功,成功则取相应结果,断网则取缓存内容</span></span><br><span class="line">self.addEventListener(<span class="string">'fetch'</span>, <span class="keyword">async</span> event => {</span><br><span class="line"> <span class="comment">//请求对象</span></span><br><span class="line"> <span class="keyword">const</span> req = event.request;</span><br><span class="line"> <span class="comment">//只缓存同源内容</span></span><br><span class="line"> <span class="keyword">const</span> url = <span class="keyword">new</span> URL(req.url);</span><br><span class="line"> <span class="keyword">if</span> (url.origin !== location.origin) {</span><br><span class="line"> <span class="keyword">return</span></span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//给浏览器相应,</span></span><br><span class="line"> <span class="keyword">if</span> (req.url.includes(<span class="string">"/api"</span>)) {</span><br><span class="line"> <span class="comment">//资源走网络优先</span></span><br><span class="line"> event.respondWith(networkFirst(req))</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">//资源走缓存优先</span></span><br><span class="line"> event.respondWith(cacheFrist(req))</span><br><span class="line"> }</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="comment">//网络优先</span></span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">networkFirst</span>(<span class="params">req</span>) </span>{</span><br><span class="line"> <span class="comment">//取缓存中读取</span></span><br><span class="line"> <span class="keyword">const</span> cache = <span class="keyword">await</span> caches.open(CACHE_NAME);</span><br><span class="line"> <span class="comment">//先从网络获取资源</span></span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">const</span> fresh = <span class="keyword">await</span> fetch(req);</span><br><span class="line"> <span class="comment">//获取到的数据应该再次更新到缓存当中,把响应的备份存到缓存当中</span></span><br><span class="line"> cache.put(req,fresh.clone())</span><br><span class="line"> <span class="keyword">return</span> fresh</span><br><span class="line"> } <span class="keyword">catch</span> (e) {</span><br><span class="line"> <span class="comment">//匹配与req对应的资源</span></span><br><span class="line"> <span class="keyword">const</span> cached = <span class="keyword">await</span> cache.match(req);</span><br><span class="line"> <span class="keyword">return</span> cached</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//缓存优先</span></span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">cacheFrist</span>(<span class="params">req</span>) </span>{</span><br><span class="line"> <span class="comment">//打开缓存</span></span><br><span class="line"> <span class="keyword">const</span> cache = <span class="keyword">await</span> caches.open(CACHE_NAME);</span><br><span class="line"> <span class="comment">//取出对应数据</span></span><br><span class="line"> <span class="keyword">const</span> cached = <span class="keyword">await</span> cache.match(req)</span><br><span class="line"> <span class="keyword">if</span> (cached) {</span><br><span class="line"> <span class="comment">//如果从缓存中得到了,直接返回缓存</span></span><br><span class="line"> <span class="keyword">return</span> cached</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">const</span> fresh = <span class="keyword">await</span> fetch(req);</span><br><span class="line"> <span class="keyword">return</span> fresh</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>打开控制台,application中即可看到被缓存的文件。</p><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200721180219.png" alt="U2C9H0.png"></p><p>勾选network中的 offline online来关闭网络, 刷新页面会发现,即使断网的情况洗也可以访问到正常的数据。</p>]]></content>
<categories>
<category> pwa </category>
</categories>
<tags>
<tag> pwa </tag>
</tags>
</entry>
<entry>
<title>docker镜像发布到dockerhub和阿里云</title>
<link href="/2020/07/11/docker%E9%95%9C%E5%83%8F%E5%8F%91%E5%B8%83/"/>
<url>/2020/07/11/docker%E9%95%9C%E5%83%8F%E5%8F%91%E5%B8%83/</url>
<content type="html"><![CDATA[<p>docker 镜像发布,一般使用以下两种情况</p><a id="more"></a><h3 id="发布前准备"><a href="#发布前准备" class="headerlink" title="发布前准备"></a>发布前准备</h3><ol><li><p>创建自己的 dockerhub 账号,<a href="https://hub.docker.com" target="_blank" rel="noopener">dockerhub 官网</a>。</p></li><li><p>在服务器上提交镜像。</p></li></ol><h3 id="docker-镜像发布到-dockerhub"><a href="#docker-镜像发布到-dockerhub" class="headerlink" title="docker 镜像发布到 dockerhub"></a>docker 镜像发布到 dockerhub</h3><ul><li>首先登录 dockerhub</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker login -u 用户名</span><br><span class="line"></span><br><span class="line"><span class="comment">#然后输入密码,提示登录成功</span></span><br></pre></td></tr></table></figure><ul><li>登陆完毕后就可以提交镜像了。</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker push 作者名/镜像名:版本号</span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果当前版本为latest,需要使用 docker tag 镜像id 1.0 修改版本号</span></span><br></pre></td></tr></table></figure><p>提交的时候也是按照镜像层级来提交的</p><h3 id="docker-镜像发布到-阿里云"><a href="#docker-镜像发布到-阿里云" class="headerlink" title="docker 镜像发布到 阿里云"></a>docker 镜像发布到 阿里云</h3><ol><li>登陆阿里云</li><li>找到容器镜像服务</li><li>创建命名空间<br><img src="https://s1.ax1x.com/2020/07/12/U1U3pn.png" alt=""></li><li>创建镜像仓库<br><img src="https://s1.ax1x.com/2020/07/12/U1Us6x.png" alt=""></li><li>点击管理,可以查看详细的操作步骤,按照操作提示来登录,推送景象即可<br><img src="https://s1.ax1x.com/2020/07/12/U1aScq.png" alt=""></li></ol>]]></content>
<categories>
<category> docker </category>
</categories>
<tags>
<tag> docker </tag>
</tags>
</entry>
<entry>
<title>dockefile的使用</title>
<link href="/2020/07/09/dockerfile%E7%9A%84%E4%BD%BF%E7%94%A8/"/>
<url>/2020/07/09/dockerfile%E7%9A%84%E4%BD%BF%E7%94%A8/</url>
<content type="html"><![CDATA[<p><img src="https://s1.ax1x.com/2020/07/09/UnyB0U.png" alt=""></p><a id="more"></a><p>docker 是用来构建 docker 镜像文件,命令参数的脚本。</p><p>构建步骤</p><ol><li>编写一个 dockerfile 文件。</li><li>docker build 构建成为一个镜像。</li><li>docker run 运行镜像。</li><li>docker push 发布镜像(dockerhub , 阿里云仓库)。</li></ol><p>很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!</p><h3 id="dockerfile-的构建过程"><a href="#dockerfile-的构建过程" class="headerlink" title="dockerfile 的构建过程"></a>dockerfile 的构建过程</h3><p><strong>基础知识</strong></p><ol><li>每个指令都必须是大写字母。</li><li>执行从上到下顺序执行。</li><li>#表示注释</li><li>每个指令都会创建一个新的镜像层并提交。</li></ol><p><img src="https://s1.ax1x.com/2020/07/09/UnWytO.png" alt=""></p><p>docker 镜像逐渐成为企业交付的标准,所以你懂的。</p><p>DockerFile: 构建文件,定义了一切的步骤,源代码</p><p>DockerImages : 通过 DockerFile 构建生成的镜像,最终发布和运行的产品!</p><p>Docker 容器 : 容器就是镜像运行起来提供服务</p><h3 id="dockerfile-指令"><a href="#dockerfile-指令" class="headerlink" title="dockerfile 指令"></a>dockerfile 指令</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">FROM <span class="comment">#基础镜像,一切从这里开始构建</span></span><br><span class="line">MAINTAINER (maintainer) <span class="comment">#镜像是谁写的,姓名+邮箱</span></span><br><span class="line">RUN <span class="comment">#镜像构建的时候需要运行的命令</span></span><br><span class="line">ADD <span class="comment">#添加内容,如添加一个tomcat的压缩包</span></span><br><span class="line">WORKDIR <span class="comment">#镜像的工作目录</span></span><br><span class="line">VOLUME <span class="comment">#挂载的目录</span></span><br><span class="line">EXPOST <span class="comment">#暴露端口配置</span></span><br><span class="line">CMD <span class="comment">#指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代!</span></span><br><span class="line">ENTRYPOINT (entrypoint) <span class="comment">#指定这个容器启动的时候要运行的命令,可以追加命令!</span></span><br><span class="line">ONBUILD <span class="comment">#当构建一个被继承 DockerFile 这个时候就会运行 ONBUILD 的指令,触发指令!</span></span><br><span class="line">COPY <span class="comment"># 类似ADD ,将文件拷贝到镜像中!</span></span><br><span class="line">ENV <span class="comment"># 构建的时候设置环境变量!</span></span><br></pre></td></tr></table></figure><h3 id="实战测试"><a href="#实战测试" class="headerlink" title="实战测试"></a>实战测试</h3><p>Docker Hub 中 99% 的镜像都是从 FROM scratch 这个基础镜像过来的!然后配置需要的软件和配置来进行构建</p><blockquote><p>创建一个自己的centos</p></blockquote><ul><li>在 home 目录中创建 dockerfile 文件夹,<code>vim mydockerfile</code> ,编写dockerfile文件 </li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 编写dockersfile文件</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#基于centos基础环境</span></span><br><span class="line">FROM centos</span><br><span class="line">MAINTAINER superkm<[email protected]></span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置环境变量</span></span><br><span class="line">ENV MYPATH /user/<span class="built_in">local</span> <span class="comment">#默认进入的目录</span></span><br><span class="line">WORKDIR <span class="variable">$MYPATH</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 执行安装的一些命令</span></span><br><span class="line">RUN yum -y install vim</span><br><span class="line">RUN yum -y install net-tools</span><br><span class="line"></span><br><span class="line"><span class="comment">#暴漏的端口</span></span><br><span class="line">EXPOSE 80</span><br><span class="line"></span><br><span class="line"><span class="comment">#输出信息,默认进入命令行</span></span><br><span class="line">CMD <span class="built_in">echo</span> <span class="variable">$MYPATH</span></span><br><span class="line">CMD <span class="built_in">echo</span> <span class="string">"---end---"</span></span><br><span class="line">CMD /bin/bash</span><br></pre></td></tr></table></figure><ul><li>构建镜像</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">docker build -f mydockerfile -t mycentos:0.1 .</span><br><span class="line"></span><br><span class="line"><span class="comment"># -f dockerfile脚本文件</span></span><br><span class="line"><span class="comment"># -t 生成目标镜像且生成到当前目录下,注意最后有个 .</span></span><br><span class="line"><span class="comment"># 构建成功的提示</span></span><br><span class="line"><span class="comment"># Successfully built 3c490273278b</span></span><br><span class="line"><span class="comment"># Successfully tagged mycentos:0.1</span></span><br></pre></td></tr></table></figure><p>测试运行,正常使用</p><p>我们拿到一个镜像,可以研究它是怎么做的</p><p>列出镜像的变更历史 <code>docker history 镜像id</code></p>]]></content>
<categories>
<category> docker </category>
</categories>
<tags>
<tag> docker </tag>
</tags>
</entry>
<entry>
<title>git常用命令</title>
<link href="/2020/07/01/git%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/"/>
<url>/2020/07/01/git%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/</url>
<content type="html"><![CDATA[<p><img src="https://s1.ax1x.com/2020/07/01/NTLLsf.jpg" alt="常用 git 命令"></p>]]></content>
<categories>
<category> git </category>
</categories>
<tags>
<tag> git </tag>
</tags>
</entry>
<entry>
<title>npm发布vue组件包(可扩展)</title>
<link href="/2020/06/29/npm%E5%8F%91%E5%B8%83%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%8C%85/"/>
<url>/2020/06/29/npm%E5%8F%91%E5%B8%83%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%8C%85/</url>
<content type="html"><![CDATA[<p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200721180309.jpeg" alt=""></p><p>😶 NPM 是随同 NodeJS 一起安装的 javascript 包管理工具,能解决 NodeJS 代码部署上的很多问题</p><a id="more"></a><h3 id="发布前的准备"><a href="#发布前的准备" class="headerlink" title="发布前的准备"></a>发布前的准备</h3><p><strong>注册一个 npm 账号</strong></p><p><a href="https://www.npmjs.com" target="_blank" rel="noopener">前往 NPM 官网进行注册</a></p><h3 id="初始化项目"><a href="#初始化项目" class="headerlink" title="初始化项目"></a>初始化项目</h3><p>这里用的是<code>webpack-simple</code>,可以理解为精简版的<code>vue-cli</code>。</p><p>如果没有全局安装 vue 的话,需要先安装</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">cnpm i -g @vue/cli-init</span><br></pre></td></tr></table></figure><p>然后再初始化 vue 项目,我们要写的是一个简单的 vue 组件,不需要依赖那么多而庞大的配置,所以,这里我们用简介版本的 webapck 配置模板</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">vue init webpack-simple 项目名(最好去npm官网搜一下,防止重复)</span><br></pre></td></tr></table></figure><p>创建之后的基本目录<br><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200721180243.png" alt=""></p><h3 id="创建-vue-插件并发布"><a href="#创建-vue-插件并发布" class="headerlink" title="创建 vue 插件并发布"></a>创建 vue 插件并发布</h3><h4 id="创建组件文件夹"><a href="#创建组件文件夹" class="headerlink" title="创建组件文件夹"></a>创建组件文件夹</h4><p><strong>举个例子:封装一个返回顶部的小组件</strong></p><p>既然是封装组件,那我们在 src 下面创建一个 plugins 文件放我们的插件,但是考虑到万一要写很多个的情况,当前组件的相关文件下创建一个 returnTop 文件夹,下面创建 returnTop.vue 和 index.js 先,结构变成下面这样:</p><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200721180248.png" alt=""></p><p>切换到当前根目录,安装依赖,启动项目</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cnpm install</span><br><span class="line"></span><br><span class="line">cnpm run dev</span><br></pre></td></tr></table></figure><h4 id="编写组件代码"><a href="#编写组件代码" class="headerlink" title="编写组件代码"></a>编写组件代码</h4><p>示例代码<br>returnTop.vue</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><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></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">"right-return-top"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"return-top"</span> @<span class="attr">click</span>=<span class="string">"returnTop"</span> <span class="attr">v-show</span>=<span class="string">"topShow"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">img</span></span></span><br><span class="line"><span class="tag"> <span class="attr">src</span>=<span class="string">"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAAHdbkFIAAAACXBIWXMAAAsSAAALEgHS3X78AAADGUlEQVR4nO2aT2vTYBzHv0/S9aKw7rJz34E5mP6zrRmOjeFgKozBcFAZwkAc6sHrttNgUBBPA5HNi5eBsJPX1k1XT9p3UF/B+g4iadI2ydI0T9P0SfX3hZDmeZI8n9/3efL8acJ0XYefJN/cICckHEfLGR3zCWB+BqjWWSfNYHBsT/O6/diZuaSamW/KvZPCRzEBH5wnPMnp2Ck5y3SE+TiruH2ZAOTQIkKXMM03WM4onYoz5K48m/4BE6kdxOEGCc/UBVXHLQmd7bYM6/cBDmv77lMjrsaNvI7t4u/RbrCaNdDmANzBbnnwTW6MDsam3W3rDzOp3vHLku55XpBec5ioJY6hIYVV6AgIYOoBvLvDQTK6ySQDZhgc+6TkTvPsOr005U/BRl7BVsG3ux6m0RxYzSpIsl+uKmji+EKJFmBBtRc8hy+Ndi/PmMCZbaCJaj04yKBxZuC2pKa4r/HZqCsmAOEA1AgJgAAIgACmaFasqftIsL3+NMxrdmz9PrL+mw0gGoymvBFuFtqo3EuJAVjPG1PyWQDXeF4cGWI0gLVct/A/Vso1XpRGguAHWMl2C2/i8480gGc9iNdlbgg+gMVMv/CzK3P1c/r91AHx9j4XRHAATVV6hZ83nEuvD5d2iHc8AHxLqQdq2jf/VenGCxhamhEAARAAAQyT8J5QtITXgGiRATFgECoyIAYMQkUGxIBBqMiAGDAIFd9L+6DS1DQY0pAZIBs2W3vZtpdcx55pjmtbOKy1xo0ajQFABcDemO95ACDQlxA8orVADBiESqwBm4U0tgqh/t4OKzGPwHpegYQaZDZrdXBNyEzDx8t2gKvHqskasJZTIFuBe48CphHHFxMzYjIGrGT7gfeHQTNYGY8gsxPXMGjmvf8WuRHRGrCYMQOXbIF3gzu7cga3XaxAwolrHtCExDRU65EZEY0BxqsUZqtxyRb4ecM/mJ1SBbLNiO61Rxxfw3EouhZgfOYnsxpktDq1+PUnXy3ulk0jJPYJ1XolGkiaCNFEiAyIAYNQkQExYBAqMiAGDEJFBsSAQaj+bwMA/AVQMPelPAquSAAAAABJRU5ErkJggg=="</span></span></span><br><span class="line"><span class="tag"> /></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 class="javascript"> <span class="keyword">export</span> <span class="keyword">default</span> {</span></span><br><span class="line"><span class="actionscript"> name: <span class="string">"ToolReturnTop"</span>, <span class="comment">//决定引用组件的名称</span></span></span><br><span class="line"> data() {</span><br><span class="line"><span class="actionscript"> <span class="keyword">return</span> {</span></span><br><span class="line"> scroll: 0,</span><br><span class="line"><span class="actionscript"> topShow: <span class="literal">false</span>,</span></span><br><span class="line"> };</span><br><span class="line"> },</span><br><span class="line"> mounted() {</span><br><span class="line"><span class="javascript"> <span class="built_in">window</span>.addEventListener(<span class="string">"scroll"</span>, <span class="keyword">this</span>.scrolls);</span></span><br><span class="line"> },</span><br><span class="line"> methods: {</span><br><span class="line"> returnTop() {</span><br><span class="line"><span class="javascript"> <span class="built_in">window</span>.scroll(<span class="number">0</span>, <span class="number">0</span>);</span></span><br><span class="line"> },</span><br><span class="line"> scrolls() {</span><br><span class="line"><span class="actionscript"> <span class="keyword">this</span>.scroll =</span></span><br><span class="line"><span class="javascript"> <span class="built_in">document</span>.documentElement &&</span></span><br><span class="line"><span class="javascript"> <span class="built_in">document</span>.documentElement.scrollTop + <span class="built_in">document</span>.body.scrollTop;</span></span><br><span class="line"><span class="javascript"> <span class="keyword">if</span> (<span class="keyword">this</span>.scroll > <span class="built_in">window</span>.innerHeight / <span class="number">2</span>) {</span></span><br><span class="line"><span class="actionscript"> <span class="keyword">this</span>.topShow = <span class="literal">true</span>;</span></span><br><span class="line"><span class="actionscript"> } <span class="keyword">else</span> {</span></span><br><span class="line"><span class="actionscript"> <span class="keyword">this</span>.topShow = <span class="literal">false</span>;</span></span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"> },</span><br><span class="line"> };</span><br><span class="line"><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"><span class="tag"><<span class="name">style</span> <span class="attr">scoped</span>></span></span><br><span class="line"><span class="css"> <span class="comment">/* 返回顶部 */</span></span></span><br><span class="line"></span><br><span class="line"><span class="css"> <span class="selector-class">.right-return-top</span> {</span></span><br><span class="line"> position: fixed;</span><br><span class="line"> left: 0;</span><br><span class="line"> right: 0;</span><br><span class="line"> bottom: 20px;</span><br><span class="line"> z-index: 9;</span><br><span class="line"> margin: auto;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> /* .return-top {</span><br><span class="line"><span class="css"> <span class="selector-tag">width</span>: 0<span class="selector-class">.63rem</span>;</span></span><br><span class="line"><span class="css"> <span class="selector-tag">height</span>: 0<span class="selector-class">.63rem</span>;</span></span><br><span class="line"> z-index: 9;</span><br><span class="line"> margin: 0 auto;</span><br><span class="line"><span class="css"> <span class="selector-tag">background-color</span>: <span class="selector-id">#f9f9f9</span>;</span></span><br><span class="line"><span class="css"> <span class="selector-tag">box-shadow</span>: 0 0<span class="selector-class">.01rem</span> 0<span class="selector-class">.05rem</span> 0 <span class="selector-tag">rgba</span>(0, 0, 0, 0<span class="selector-class">.2</span>) !<span class="selector-tag">important</span>;</span></span><br><span class="line"><span class="css"> <span class="selector-tag">-webkit-box-shadow</span>: 0 0<span class="selector-class">.01rem</span> 0<span class="selector-class">.05rem</span> 0 <span class="selector-tag">rgba</span>(0, 0, 0, 0<span class="selector-class">.2</span>) !<span class="selector-tag">important</span>;</span></span><br><span class="line"> border-radius: 1rem;</span><br><span class="line"> } */</span><br><span class="line"><span class="css"> <span class="selector-class">.return-top</span> {</span></span><br><span class="line"> width: 40px;</span><br><span class="line"> height: 40px;</span><br><span class="line"> z-index: 9;</span><br><span class="line"> margin: 0 auto;</span><br><span class="line"><span class="css"> <span class="selector-tag">background-color</span>: <span class="selector-id">#f9f9f9</span>;</span></span><br><span class="line"><span class="css"> <span class="selector-tag">box-shadow</span>: 0 0<span class="selector-class">.01rem</span> 0<span class="selector-class">.05rem</span> 0 <span class="selector-tag">rgba</span>(0, 0, 0, 0<span class="selector-class">.2</span>) !<span class="selector-tag">important</span>;</span></span><br><span class="line"><span class="css"> <span class="selector-tag">-webkit-box-shadow</span>: 0 0<span class="selector-class">.01rem</span> 0<span class="selector-class">.05rem</span> 0 <span class="selector-tag">rgba</span>(0, 0, 0, 0<span class="selector-class">.2</span>) !<span class="selector-tag">important</span>;</span></span><br><span class="line"> border-radius: 1rem;</span><br><span class="line"> -webkit-animation: show 350ms ease-out forwards 1;</span><br><span class="line"> animation: show 350ms ease-out forwards 1;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"><span class="css"> <span class="selector-class">.return-top</span> <span class="selector-tag">img</span> {</span></span><br><span class="line"> width: 100%;</span><br><span class="line"> height: 100%;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"><span class="css"> <span class="keyword">@-webkit-keyframes</span> show {</span></span><br><span class="line"> 0% {</span><br><span class="line"> -webkit-transform: rotate(0deg);</span><br><span class="line"> }</span><br><span class="line"> 25% {</span><br><span class="line"><span class="css"> <span class="selector-tag">opacity</span>: 0<span class="selector-class">.5</span>;</span></span><br><span class="line"><span class="css"> <span class="selector-tag">-webkit-transform</span>: <span class="selector-tag">rotate</span>(<span class="selector-tag">-3deg</span>) <span class="selector-tag">translateY</span>(<span class="selector-tag">-0</span><span class="selector-class">.2rem</span>);</span></span><br><span class="line"> }</span><br><span class="line"> 75% {</span><br><span class="line"> -webkit-transform: rotate(3deg);</span><br><span class="line"> }</span><br><span class="line"> 100% {</span><br><span class="line"><span class="css"> <span class="selector-tag">opacity</span>: 0<span class="selector-class">.9</span>;</span></span><br><span class="line"> -webkit-transform: rotate(0deg);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"><span class="css"> <span class="keyword">@keyframes</span> show {</span></span><br><span class="line"> 0% {</span><br><span class="line"> transform: rotate(0deg);</span><br><span class="line"> }</span><br><span class="line"> 25% {</span><br><span class="line"><span class="css"> <span class="selector-tag">opacity</span>: 0<span class="selector-class">.5</span>;</span></span><br><span class="line"><span class="css"> <span class="selector-tag">transform</span>: <span class="selector-tag">rotate</span>(<span class="selector-tag">-3deg</span>) <span class="selector-tag">translateY</span>(<span class="selector-tag">-0</span><span class="selector-class">.2rem</span>);</span></span><br><span class="line"> }</span><br><span class="line"> 75% {</span><br><span class="line"> transform: rotate(3deg);</span><br><span class="line"> }</span><br><span class="line"> 100% {</span><br><span class="line"><span class="css"> <span class="selector-tag">opacity</span>: 0<span class="selector-class">.9</span>;</span></span><br><span class="line"> transform: rotate(0deg);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"><span class="tag"></<span class="name">style</span>></span></span><br></pre></td></tr></table></figure><p>编辑 returTop/index.js 文件,目的:将该组件作为 Vue 插件</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// sumFunction 插件对应组件的名字</span></span><br><span class="line"><span class="keyword">import</span> returnTop <span class="keyword">from</span> <span class="string">"./returnTop"</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Vue.js 的插件应当有一个公开方法 install 。第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象</span></span><br><span class="line"><span class="comment">// 此处注意,组件需要添加name属性,代表注册的组件名称,也可以修改成其他的</span></span><br><span class="line">returnTop.install = <span class="function">(<span class="params">Vue</span>) =></span> Vue.component(returnTop.name, returnTop); <span class="comment">//注册组件</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 标签的方式引入</span></span><br><span class="line"><span class="comment">//const install = function(Vue, opts = {}) {</span></span><br><span class="line"><span class="comment">// Vue.component(sumFunction.name, sumFunction);</span></span><br><span class="line"><span class="comment">//}</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 支持使用标签的方式引入 Vue是全局变量时,自动install */</span></span><br><span class="line"><span class="comment">//if (typeof window !== 'undefined' && window.Vue) {</span></span><br><span class="line"><span class="comment">// install(window.Vue);</span></span><br><span class="line"><span class="comment">//}</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> returnTop;</span><br></pre></td></tr></table></figure><p><strong>此处需要注意的是 install。 Vue 的插件必须提供一个公开方法 install,该方法会在你使用该插件,也就是 Vue.use(yourPlugin)时被调用。这样也就给 Vue 全局注入了你的所有的组件。</strong></p><h4 id="在src目录下创建index-js文件-用来统一管理组件"><a href="#在src目录下创建index-js文件-用来统一管理组件" class="headerlink" title="在src目录下创建index.js文件,用来统一管理组件"></a>在src目录下创建index.js文件,用来统一管理组件</h4><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200721180253.png" alt=""></p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Vue <span class="keyword">from</span> <span class="string">'vue'</span>;</span><br><span class="line"><span class="keyword">import</span> ReturnTop <span class="keyword">from</span> <span class="string">'./plugins/returnTop/index.js'</span>;<span class="comment">//返回顶部</span></span><br><span class="line"><span class="comment">// ...如果还有的话继续添加</span></span><br><span class="line"><span class="keyword">const</span> components = [</span><br><span class="line"> ReturnTop,</span><br><span class="line">]</span><br><span class="line"><span class="comment">//循环遍历注册组件,就可以向其他ui组件库那样,使用Vue.use()来全局使用</span></span><br><span class="line"><span class="keyword">const</span> install = <span class="function"><span class="keyword">function</span> (<span class="params">Vue, opts = {}</span>) </span>{</span><br><span class="line"> components.map(<span class="function"><span class="params">component</span> =></span> {</span><br><span class="line"> Vue.component(component.name, component);</span><br><span class="line"> })</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 支持使用标签的方式引入 */</span></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">typeof</span> <span class="built_in">window</span> !== <span class="string">'undefined'</span> && <span class="built_in">window</span>.Vue) {</span><br><span class="line"> install(<span class="built_in">window</span>.Vue);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> {</span><br><span class="line"> install,</span><br><span class="line"> ReturnTop, <span class="comment">//在这里多写一次可以单独调用,例如:Vue.use(vueutils.ReturnTop)</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="修改-package-json"><a href="#修改-package-json" class="headerlink" title="修改 package.json"></a>修改 package.json</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><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"> <span class="string">"name"</span>: <span class="string">"km-vue-utils"</span>,</span><br><span class="line"> <span class="string">"description"</span>: <span class="string">"vue常用工具合集"</span>,</span><br><span class="line"> <span class="string">"version"</span>: <span class="string">"0.0.1"</span>,</span><br><span class="line"> <span class="string">"author"</span>: <span class="string">"SuperKM"</span>,</span><br><span class="line"> <span class="string">"license"</span>: <span class="string">"MIT"</span>, <span class="comment">// 开源协议</span></span><br><span class="line"> <span class="comment">// 采用commonJs入口文件,如果不配置,我们在其他项目中就不用import XX from XX来引用了,只能以包名作为起点来指定相对的路径</span></span><br><span class="line"> <span class="string">"main"</span>: <span class="string">"dist/index.js"</span>,</span><br><span class="line"> <span class="string">"jsnext:main"</span>: <span class="string">"src/index.js"</span>, <span class="comment">// 采用es6模块化入口</span></span><br><span class="line"> <span class="string">"private"</span>: <span class="literal">false</span>, <span class="comment">// 因为组件包是公用的,所以private为false</span></span><br><span class="line"> <span class="string">"scripts"</span>: {</span><br><span class="line"> <span class="string">"dev"</span>: <span class="string">"cross-env NODE_ENV=development webpack-dev-server --open --hot"</span>,</span><br><span class="line"> <span class="string">"build"</span>: <span class="string">"cross-env NODE_ENV=production webpack --progress --hide-modules"</span></span><br><span class="line"> },</span><br><span class="line"><span class="comment">// 指定代码所在的仓库地址</span></span><br><span class="line"> <span class="string">"repository"</span>: {</span><br><span class="line"> <span class="string">"type"</span>: <span class="string">"git"</span>,</span><br><span class="line"> <span class="string">"url"</span>: <span class="string">"https://github.com/superliebe/vueTools.git"</span></span><br><span class="line"> },</span><br><span class="line"><span class="comment">// 提交bug的地址</span></span><br><span class="line"> <span class="string">"bugs"</span>: {</span><br><span class="line"> <span class="string">"url"</span>: <span class="string">"https://github.com/superliebe/vueTools/issues"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// 项目官网的url</span></span><br><span class="line"> <span class="string">"homepage"</span>: <span class="string">"https://github.com/superliebe/vueTools"</span>,</span><br><span class="line"> <span class="string">"keywords"</span>: [</span><br><span class="line"> <span class="string">"vue"</span>,</span><br><span class="line"> <span class="string">"component"</span>,</span><br><span class="line"> <span class="string">"tools"</span>,</span><br><span class="line"> <span class="string">"superkm"</span></span><br><span class="line"> ], <span class="comment">// 指定关键字</span></span><br><span class="line"> <span class="string">"dependencies"</span>: {</span><br><span class="line"> <span class="string">"vue"</span>: <span class="string">"^2.5.11"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="string">"browserslist"</span>: [</span><br><span class="line"> <span class="string">"> 1%"</span>,</span><br><span class="line"> <span class="string">"last 2 versions"</span>,</span><br><span class="line"> <span class="string">"not ie <= 8"</span></span><br><span class="line"> ],</span><br><span class="line"> <span class="string">"devDependencies"</span>: {</span><br><span class="line"> ...</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="修改-gitignore"><a href="#修改-gitignore" class="headerlink" title="修改.gitignore"></a>修改.gitignore</h4><p>因为要用 dist 文件夹,所以在.gitignore 文件中把 dist/去掉。</p><h4 id="修改-webpack-config-js"><a href="#修改-webpack-config-js" class="headerlink" title="修改 webpack.config.js"></a>修改 webpack.config.js</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 原</span></span><br><span class="line"><span class="built_in">module</span>.exports = {</span><br><span class="line"> entry: <span class="string">'./src/main.js'</span>,</span><br><span class="line"> output: {</span><br><span class="line"> path: path.resolve(__dirname, <span class="string">'./dist'</span>),</span><br><span class="line"> publicPath: <span class="string">'/dist/'</span>,</span><br><span class="line"> filename: <span class="string">'build.js'</span></span><br><span class="line"> }</span><br><span class="line">...</span><br><span class="line">}</span><br><span class="line"><span class="comment">// 新</span></span><br><span class="line"><span class="keyword">const</span> NODE_ENV = process.env.NODE_ENV</span><br><span class="line"><span class="built_in">module</span>.exports = {</span><br><span class="line"> entry: NODE_ENV == <span class="string">'development'</span> ? <span class="string">'./src/main.js'</span> : <span class="string">'./src/index.js'</span>,</span><br><span class="line"> output: {</span><br><span class="line"> path: path.resolve(__dirname, <span class="string">'./dist'</span>),</span><br><span class="line"> publicPath: <span class="string">'/dist/'</span>,</span><br><span class="line"> filename: <span class="string">'index.js'</span>,</span><br><span class="line"> libraryTarget: <span class="string">'umd'</span>, <span class="comment">// 指定输出格式</span></span><br><span class="line"> umdNamedDefine: <span class="literal">true</span> <span class="comment">// 会对 UMD 的构建过程中的 AMD 模块进行命名。否则就使用匿名的 define</span></span><br><span class="line"> }</span><br><span class="line">...</span><br><span class="line">}</span><br></pre></td></tr></table></figure><blockquote><p>❗ 发布 npm 之前必须做两件事情。</p><p>❤️ - 必须 npm run build 打包一下。</p><p>❤️ - 必须 修改 package.json 中的版本号。</p></blockquote><h3 id="发布包到-npm"><a href="#发布包到-npm" class="headerlink" title="发布包到 npm"></a>发布包到 npm</h3><ul><li>已经注册过 npm 账号,首先登陆,登陆过一次之后,就可以直接发布</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">npm login --registry http:<span class="comment">//registry.npmjs.org</span></span><br><span class="line"><span class="comment">//适用于使用了淘宝镜像加速的</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//或者</span></span><br><span class="line"></span><br><span class="line">npm login <span class="comment">//未采用镜像加速过</span></span><br></pre></td></tr></table></figure><p>输入账号-密码-邮箱后,提示 Logged in as *** on <a href="http://registry.npmjs.org/" target="_blank" rel="noopener">http://registry.npmjs.org/</a>. 就是登陆成功了</p><ul><li>然后直接发布</li></ul><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">npm publish --registry http:<span class="comment">//registry.npmjs.org</span></span><br></pre></td></tr></table></figure><p>发布成功后提示,前往自己的 npm 库中就可以查看到刚刚发布的 npm 包</p><p>npm 库中</p><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200721180259.png" alt=""></p><ul><li>如果想删除发布的包</li></ul><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">npm unpublish km-vuetools --force --registry http:<span class="comment">//registry.npmjs.org</span></span><br></pre></td></tr></table></figure><h4 id="npm-发布中常见错误"><a href="#npm-发布中常见错误" class="headerlink" title="npm 发布中常见错误"></a>npm 发布中常见错误</h4><ul><li>409 Conflict</li></ul><p>npm login 或者 npm adduser 时 输入完账号密码邮箱后 提示 E409 Conflict 报错 一般因为淘宝镜像的原因</p><p>解决方案,直接 registry 镜像源</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">npm login --registry http:<span class="comment">//registry.npmjs.org</span></span><br></pre></td></tr></table></figure><ul><li>npm ERR! 403</li></ul><p>可能是包名已经存在,或者是邮箱未认证</p><h3 id="使用自己发布的包"><a href="#使用自己发布的包" class="headerlink" title="使用自己发布的包"></a>使用自己发布的包</h3><p>使用 cnpm 安装依赖</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">cnpm i km-vue-utils -S</span><br></pre></td></tr></table></figure><p>在 main.js 文件 或者想要引入的文件导入</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> utils <span class="keyword">from</span> <span class="string">"km-vue-utils"</span>;</span><br><span class="line">Vue.use(utils);</span><br></pre></td></tr></table></figure><p>在想要引用的.vue 文件中直接写</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></pre></td><td class="code"><pre><span class="line"><span class="comment"><!-- 该名称由封装组件中的name属性决定 --></span></span><br><span class="line"><span class="tag"><<span class="name">tool-return-top</span>></span><span class="tag"></<span class="name">tool-return-top</span>></span></span><br><span class="line"></span><br><span class="line"><span class="comment"><!-- </span></span><br><span class="line"><span class="comment"> 如果想引用组件中包含的方法,给Vue.prototype属性</span></span><br><span class="line"><span class="comment"> Vue.prototype.$utils = utils;</span></span><br><span class="line"><span class="comment"> 在需要调用的地方直接写</span></span><br><span class="line"><span class="comment"> this.$utils.方法文件.方法名;</span></span><br><span class="line"><span class="comment"> --></span></span><br></pre></td></tr></table></figure><p>😜😜😜</p>]]></content>
<categories>
<category> vue </category>
<category> node </category>
</categories>
<tags>
<tag> vue </tag>
</tags>
</entry>
<entry>
<title>网站变灰技巧</title>
<link href="/2020/06/28/%E7%BD%91%E7%AB%99%E5%8F%98%E7%81%B0%E6%8A%80%E5%B7%A7/"/>
<url>/2020/06/28/%E7%BD%91%E7%AB%99%E5%8F%98%E7%81%B0%E6%8A%80%E5%B7%A7/</url>
<content type="html"><![CDATA[<p>把网站变成灰色,来追悼逝去的英魂</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">html</span> {</span><br><span class="line"> <span class="attribute">-webkit-filter</span>: <span class="built_in">grayscale</span>(<span class="number">100%</span>);</span><br><span class="line"> <span class="attribute">-moz-filter</span>: <span class="built_in">grayscale</span>(<span class="number">100%</span>);</span><br><span class="line"> <span class="attribute">-ms-filter</span>: <span class="built_in">grayscale</span>(<span class="number">100%</span>);</span><br><span class="line"> <span class="attribute">-o-filter</span>: <span class="built_in">grayscale</span>(<span class="number">100%</span>);</span><br><span class="line"> <span class="attribute">filter</span>: <span class="built_in">grayscale</span>(<span class="number">100%</span>);</span><br><span class="line"> <span class="attribute">filter</span>: gray;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> vue </category>
</categories>
<tags>
<tag> vue </tag>
</tags>
</entry>
<entry>
<title>docker常用命令操作、容器卷使用、dockefile等</title>
<link href="/2020/06/18/docker%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4%E6%93%8D%E4%BD%9C/"/>
<url>/2020/06/18/docker%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4%E6%93%8D%E4%BD%9C/</url>
<content type="html"><![CDATA[<p><img src="https://s1.ax1x.com/2020/06/17/NEy0ij.png" alt=""></p><p>docker 常用命令小字典</p><a id="more"></a><h3 id="镜像命令"><a href="#镜像命令" class="headerlink" title="镜像命令"></a>镜像命令</h3><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">docker version</span><br></pre></td></tr></table></figure><h4 id="系统信息,镜像和容器数量"><a href="#系统信息,镜像和容器数量" class="headerlink" title="系统信息,镜像和容器数量"></a>系统信息,镜像和容器数量</h4><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">docker info</span><br></pre></td></tr></table></figure><h4 id="查看所有本地主机上的镜像"><a href="#查看所有本地主机上的镜像" class="headerlink" title="查看所有本地主机上的镜像"></a>查看所有本地主机上的镜像</h4><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></pre></td><td class="code"><pre><span class="line">docker images</span><br><span class="line"></span><br><span class="line"><span class="comment"># 可选项</span></span><br><span class="line"></span><br><span class="line">-a , --all <span class="comment">#列出所有镜像</span></span><br><span class="line">-q , --quiet <span class="comment">#只显示镜像的id</span></span><br></pre></td></tr></table></figure><h4 id="搜索镜像"><a href="#搜索镜像" class="headerlink" title="搜索镜像"></a>搜索镜像</h4><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">docker search mysql</span><br></pre></td></tr></table></figure><h4 id="下载镜像"><a href="#下载镜像" class="headerlink" title="下载镜像"></a>下载镜像</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">docker pull mysql</span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果不写版本,默认使用latest最新版本</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 指定版本下载</span></span><br><span class="line"></span><br><span class="line">docker pull mysql:5.7</span><br><span class="line"></span><br><span class="line"><span class="comment"># 输出</span></span><br><span class="line">latest: Pulling from library/mysql</span><br><span class="line">8559a31e96f4: Pull complete <span class="comment"># 分层下载。docker的核心联合文件系统</span></span><br><span class="line">Digest: sha256:8b7b328a7ff6de46ef96bcf83af048cb00a1c86282bfca0cb119c84568b4caf6 <span class="comment">#签名</span></span><br><span class="line">Status: Downloaded newer image <span class="keyword">for</span> mysql:latest <span class="comment">#真实地址</span></span><br></pre></td></tr></table></figure><h4 id="删除镜像"><a href="#删除镜像" class="headerlink" title="删除镜像"></a>删除镜像</h4><p>如果容器正在运行中,是不能使用 rmi 这个命令的</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker rmi 镜像名 <span class="comment"># 删除镜像</span></span><br><span class="line">docker rmi -f 镜像id <span class="comment"># 根据id删除镜像</span></span><br><span class="line">docker rmi -f $(docker -aq) <span class="comment"># 删除全部镜像</span></span><br></pre></td></tr></table></figure><h3 id="容器命令"><a href="#容器命令" class="headerlink" title="容器命令"></a>容器命令</h3><p>说明:有了镜像才可以创建容器</p><h4 id="新建容器并启动"><a href="#新建容器并启动" class="headerlink" title="新建容器并启动"></a>新建容器并启动</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">docker pull centos <span class="comment"># 下载centos镜像</span></span><br><span class="line"></span><br><span class="line">docker run [可选参数] image</span><br><span class="line"></span><br><span class="line"><span class="comment"># 参数说明</span></span><br><span class="line"></span><br><span class="line">--m = <span class="string">"name"</span> <span class="comment"># 容器名字,用来区分容器</span></span><br><span class="line">-d <span class="comment"># 后台运行</span></span><br><span class="line">-it <span class="comment"># 使用交互方式运行,进入容器查看内容</span></span><br><span class="line">-P <span class="comment"># 指定容器的端口</span></span><br><span class="line"> <span class="comment"># -p 8080(主机端口):8080(容器端口)</span></span><br><span class="line">-p <span class="comment"># 随机容器的端口</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 测试,启动centos并进入</span></span><br><span class="line">$ docker run -it centos /bin/bash</span><br><span class="line">[root@f8ed75f63bcc /]<span class="comment"># ls #查看容器内的centos</span></span><br><span class="line">bin dev etc home lib lib64 lost+found media mnt opt proc...</span><br><span class="line"></span><br><span class="line"><span class="comment">#从容器中退回主机</span></span><br><span class="line">[root@f8ed75f63bcc /]<span class="comment"># exit</span></span><br></pre></td></tr></table></figure><h4 id="查看运行中的容器"><a href="#查看运行中的容器" class="headerlink" title="查看运行中的容器"></a>查看运行中的容器</h4><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></pre></td><td class="code"><pre><span class="line">docker ps <span class="comment"># 查看运行中</span></span><br><span class="line">docker ps -a <span class="comment"># 查看所有运行过+进行中的容器</span></span><br><span class="line">docker ps -n=2 <span class="comment"># 显示最近正在运行的容器</span></span><br><span class="line">docker ps -aq <span class="comment"># 显示所有运行过+进行中的容器的id</span></span><br></pre></td></tr></table></figure><h4 id="删除容器"><a href="#删除容器" class="headerlink" title="删除容器"></a>删除容器</h4><figure class="highlight bash"><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">docker rm 容器id <span class="comment">#删除指定容器,不能删除正在运行的</span></span><br><span class="line">docker rm -f $(docker ps -aq) <span class="comment">#删除所有容器,强制删除</span></span><br></pre></td></tr></table></figure><h4 id="退出容器"><a href="#退出容器" class="headerlink" title="退出容器"></a>退出容器</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">exit</span> <span class="comment"># 直接停止并退出</span></span><br><span class="line">Ctrl+P+Q <span class="comment">#容器不停止退出</span></span><br></pre></td></tr></table></figure><h4 id="启动容器"><a href="#启动容器" class="headerlink" title="启动容器"></a>启动容器</h4><figure class="highlight bash"><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">docker start 容器id <span class="comment"># 启动</span></span><br><span class="line">docker restart 容器id <span class="comment"># 重启</span></span><br></pre></td></tr></table></figure><h4 id="停止容器"><a href="#停止容器" class="headerlink" title="停止容器"></a>停止容器</h4><figure class="highlight bash"><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">docker stop 容器id <span class="comment"># 停止</span></span><br><span class="line">docker <span class="built_in">kill</span> 容器id <span class="comment"># 杀死</span></span><br></pre></td></tr></table></figure><h3 id="常用其他命令"><a href="#常用其他命令" class="headerlink" title="常用其他命令"></a>常用其他命令</h3><h4 id="后台启动"><a href="#后台启动" class="headerlink" title="后台启动"></a>后台启动</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker run -d 镜像名</span><br><span class="line"></span><br><span class="line"><span class="comment"># 常见问题:docker容器使用后台运行,就必须拥有前台进程,docker发现没有应用就会自动停止</span></span><br></pre></td></tr></table></figure><h4 id="持续打印日志"><a href="#持续打印日志" class="headerlink" title="持续打印日志"></a>持续打印日志</h4><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">docker logs -tf --tail 10 容器名</span><br></pre></td></tr></table></figure><h4 id="查看-docker-容器内部的进程信息"><a href="#查看-docker-容器内部的进程信息" class="headerlink" title="查看 docker 容器内部的进程信息"></a>查看 docker 容器内部的进程信息</h4><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">docker top 容器id</span><br></pre></td></tr></table></figure><h4 id="查看容器元数据"><a href="#查看容器元数据" class="headerlink" title="查看容器元数据"></a>查看容器元数据</h4><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">docker inspect 容器id</span><br></pre></td></tr></table></figure><h4 id="进入当前正在运行的容器"><a href="#进入当前正在运行的容器" class="headerlink" title="进入当前正在运行的容器"></a>进入当前正在运行的容器</h4><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 我们容器通常是使用后台运行的,需要进入容器,修改一些配置</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 命令</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 进入容器后开启一个新的终端,可以在里面操作</span></span><br><span class="line">docker <span class="built_in">exec</span> -it 容器id + 默认命令行(/bin/bash)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 进入容器正在执行的终端,不会启动新进程</span></span><br><span class="line">docker attach 容器id</span><br></pre></td></tr></table></figure><h4 id="从文件内容拷贝到主机"><a href="#从文件内容拷贝到主机" class="headerlink" title="从文件内容拷贝到主机"></a>从文件内容拷贝到主机</h4><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">docker cp 容器id:容器内路径 目的的主机路径</span><br></pre></td></tr></table></figure><h4 id="可视化图形界面"><a href="#可视化图形界面" class="headerlink" title="可视化图形界面"></a>可视化图形界面</h4><figure class="highlight bash"><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">docker run -d -p 8088:9000 \</span><br><span class="line">--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=<span class="literal">true</span> portainer/portainer</span><br></pre></td></tr></table></figure><h4 id="打包提交自己的镜像"><a href="#打包提交自己的镜像" class="headerlink" title="打包提交自己的镜像"></a>打包提交自己的镜像</h4><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></pre></td><td class="code"><pre><span class="line">docker commit <span class="comment">#提交容器为一个新的副本</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 和 git 提交原理类似</span></span><br><span class="line">docker commit -m=<span class="string">"提交信息"</span> -a=<span class="string">"作者"</span> 容器id 目标镜像名:[tag]</span><br></pre></td></tr></table></figure><h3 id="容器卷"><a href="#容器卷" class="headerlink" title="容器卷"></a>容器卷</h3><p>容器之间可以有一个数据共享的技术,docker 容器的数据可以同步到本地,这就是卷技术</p><blockquote><p>卷的设计目的就是数据的持久化,完全独立与容器的生命周期,因此 Docker 不会在容器删除时删除其挂载的数据卷。</p><p>特点:</p><ol><li><p>数据卷可以在容器之间共享和重用数据。</p></li><li><p>卷的更改可以直接生效。</p></li><li><p>数据卷的更改不会包含在镜像的更新中。</p></li><li><p>数据卷的生命周期一直持续到没有容器使用它为止。</p></li></ol><p>容器的持久化</p><p>容器间继承+共享数据</p></blockquote><p><strong>总结一句话:容器持久化和同步技术,容器间也是可以数据共享的!</strong></p><h4 id="使用容器卷"><a href="#使用容器卷" class="headerlink" title="使用容器卷"></a>使用容器卷</h4><blockquote><p>方式-:直接使用命令来挂载 -v</p></blockquote><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 指定路径挂载</span></span><br><span class="line">docker run -it -v 主机目录:容器目录</span><br><span class="line"></span><br><span class="line"><span class="comment">#示例</span></span><br><span class="line">docker run -d -it -v /home/ceshi:/home centos /bin/bash</span><br></pre></td></tr></table></figure><p>通过 <code>docker inspect 容器id</code> 查看容器详细信息</p><p><img src="https://s1.ax1x.com/2020/07/07/UACcpq.png" alt=""></p><p>如果在容器内部对应的目录下增加文件,则对应的主机目录也会增加相关文件</p><h4 id="具名挂载和匿名挂载"><a href="#具名挂载和匿名挂载" class="headerlink" title="具名挂载和匿名挂载"></a>具名挂载和匿名挂载</h4><ul><li>匿名挂载</li></ul><p>不指定主机名,直接写容器内路径。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">-v 容器内路径</span><br><span class="line">docker run -d -P --name nginx01 -v /etc/nginx nginx</span><br><span class="line"></span><br><span class="line"><span class="comment"># 通过docker volume ls查看所有卷情况</span></span><br><span class="line"></span><br><span class="line">输出:</span><br><span class="line">DRIVER VOLUME NAME</span><br><span class="line"><span class="built_in">local</span> 53d4bdcfd2df.... <span class="comment">#匿名卷</span></span><br></pre></td></tr></table></figure><ul><li>具名挂载</li></ul><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></pre></td><td class="code"><pre><span class="line">-v 容器内路径</span><br><span class="line">docker run -d -P --name nginx02 -v <span class="built_in">test</span>-nginx:/etc/nginx nginx <span class="comment">#指定了名字test-nginx</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 通过docker volume ls查看所有卷情况</span></span><br><span class="line"></span><br><span class="line">输出:</span><br><span class="line">DRIVER VOLUME NAME</span><br><span class="line"><span class="built_in">local</span> <span class="built_in">test</span>-nginx <span class="comment">#具名挂载</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 通过 docker volume inspect test-nginx 查看具体卷情况</span></span><br></pre></td></tr></table></figure><p>通过具名挂载可以方便的找到卷</p><h3 id="Dockerfile"><a href="#Dockerfile" class="headerlink" title="Dockerfile"></a>Dockerfile</h3><p>dokcerfile 就是用来构建 docker 的镜像文件,也就是命令脚本,通过脚本生成镜像</p><blockquote><p>方式二:命令脚本</p></blockquote><p>创建 dockerfile1 文件并编辑</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#文件中的内容,指令必须大写,每个命令都是一层一层的</span></span><br><span class="line"></span><br><span class="line">FROM centos <span class="comment">#基础镜像</span></span><br><span class="line"></span><br><span class="line">VOLUME [<span class="string">"volume01"</span>,<span class="string">"volume02"</span>] <span class="comment">#创建同步的目录,匿名挂载</span></span><br><span class="line"></span><br><span class="line">CMD /bin/bash <span class="comment"># 运行/bin/bash</span></span><br></pre></td></tr></table></figure><p>接下来开始构建</p><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">docker build -f dockerfile脚本地址 -t 镜像名:[tag] .</span><br><span class="line"></span><br><span class="line"><span class="comment"># 例如:docker build -f dockerfile1 -t superkm/centos:1.0 .</span></span><br><span class="line"><span class="comment"># -f dockerfile脚本地址</span></span><br><span class="line"><span class="comment"># -t 生成镜像且生成到当前目录下,注意最后有个 .</span></span><br></pre></td></tr></table></figure><p>然后查看<code>docker images</code> 就可以看到刚刚生成的镜像</p><p>进入自己创建的镜像<code>docker run -it 容器id</code>,然后 ls 查看目录就会看到,目录中包含 volume01,volume02 即为挂载的数据卷目录</p><p><code>docker inspect 容器id</code> 查看容器详情</p><h4 id="容器间同步挂载"><a href="#容器间同步挂载" class="headerlink" title="容器间同步挂载"></a>容器间同步挂载</h4><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 首先创建容器docker01</span></span><br><span class="line">docker run -it --name docker01 superkm/centos:1.0</span><br><span class="line"><span class="comment"># 然后同步创建docker02</span></span><br><span class="line">docker run -it --name docker02 --volumes-from docker01 superkm/centos:1.0</span><br><span class="line"></span><br><span class="line"><span class="comment"># 通过--volumes-from 实现容器间的数据同享,只要存在一个容器使用,其他容器删除文件也依旧存在</span></span><br></pre></td></tr></table></figure><p>这样容器 docker01 就和 容器 docker02 挂载目录实时同步更新</p><h3 id="登录-docker-hub"><a href="#登录-docker-hub" class="headerlink" title="登录 docker hub"></a>登录 docker hub</h3><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">docker login</span><br></pre></td></tr></table></figure><p>输入 账号密码回车即可</p>]]></content>
<categories>
<category> docker </category>
</categories>
<tags>
<tag> docker </tag>
</tags>
</entry>
<entry>
<title>dockerToolbox的安装、配置镜像</title>
<link href="/2020/06/17/dockerTool-box%E7%9A%84%E5%AE%89%E8%A3%85%E9%85%8D%E7%BD%AE/"/>
<url>/2020/06/17/dockerTool-box%E7%9A%84%E5%AE%89%E8%A3%85%E9%85%8D%E7%BD%AE/</url>
<content type="html"><![CDATA[<p>作为一种新兴的虚拟化方式,Docker 跟传统的虚拟化方式相比具有众多的优势。</p><a id="more"></a><h3 id="docker-的基本介绍"><a href="#docker-的基本介绍" class="headerlink" title="docker 的基本介绍"></a>docker 的基本介绍</h3><p>首先,Docker 容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得多。其次,Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器。</p><p>容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机,而 Docker 只需要启动 10 个隔离的应用即可。</p><p>docker 与 传统虚拟机相比</p><table><thead><tr><th>特性</th><th>docker 容器</th><th>虚拟机</th></tr></thead><tbody><tr><td>硬盘使用</td><td>一般为 MB</td><td>一般为 GB</td></tr><tr><td>性能</td><td>接近原生</td><td>弱于</td></tr><tr><td>系统支持量</td><td>单机支持上千个容器</td><td>一般几十个</td></tr></tbody></table><h3 id="DockerToolbox-安装-docker"><a href="#DockerToolbox-安装-docker" class="headerlink" title="DockerToolbox 安装 docker"></a>DockerToolbox 安装 docker</h3><p><a href="https://www.docker.com" target="_blank" rel="noopener">docker 官网</a></p><p>win7、win8,非 win10 专业版等需要利用 docker toolbox 来安装,国内可以使用阿里云的镜像来下载,下载地址:<a href="http://mirrors.aliyun.com/docker-toolbox/windows/docker-toolbox/" target="_blank" rel="noopener">http://mirrors.aliyun.com/docker-toolbox/windows/docker-toolbox/</a></p><p><img src="https://s1.ax1x.com/2020/06/17/NERd8H.png" alt=""></p><p>选择需要的服务,进行下一步安装</p><p>安装成功后,桌面会显示启动图标,双击运行<br><img src="https://s1.ax1x.com/2020/06/17/NE43WD.png" alt=""></p><p>如果运行成功,进入 docker</p><p><img src="https://s1.ax1x.com/2020/06/17/NEWUe0.md.png" alt=""></p><p>如果失败,请看下方安装问题</p><h3 id="docker-toolbox-环境下-使用阿里云容器镜像加速器"><a href="#docker-toolbox-环境下-使用阿里云容器镜像加速器" class="headerlink" title="docker toolbox 环境下 使用阿里云容器镜像加速器"></a>docker toolbox 环境下 使用阿里云容器镜像加速器</h3><ul><li>在 Docker Quickstart Terminal 命令行输入命令:</li></ul><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">docker-machine ssh <span class="keyword">default</span></span><br></pre></td></tr></table></figure><p>意思是采用 docker-machine 命令,以 ssh 方式,从当前 Docker Quickstart Terminal 窗口登录名称为 default 的 docker 虚拟机</p><ul><li>此时窗口进入到了 docker 虚拟机,docker-machine 命令已经失效。linux 命令生效。</li></ul><p>输入 <code>cat /var/lib/boot2docker/profile</code></p><p>查看当前配置文件,其中第一句中</p><p><code>EXTRA_ARGS='--registry-mirror=http://******.io</code></p><p>registry-mirror=后的网址即为当前镜像地址。</p><ul><li>使用如下命令即可改为阿里云镜像地址</li></ul><p><code>sudo sed -i "s|EXTRA_ARGS='|EXTRA_ARGS='--registry-mirror=镜像地址 |g" /var/lib/boot2docker/profile</code></p><p>添加后输入<code>exit</code></p><p>退出 docker@default</p><p>重启 docker-machine <code>docker-machine restart default</code></p><p>输入<code>docker info</code>查看镜像配置,registry 中可以看到配置的镜像</p><p><img src="https://s1.ax1x.com/2020/06/18/NZNZNt.png" alt="NZNZNt.png"></p><p>注意:需要登录阿里云容器镜像服务,获取自己的加速地址,<a href="https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors" target="_blank" rel="noopener">点击进入阿里云镜像服务</a></p><h3 id="安装问题"><a href="#安装问题" class="headerlink" title="安装问题"></a>安装问题</h3><p><strong>问题一</strong></p><p>双击 Docker Quickstart Terminal,提示 windows 正在查找 bash.exe。如果想亲自查找文件,请点击“浏览”。</p><p><strong>问题原因</strong><br>一般出现这个问题,是因为之前已经安装过了 git,且 bash.exe 的路径与 Docker Toolbox 中不一致导致的。</p><p><strong>解决办法</strong><br>右击 Docker Quickstart Terminal 的图标,修改前一段 bash 的路径为本机 git 安装路径。</p><p><img src="https://s1.ax1x.com/2020/06/17/NE5Qns.png" alt=""></p><p><strong>问题二</strong></p><p>配置了镜像加速后,重启电脑,通过 docker info 查看镜像又成了原来默认的地址</p><p><strong>解决方法</strong></p><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">docker-machine rm <span class="keyword">default</span></span><br></pre></td></tr></table></figure><p>打开 docker 安装目录,编辑 start.sh 文件(如果你 docker 创建主机了你修改之后要删除主机 重新创建一台)</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="string">"${DOCKER_MACHINE}"</span> create -d virtualbox $PROXY_ENV <span class="string">"${VM}"</span></span><br></pre></td></tr></table></figure><p>改成</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"${DOCKER_MACHINE}"</span> create --engine-registry-mirror=你的阿里云地址 -d virtualbox $PROXY_ENV <span class="string">"${VM}"</span></span><br></pre></td></tr></table></figure><p>运行Docker Quickstart Termin</p><p>通过 docker info 查看镜像地址 就再也不会改变啦,可以开开心心的push了~</p>]]></content>
<categories>
<category> docker </category>
</categories>
<tags>
<tag> docker </tag>
</tags>
</entry>
<entry>
<title>koa2下一代web开发框架</title>
<link href="/2020/06/10/koa%E4%B8%8B%E4%B8%80%E4%BB%A3web%E5%BC%80%E5%8F%91%E6%A1%86%E6%9E%B6/"/>
<url>/2020/06/10/koa%E4%B8%8B%E4%B8%80%E4%BB%A3web%E5%BC%80%E5%8F%91%E6%A1%86%E6%9E%B6/</url>
<content type="html"><![CDATA[<p><img src="https://s1.ax1x.com/2020/06/10/tob9aD.png" alt=""></p><p><strong>next generation web framework for node.js</strong></p><a id="more"></a><p><a href="https://www.koajs.com.cn" target="_blank" rel="noopener">koa官网</a></p><p>先看一下 koa 的交互流程概念</p><p><img src="https://s1.ax1x.com/2020/06/10/toXbcj.png" alt="koa核心概念"></p><h3 id="koa的工作原理"><a href="#koa的工作原理" class="headerlink" title="koa的工作原理"></a>koa的工作原理</h3><p>koa中的中间件本质上就是一个async函数</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">async</span> (ctx, next) => {</span><br><span class="line"> <span class="keyword">await</span> next();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><blockquote><p>Koa 中间件的实现原理,也就是洋葱模型的实现原理,核心在于next的实现。next需要依次调用下一个middleware,当到最后一个的时候结束,这样后面middleware的promise先resolve,然后直到第一个,这样的流程也就是洋葱模型的流程了。</p></blockquote><p><img src="https://s1.ax1x.com/2020/06/10/tTpm1U.jpg" alt=""></p><p>基本写法示例</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> Koa = <span class="built_in">require</span>(<span class="string">'koa'</span>);</span><br><span class="line"><span class="keyword">const</span> app = <span class="keyword">new</span> Koa();</span><br><span class="line"></span><br><span class="line">app.use(<span class="keyword">async</span> ctx => {</span><br><span class="line"> ctx.body = <span class="string">'Hello World'</span>;</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line">app.listen(<span class="number">3000</span>);</span><br></pre></td></tr></table></figure><p>打开浏览器 localhost:3000就可以看到Hello World</p><h3 id="koa-router路由配置"><a href="#koa-router路由配置" class="headerlink" title="koa-router路由配置"></a>koa-router路由配置</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">cnpm i -D koa-router</span><br></pre></td></tr></table></figure><p>引入路由组件</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Router <span class="keyword">from</span> <span class="string">'koa-router'</span></span><br><span class="line"><span class="comment">// 或者</span></span><br><span class="line"><span class="comment">// const Router = require('koa-router');</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 定义router</span></span><br><span class="line"><span class="keyword">const</span> router = <span class="keyword">new</span> Router();</span><br><span class="line"></span><br><span class="line"><span class="comment">//创建一个get方法</span></span><br><span class="line">router.get(<span class="string">'/api'</span>,ctx=>{</span><br><span class="line"> ctx.body = <span class="string">'hello api!'</span></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"><span class="comment">//router.prefix添加接口前缀</span></span><br><span class="line">router.prefix(<span class="string">'/api'</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></pre></td><td class="code"><pre><span class="line">cnpm i -S koa-combine-routers</span><br></pre></td></tr></table></figure><h3 id="添加安全头部-koa-helmet"><a href="#添加安全头部-koa-helmet" class="headerlink" title="添加安全头部 koa-helmet"></a>添加安全头部 koa-helmet</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">cnpm i -S koa-helmet</span><br></pre></td></tr></table></figure><h3 id="添加静态文件-koa-static"><a href="#添加静态文件-koa-static" class="headerlink" title="添加静态文件 koa-static"></a>添加静态文件 koa-static</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">cnpm i -S koa-static</span><br></pre></td></tr></table></figure><h3 id="koa-body协议解析"><a href="#koa-body协议解析" class="headerlink" title="koa-body协议解析"></a>koa-body协议解析</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">cnpm i koa-body</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用方法,直接use即可</span></span><br><span class="line"><span class="keyword">const</span> koaBody = <span class="built_in">require</span>(<span class="string">'koa-body'</span>);</span><br><span class="line"></span><br><span class="line">app.use(koaBody());</span><br></pre></td></tr></table></figure><h3 id="koa-cors跨域处理"><a href="#koa-cors跨域处理" class="headerlink" title="@koa/cors跨域处理"></a>@koa/cors跨域处理</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">cnpm i @koa/cors</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用方法,直接use即可</span></span><br><span class="line"><span class="keyword">const</span> cors = <span class="built_in">require</span>(<span class="string">'@koa/cors'</span>);</span><br><span class="line"> </span><br><span class="line">app.use(cors());</span><br></pre></td></tr></table></figure><h3 id="配置koa的热加载-nodemon"><a href="#配置koa的热加载-nodemon" class="headerlink" title="配置koa的热加载 nodemon"></a>配置koa的热加载 nodemon</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">cnpm i - D nodemon</span><br></pre></td></tr></table></figure><p>使用<code>npx nodemon src/index.js</code> 监听文件内容变化,实现热更新</p>]]></content>
<categories>
<category> koa </category>
</categories>
<tags>
<tag> nodejs,koa </tag>
</tags>
</entry>
<entry>
<title>vue性能优化之路</title>
<link href="/2020/06/04/vue-cli4%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E8%B7%AF/"/>
<url>/2020/06/04/vue-cli4%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E8%B7%AF/</url>
<content type="html"><![CDATA[<p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200721180140.png" alt=""></p><p>vue 生产环境上的性能优化:开启 Gzip、去掉打包后的 console、图片懒加载等</p><a id="more"></a><h2 id="开启-Gzip-压缩模式"><a href="#开启-Gzip-压缩模式" class="headerlink" title="开启 Gzip 压缩模式"></a>开启 Gzip 压缩模式</h2><p>gizp 压缩是一种 http 请求优化方式,通过减少文件体积来提高加载速度,对于用户量多的网站,开启 gizp 压缩会大大降低服务器压力,提高加载速度,降低服务器流量成本</p><blockquote><p><strong>安装 compression-webpack-plugin 插件</strong></p></blockquote><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">cnpm install compression-webpack-plugin --save-dev</span><br></pre></td></tr></table></figure><p><strong>vue.config.js 配置 Gzip 压缩</strong></p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 导入compression-webpack-plugin</span></span><br><span class="line"><span class="keyword">const</span> CompressionWebpackPlugin = <span class="built_in">require</span>(<span class="string">"compression-webpack-plugin"</span>);</span><br><span class="line"><span class="comment">// 定义压缩文件类型</span></span><br><span class="line"><span class="keyword">const</span> productionGzipExtensions = [<span class="string">"js"</span>, <span class="string">"css"</span>];</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = {</span><br><span class="line"> <span class="comment">//统一配置打包插件</span></span><br><span class="line"> configureWebpack: {</span><br><span class="line"> plugins: [</span><br><span class="line"> <span class="keyword">new</span> CompressionWebpackPlugin({</span><br><span class="line"> filename: <span class="string">"[path].gz[query]"</span>,</span><br><span class="line"> algorithm: <span class="string">"gzip"</span>,</span><br><span class="line"> test: <span class="keyword">new</span> <span class="built_in">RegExp</span>(<span class="string">"\\.("</span> + productionGzipExtensions.join(<span class="string">"|"</span>) + <span class="string">")$"</span>), <span class="comment">//匹配文件名</span></span><br><span class="line"> threshold: <span class="number">10240</span>, <span class="comment">//对10K以上的数据进行压缩</span></span><br><span class="line"> minRatio: <span class="number">0.8</span>,</span><br><span class="line"> deleteOriginalAssets: <span class="literal">false</span>, <span class="comment">//是否删除源文件</span></span><br><span class="line"> }),</span><br><span class="line"> ],</span><br><span class="line"> },</span><br><span class="line">};</span><br></pre></td></tr></table></figure><p>npm run build 之后,对比之前的文件,平均压缩了 4 倍左右</p><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200721180131.png" alt="build.png"></p><p>接下来在服务器的 nginx 上配置 Gzip</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><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="attribute">gzip</span> <span class="literal">on</span>; <span class="comment">#开启或关闭gzip on off</span></span><br><span class="line"><span class="attribute">gzip_min_length</span> <span class="number">5k</span>; <span class="comment">#gzip压缩最小文件大小,超出进行压缩(自行调节)</span></span><br><span class="line"><span class="attribute">gzip_buffers</span> <span class="number">4</span> <span class="number">16k</span>; <span class="comment">#buffer 不用修改</span></span><br><span class="line"><span class="attribute">gzip_comp_level</span> <span class="number">4</span>; <span class="comment">#压缩级别:1-10,数字越大压缩的越好,时间也越长</span></span><br><span class="line"><span class="attribute">gzip_types</span> text/plain application/x-javascript application/javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; <span class="comment"># 压缩文件类型</span></span><br><span class="line"><span class="attribute">gzip_vary</span> <span class="literal">on</span>; <span class="comment"># 和http头有关系,加个vary头,给代理服务器用的,有的浏览器支持压缩,有的不支持,所以避免浪费不支持的也压缩,所以根据客户端的HTTP头来判断,是否需要压缩</span></span><br></pre></td></tr></table></figure><p>修改后记得执行 <code>nginx -s reload</code></p><p>一般浏览器都已支持.gz 的资源文件,在 http 请求的 Request Headers 中能看到 Accept-Encoding:gzip,加载速度会提升很大。</p><p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200721180126.png" alt=""></p><h2 id="去掉打包后的-console"><a href="#去掉打包后的-console" class="headerlink" title="去掉打包后的 console"></a>去掉打包后的 console</h2><blockquote><p><strong>使用 babel-plugin-transform-remove-console 插件</strong></p></blockquote><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">cnpm install babel-plugin-transform-remove-<span class="built_in">console</span> --save-dev</span><br></pre></td></tr></table></figure><p>【babel.config.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><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> plugins = [<span class="string">"@vue/babel-plugin-transform-vue-jsx"</span>];</span><br><span class="line"><span class="comment">// 生产环境移除console</span></span><br><span class="line"><span class="keyword">if</span> (process.env.NODE_ENV === <span class="string">"production"</span>) {</span><br><span class="line"> plugins.push(<span class="string">"transform-remove-console"</span>);</span><br><span class="line">}</span><br><span class="line"><span class="built_in">module</span>.exports = {</span><br><span class="line"> plugins: plugins,</span><br><span class="line"> presets: [<span class="string">"@vue/cli-plugin-babel/preset"</span>],</span><br><span class="line">};</span><br></pre></td></tr></table></figure><p>打包部署后,生产环境的 console 就全部去掉了~</p><h2 id="图片懒加载"><a href="#图片懒加载" class="headerlink" title="图片懒加载"></a>图片懒加载</h2><blockquote><p><strong>使用 vue-lazyload</strong></p></blockquote><ul><li>安装依赖</li></ul><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">cnpm i vue-lazyload -S</span><br></pre></td></tr></table></figure><ul><li>main.js 中直接引用</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> VueLazyload <span class="keyword">from</span> <span class="string">"vue-lazyload"</span>;</span><br><span class="line"></span><br><span class="line">Vue.use(VueLazyload);</span><br><span class="line"></span><br><span class="line"><span class="comment">// or with options</span></span><br><span class="line">Vue.use(VueLazyload, {</span><br><span class="line"> <span class="comment">//预加载高度</span></span><br><span class="line"> preLoad: <span class="number">1.3</span>,</span><br><span class="line"> <span class="comment">//错误时显示的图片</span></span><br><span class="line"> error: <span class="string">"static/about111.jpg"</span>,</span><br><span class="line"> <span class="comment">//图片加载中显示的图片</span></span><br><span class="line"> loading: <span class="string">"static/img/loading.gif"</span>,</span><br><span class="line"> <span class="comment">//尝试加载次数</span></span><br><span class="line"> attempt: <span class="number">1</span>,</span><br><span class="line">});</span><br></pre></td></tr></table></figure><ul><li>在组件中使用时,将 img 标签的 src 换成 v-lazy:</li></ul><ol><li>未使用懒加载前的代码:</li></ol><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">li</span>></span><span class="tag"><<span class="name">img</span> <span class="attr">class</span>=<span class="string">"g-img1"</span> <span class="attr">src</span>=<span class="string">"static/1.jpg"</span> <span class="attr">alt</span>=<span class="string">""</span> /></span><span class="tag"></<span class="name">li</span>></span></span><br></pre></td></tr></table></figure><ol><li>使用懒加载后的代码:</li></ol><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">li</span>></span><span class="tag"><<span class="name">img</span> <span class="attr">class</span>=<span class="string">"g-img1"</span> <span class="attr">v-lazy</span>=<span class="string">"'static/1.jpg'"</span> <span class="attr">alt</span>=<span class="string">""</span> /></span><span class="tag"></<span class="name">li</span>></span></span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 性能优化 </category>
</categories>
<tags>
<tag> 性能优化 </tag>
</tags>
</entry>
<entry>
<title>前端常用小方法合集</title>
<link href="/2020/06/03/vue%E5%B8%B8%E7%94%A8%E5%B0%8F%E6%96%B9%E6%B3%95%E5%90%88%E9%9B%86/"/>
<url>/2020/06/03/vue%E5%B8%B8%E7%94%A8%E5%B0%8F%E6%96%B9%E6%B3%95%E5%90%88%E9%9B%86/</url>
<content type="html"><![CDATA[<p><img src="https://s1.ax1x.com/2020/06/03/tUoQN8.png" alt=""></p><p>记录一下 项目中经常使用的小方法</p><a id="more"></a><h2 id="vue相关"><a href="#vue相关" class="headerlink" title="vue相关"></a>vue相关</h2><h3 id="一:获取-url-地址栏参数"><a href="#一:获取-url-地址栏参数" class="headerlink" title="一:获取 url 地址栏参数"></a>一:获取 url 地址栏参数</h3><p>例如:/placeList?id=1;</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">this</span>.$route.query.id(id为连接上的参数名称);</span><br></pre></td></tr></table></figure><h3 id="二:向下一个页面传递对象-query-传参"><a href="#二:向下一个页面传递对象-query-传参" class="headerlink" title="二:向下一个页面传递对象 (query 传参)"></a>二:向下一个页面传递对象 (query 传参)</h3><p>父.vue</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">this</span>.$router.push({</span><br><span class="line"> path: <span class="string">"/placeAdd"</span>,</span><br><span class="line"> query: item,</span><br><span class="line">});</span><br><span class="line"><span class="comment">//path和query均为固定key名</span></span><br><span class="line"><span class="comment">//path:跳转路径</span></span><br><span class="line"><span class="comment">//query: 传递参数对象</span></span><br><span class="line"><span class="comment">//item:数组对象</span></span><br></pre></td></tr></table></figure><p>子.vue</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">this</span>.$route.query.item;</span><br></pre></td></tr></table></figure><h3 id="三:父组件向子组件传值"><a href="#三:父组件向子组件传值" class="headerlink" title="三:父组件向子组件传值"></a>三:父组件向子组件传值</h3><p>父.vue</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></pre></td><td class="code"><pre><span class="line"><span class="comment">/*引入子组件*/</span></span><br><span class="line"><child-v ref=<span class="string">"chil"</span>><<span class="regexp">/child-v>;</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">/</span>*script</span><br><span class="line"> *showHover为子元素内的方法*<span class="regexp">/</span></span><br><span class="line"><span class="regexp">this.$refs.chil.showMessage("父组件调用子组件方法啦");</span></span><br></pre></td></tr></table></figure><p>子.vue</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></pre></td><td class="code"><pre><span class="line"><span class="comment">//只需要正常定义方法接参即可</span></span><br><span class="line">methods: {</span><br><span class="line"> showMessage(text) {</span><br><span class="line"> <span class="built_in">console</span>.log(text)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="四:父子组件相互调用"><a href="#四:父子组件相互调用" class="headerlink" title="四:父子组件相互调用"></a>四:父子组件相互调用</h3><h4 id="vue2-x"><a href="#vue2-x" class="headerlink" title="vue2.x"></a>vue2.x</h4><ul><li><p>vue 子组件调用父组件方法:</p><p> 子组件:this.$emit(‘xx’);</p><p> 父组件:定义 yy 方法,并在引用子组件时传参,如@xx=”yy”</p></li><li><p>vue 父组件调用子组件方法:</p><p> 子组件:定义 xx 方法</p><p> 父组件:引用子组件时加上 ref=”yy”,调用方法为 this.$refs.yy.xx()</p></li></ul><h4 id="vue3-x"><a href="#vue3-x" class="headerlink" title="vue3.x"></a>vue3.x</h4><ul><li>vue 子组件调用父组件方法:</li><li>父组件:定义 yy 方法,并在引用子组件时传参,如@xx=”yy”</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//子组件</span></span><br><span class="line">setup(props, { emit }) {</span><br><span class="line"> <span class="keyword">const</span> clickEvent = <span class="function"><span class="params">()</span> =></span> {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"clickEvent"</span>);</span><br><span class="line"> <span class="comment">//调用父组件的方法,并传值</span></span><br><span class="line"> emit(<span class="string">"sendMesg"</span>, state.result);</span><br><span class="line">};</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="五:阻止父元素冒泡事件"><a href="#五:阻止父元素冒泡事件" class="headerlink" title="五:阻止父元素冒泡事件"></a>五:阻止父元素冒泡事件</h3><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">div</span> @<span class="attr">click</span>=<span class="string">"a"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"b"</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></pre></td></tr></table></figure><p>当触发 button 的事件 a 时,b 事件也会被触发</p><p>解决办法:在 button 上添加@click.stop=”b”,来阻止事件冒泡。</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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">div</span> @<span class="attr">click</span>=<span class="string">"a"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">button</span> @<span class="attr">click.stop</span>=<span class="string">"b"</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></pre></td></tr></table></figure><h3 id="六:vue-修改-data-数据后页面未渲染"><a href="#六:vue-修改-data-数据后页面未渲染" class="headerlink" title="六:vue 修改 data 数据后页面未渲染"></a>六:vue 修改 data 数据后页面未渲染</h3><ul><li>强制渲染</li></ul><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">this</span>.$forceUpdate();</span><br></pre></td></tr></table></figure><ul><li>使用 Vue.set</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Vue.set(target, key, value);</span><br><span class="line"></span><br><span class="line"><span class="comment">// target:要更改的数据源(可以是对象或者数组)</span></span><br><span class="line"><span class="comment">// key:要更改的具体数据</span></span><br><span class="line"><span class="comment">// value :重新赋的值</span></span><br></pre></td></tr></table></figure><h3 id=""><a href="#" class="headerlink" title=""></a></h3><h2 id="js相关"><a href="#js相关" class="headerlink" title="js相关"></a>js相关</h2><h3 id="一:数组操作"><a href="#一:数组操作" class="headerlink" title="一:数组操作"></a>一:数组操作</h3><h4 id="去掉指定数组对象-id-相同的元素"><a href="#去掉指定数组对象-id-相同的元素" class="headerlink" title="去掉指定数组对象 id 相同的元素"></a>去掉指定数组对象 id 相同的元素</h4><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">arr.splice(arr.findIndex(item => item.id == id), 1)</span><br></pre></td></tr></table></figure><h4 id="过滤对象数组中key值相同的数据"><a href="#过滤对象数组中key值相同的数据" class="headerlink" title="过滤对象数组中key值相同的数据"></a>过滤对象数组中key值相同的数据</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr =[</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"count"</span>: <span class="number">1095</span>,</span><br><span class="line"> <span class="string">"month"</span>: <span class="string">"三月"</span>,</span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"count"</span>: <span class="number">1106</span>,</span><br><span class="line"> <span class="string">"month"</span>: <span class="string">"三月"</span>,</span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"count"</span>: <span class="number">987</span>,</span><br><span class="line"> <span class="string">"month"</span>: <span class="string">"四月"</span>,</span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"count"</span>: <span class="number">1166</span>,</span><br><span class="line"> <span class="string">"month"</span>: <span class="string">"四月"</span>,</span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"count"</span>: <span class="number">753</span>,</span><br><span class="line"> <span class="string">"month"</span>: <span class="string">"五月"</span>,</span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"count"</span>: <span class="number">891</span>,</span><br><span class="line"> <span class="string">"month"</span>: <span class="string">"五月"</span>,</span><br><span class="line"> }</span><br><span class="line">];</span><br><span class="line"><span class="keyword">const</span> res = <span class="keyword">new</span> <span class="built_in">Map</span>();</span><br><span class="line"><span class="keyword">const</span> new2 = arr.filter(<span class="function"><span class="params">item</span> =></span> !res.has(item.month) && res.set(item.month, <span class="number">1</span>));</span><br><span class="line"><span class="built_in">console</span>.log(arr.length, new2);</span><br></pre></td></tr></table></figure><h4 id="数组去重"><a href="#数组去重" class="headerlink" title="数组去重"></a>数组去重</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>];</span><br><span class="line"><span class="keyword">let</span> newArr = [...new <span class="built_in">Set</span>(arr)];</span><br><span class="line"></span><br><span class="line"><span class="comment">//结果:newArr = [1, 2, 3, 4, 5, 6]</span></span><br></pre></td></tr></table></figure><h4 id="随机取数组对象"><a href="#随机取数组对象" class="headerlink" title="随机取数组对象"></a>随机取数组对象</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getArrayItems</span>(<span class="params">arr, num</span>) </span>{</span><br><span class="line"> <span class="comment">//新建一个数组,将传入的数组复制过来,用于运算,而不要直接操作传入的数组;</span></span><br><span class="line"> <span class="keyword">var</span> temp_array = <span class="keyword">new</span> <span class="built_in">Array</span>();</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> index <span class="keyword">in</span> arr) {</span><br><span class="line"> temp_array.push(arr[index]);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//取出的数值项,保存在此数组</span></span><br><span class="line"> <span class="keyword">var</span> return_array = <span class="keyword">new</span> <span class="built_in">Array</span>();</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < num; i++) {</span><br><span class="line"> <span class="comment">//判断如果数组还有可以取出的元素,以防下标越界</span></span><br><span class="line"> <span class="keyword">if</span> (temp_array.length > <span class="number">0</span>) {</span><br><span class="line"> <span class="comment">//在数组中产生一个随机索引</span></span><br><span class="line"> <span class="keyword">var</span> arrIndex = <span class="built_in">Math</span>.floor(<span class="built_in">Math</span>.random() * temp_array.length);</span><br><span class="line"> <span class="comment">//将此随机索引的对应的数组元素值复制出来</span></span><br><span class="line"> return_array[i] = temp_array[arrIndex];</span><br><span class="line"> <span class="comment">//然后删掉此索引的数组元素,这时候temp_array变为新的数组</span></span><br><span class="line"> temp_array.splice(arrIndex, <span class="number">1</span>);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">//数组中数据项取完后,退出循环,比如数组本来只有10项,但要求取出20项.</span></span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> return_array;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="排序-操作"><a href="#排序-操作" class="headerlink" title="排序/操作"></a>排序/操作</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a=[<span class="number">1</span>,<span class="number">2</span>,<span class="number">13</span>,<span class="number">4</span>,<span class="number">5</span>]</span><br><span class="line"></span><br><span class="line"><span class="comment">//倒序</span></span><br><span class="line">a.reverse();<span class="comment">//[5, 4, 13, 2, 1]</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//默认按照转换为的字符串的诸个字符的Unicode位点进行排序</span></span><br><span class="line">a.sort();<span class="comment">//[1,13,2,4,5]</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 针对数字排序</span></span><br><span class="line"><span class="comment">* 如果 小于 0 ,那么 a 会被排列到 b 之前;</span></span><br><span class="line"><span class="comment">* 如果 等于 0 , a 和 b 的相对位置不变。</span></span><br><span class="line"><span class="comment">* 如果 大于 0 , b 会被排列到 a 之前。</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">arr.sort(<span class="function">(<span class="params">a, b</span>) =></span> a - b);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">a.unshift();<span class="comment">//5,代表数组长度;</span></span><br><span class="line">a.unshift(<span class="number">0</span>);<span class="comment">//返回6,数组长度;此时a=[0, 1, 2, 3, 4, 5];</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//取出数组第一位</span></span><br><span class="line">a.shift();<span class="comment">//1,不仅将数据取出,而且改变了数组,此时a=[2, 3, 4, 5]</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//取出数组最后一位</span></span><br><span class="line">a.pop();<span class="comment">//5,一样也是改变了数组,此时a=[1, 2, 3, 4]</span></span><br></pre></td></tr></table></figure><h3 id="二:限制能输入数字类型-小数点"><a href="#二:限制能输入数字类型-小数点" class="headerlink" title="二:限制能输入数字类型+小数点"></a>二:限制能输入数字类型+小数点</h3><ul><li>纯整数</li></ul><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">onkeyup = <span class="string">"value=value.replace(/[^d]/g,'')"</span>;</span><br></pre></td></tr></table></figure><ul><li>数字类型+小数点</li></ul><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">oninput</span>=<span class="string">"value=value.replace(/[^\d.]/g,'')"</span> /></span></span><br></pre></td></tr></table></figure><ul><li>限制输入两位小数</li></ul><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">input</span> @<span class="attr">input</span>=<span class="string">"handleInput2"</span> <span class="attr">onkeyup</span>=<span class="string">"value=value.replace(/[^\d.]/g,'')"</span> /></span> //</span><br><span class="line"></span><br><span class="line"><span class="comment"><!--</span></span><br><span class="line"><span class="comment">通过正则过滤小数点后两位, </span></span><br><span class="line"><span class="comment">handleInput2(e) { </span></span><br><span class="line"><span class="comment">this.valuet =(e.match(/^\d*(\.?\d{0,2})/g)[0]) || null </span></span><br><span class="line"><span class="comment">}</span></span><br><span class="line"><span class="comment">--></span></span><br></pre></td></tr></table></figure><h3 id="三:时间戳转化为时间"><a href="#三:时间戳转化为时间" class="headerlink" title="三:时间戳转化为时间"></a>三:时间戳转化为时间</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//将时间戳转化为日期</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">timestampToTime</span>(<span class="params">timestamp</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> date = <span class="keyword">new</span> <span class="built_in">Date</span>(timestamp); <span class="comment">//时间戳为10位需*1000,时间戳为13位的话不需乘1000</span></span><br><span class="line"> <span class="keyword">var</span> Y = date.getFullYear() + <span class="string">"-"</span>;</span><br><span class="line"> <span class="keyword">var</span> M =</span><br><span class="line"> (date.getMonth() + <span class="number">1</span> < <span class="number">10</span></span><br><span class="line"> ? <span class="string">"0"</span> + (date.getMonth() + <span class="number">1</span>)</span><br><span class="line"> : date.getMonth() + <span class="number">1</span>) + <span class="string">"-"</span>;</span><br><span class="line"> <span class="keyword">var</span> D = (date.getDate() < <span class="number">10</span> ? <span class="string">"0"</span> + date.getDate() : date.getDate()) + <span class="string">" "</span>;</span><br><span class="line"> <span class="keyword">var</span> h =</span><br><span class="line"> (date.getHours() < <span class="number">10</span> ? <span class="string">"0"</span> + date.getHours() : date.getHours()) + <span class="string">":"</span>;</span><br><span class="line"> <span class="keyword">var</span> m =</span><br><span class="line"> (date.getMinutes() < <span class="number">10</span> ? <span class="string">"0"</span> + date.getMinutes() : date.getMinutes()) +</span><br><span class="line"> <span class="string">":"</span>;</span><br><span class="line"> <span class="keyword">var</span> s = date.getSeconds() < <span class="number">10</span> ? <span class="string">"0"</span> + date.getSeconds() : date.getSeconds();</span><br><span class="line"> <span class="keyword">return</span> Y + M + D + h + m + s;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="四:计算两个时间相差日期"><a href="#四:计算两个时间相差日期" class="headerlink" title="四:计算两个时间相差日期"></a>四:计算两个时间相差日期</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//startData,endData均为时间戳</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">timesDiffer</span>(<span class="params">startData, endData</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> date1 = startData; <span class="comment">//开始时间</span></span><br><span class="line"> <span class="keyword">var</span> date2 = endData; <span class="comment">//结束时间</span></span><br><span class="line"> <span class="keyword">var</span> date3 = <span class="built_in">parseInt</span>(date2) - <span class="built_in">parseInt</span>(date1); <span class="comment">//时间差的毫秒数</span></span><br><span class="line"> <span class="comment">//计算出相差天数</span></span><br><span class="line"> <span class="keyword">var</span> days = <span class="built_in">Math</span>.floor(date3 / (<span class="number">24</span> * <span class="number">3600</span> * <span class="number">1000</span>));</span><br><span class="line"> <span class="comment">//计算出小时数</span></span><br><span class="line"> <span class="keyword">var</span> leave1 = date3 % (<span class="number">24</span> * <span class="number">3600</span> * <span class="number">1000</span>); <span class="comment">//计算天数后剩余的毫秒数</span></span><br><span class="line"> <span class="keyword">var</span> hours = <span class="built_in">Math</span>.floor(leave1 / (<span class="number">3600</span> * <span class="number">1000</span>));</span><br><span class="line"> <span class="comment">//计算相差分钟数</span></span><br><span class="line"> <span class="keyword">var</span> leave2 = leave1 % (<span class="number">3600</span> * <span class="number">1000</span>); <span class="comment">//计算小时数后剩余的毫秒数</span></span><br><span class="line"> <span class="keyword">var</span> minutes = <span class="built_in">Math</span>.floor(leave2 / (<span class="number">60</span> * <span class="number">1000</span>));</span><br><span class="line"></span><br><span class="line"> <span class="comment">//计算相差秒数</span></span><br><span class="line"> <span class="keyword">var</span> leave3 = leave2 % (<span class="number">60</span> * <span class="number">1000</span>); <span class="comment">//计算分钟数后剩余的毫秒数</span></span><br><span class="line"> <span class="keyword">var</span> seconds = <span class="built_in">Math</span>.round(leave3 / <span class="number">1000</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (hours <= <span class="number">0</span> && minutes <= <span class="number">0</span> && seconds <= <span class="number">0</span>) {</span><br><span class="line"> <span class="comment">//时间小于0s的操作</span></span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> hours = hours < <span class="number">10</span> ? <span class="string">"0"</span> + hours : hours;</span><br><span class="line"> minutes = minutes < <span class="number">10</span> ? <span class="string">"0"</span> + minutes : minutes;</span><br><span class="line"> seconds = seconds < <span class="number">10</span> ? <span class="string">"0"</span> + seconds : seconds;</span><br><span class="line"> <span class="keyword">return</span> hours + <span class="string">":"</span> + minutes + <span class="string">":"</span> + seconds;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="五:下载文件流"><a href="#五:下载文件流" class="headerlink" title="五:下载文件流"></a>五:下载文件流</h3><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//下载文件流</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">operateFile</span>(<span class="params">file, filename</span>) </span>{</span><br><span class="line"> <span class="comment">// var filename = '';</span></span><br><span class="line"> <span class="keyword">let</span> url = <span class="built_in">window</span>.URL.createObjectURL(file.data);</span><br><span class="line"> <span class="keyword">let</span> link = <span class="built_in">document</span>.createElement(<span class="string">"a"</span>);</span><br><span class="line"> link.style.display = <span class="string">"none"</span>;</span><br><span class="line"> link.href = url;</span><br><span class="line"> link.setAttribute(<span class="string">"download"</span>, filename + <span class="string">".xls"</span>);</span><br><span class="line"> <span class="built_in">document</span>.body.appendChild(link);</span><br><span class="line"> link.click();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="六:计算-n-天前后的日期"><a href="#六:计算-n-天前后的日期" class="headerlink" title="六:计算 n 天前后的日期"></a>六:计算 n 天前后的日期</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getBeforeDate</span>(<span class="params">strDate, n</span>) </span>{</span><br><span class="line"> <span class="comment">//strDate 为字符串日期 如:'2020-01-01' n为你要传入的参数,当前为0,前一天为-1,后一天为1</span></span><br><span class="line"> <span class="keyword">let</span> datt = strDate.split(<span class="string">"-"</span>); <span class="comment">//这边给定一个特定时间</span></span><br><span class="line"> <span class="keyword">var</span> newDate = <span class="keyword">new</span> <span class="built_in">Date</span>(datt[<span class="number">0</span>], datt[<span class="number">1</span>] - <span class="number">1</span>, datt[<span class="number">2</span>]);</span><br><span class="line"> <span class="keyword">let</span> befminuts = newDate.getTime() + <span class="number">1000</span> * <span class="number">60</span> * <span class="number">60</span> * <span class="number">24</span> * <span class="built_in">parseInt</span>(n); <span class="comment">//计算前几天用减,计算后几天用加,最后一个就是多少天的数量</span></span><br><span class="line"> <span class="keyword">let</span> beforeDat = <span class="keyword">new</span> <span class="built_in">Date</span>();</span><br><span class="line"> beforeDat.setTime(befminuts);</span><br><span class="line"> <span class="keyword">let</span> befMonth = beforeDat.getMonth() + <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">let</span> mon = befMonth >= <span class="number">10</span> ? befMonth : <span class="string">"0"</span> + befMonth;</span><br><span class="line"> <span class="keyword">let</span> befDate = beforeDat.getDate();</span><br><span class="line"> <span class="keyword">let</span> da = befDate >= <span class="number">10</span> ? befDate : <span class="string">"0"</span> + befDate;</span><br><span class="line"> <span class="keyword">var</span> newDate = beforeDat.getFullYear() + <span class="string">"-"</span> + mon + <span class="string">"-"</span> + da;</span><br><span class="line"> <span class="built_in">console</span>.log(newDate);</span><br><span class="line"> <span class="keyword">return</span> newDate;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="七:ASCII-码排序参数"><a href="#七:ASCII-码排序参数" class="headerlink" title="七:ASCII 码排序参数"></a>七:ASCII 码排序参数</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">objKeySort</span>(<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="comment">//obj排序对象</span></span><br><span class="line"> <span class="keyword">var</span> newkey = <span class="built_in">Object</span>.keys(obj).sort();</span><br><span class="line"> <span class="keyword">var</span> newObj = {}; <span class="comment">//创建一个新的对象,用于存放排好序的键值对</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < newkey.length; i++) {</span><br><span class="line"> newObj[newkey[i]] = obj[newkey[i]];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> newObj; <span class="comment">//返回排好序的新对象</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="八:如何平滑滚动到页面顶部"><a href="#八:如何平滑滚动到页面顶部" class="headerlink" title="八:如何平滑滚动到页面顶部"></a>八:如何平滑滚动到页面顶部</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> scrollToTop = <span class="function"><span class="params">()</span> =></span> { </span><br><span class="line"> <span class="keyword">const</span> c = <span class="built_in">document</span>.documentElement.scrollTop || <span class="built_in">document</span>.body.scrollTop; </span><br><span class="line"> <span class="keyword">if</span> (c > <span class="number">0</span>) { </span><br><span class="line"> <span class="built_in">window</span>.requestAnimationFrame(scrollToTop); </span><br><span class="line"> <span class="built_in">window</span>.scrollTo(<span class="number">0</span>, c - c / <span class="number">8</span>); </span><br><span class="line"> } </span><br><span class="line">} </span><br><span class="line"> </span><br><span class="line"><span class="comment">// 事例 </span></span><br><span class="line">scrollToTop(); <span class="comment">//返回排好序的新对象</span></span><br></pre></td></tr></table></figure><h3 id="九:如何获得两个日期之间的差异(以天为单位)"><a href="#九:如何获得两个日期之间的差异(以天为单位)" class="headerlink" title="九:如何获得两个日期之间的差异(以天为单位)"></a>九:如何获得两个日期之间的差异(以天为单位)</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> getDaysDiffBetweenDates = <span class="function">(<span class="params">dateInitial, dateFinal</span>) =></span> </span><br><span class="line"> (dateFinal - dateInitial) / (<span class="number">1000</span> * <span class="number">3600</span> * <span class="number">24</span>); </span><br><span class="line"> </span><br><span class="line"><span class="comment">// 事例 </span></span><br><span class="line">getDaysDiffBetweenDates(<span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">'2020-12-13'</span>), <span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">'2020-12-22'</span>)); <span class="comment">// 9</span></span><br></pre></td></tr></table></figure><!-- ### vuex状态管理模式 --><h3 id="十:解析动态json数据"><a href="#十:解析动态json数据" class="headerlink" title="十:解析动态json数据"></a>十:解析动态json数据</h3><p><img src="https://s1.ax1x.com/2020/07/15/UwwdeO.png" alt="UwwdeO.png"></p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 取出key和value的值。再封装到一个数组里面。 </span></span><br><span class="line"><span class="keyword">let</span> userData = 动态json数据;</span><br><span class="line"><span class="keyword">let</span> userArray=[];</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> [key, value] <span class="keyword">of</span> <span class="built_in">Object</span>.entries(userData)) {</span><br><span class="line"> userArray.push({<span class="string">"时间"</span>:key,<span class="string">"人数"</span>:value});</span><br><span class="line"> <span class="built_in">console</span>.log(userArray)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//只取key值:</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> key <span class="keyword">of</span> <span class="built_in">Object</span>.keys(obj)) {</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//只取value值 </span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> value <span class="keyword">of</span> <span class="built_in">Object</span>.values(obj)) {</span><br><span class="line"> </span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="十一:点击复制文本"><a href="#十一:点击复制文本" class="headerlink" title="十一:点击复制文本"></a>十一:点击复制文本</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> httpUrl = <span class="keyword">this</span>.herfAddress; <span class="comment">//此处为需要被复制的文本</span></span><br><span class="line"><span class="keyword">let</span> oInput = <span class="built_in">document</span>.createElement(<span class="string">"input"</span>);</span><br><span class="line">oInput.value = httpUrl;</span><br><span class="line"><span class="built_in">document</span>.body.appendChild(oInput);</span><br><span class="line">oInput.select(); <span class="comment">// 选择对象</span></span><br><span class="line"><span class="built_in">document</span>.execCommand(<span class="string">"Copy"</span>); <span class="comment">// 执行浏览器复制命令</span></span><br><span class="line">oInput.className = <span class="string">"oInput"</span>;</span><br><span class="line">oInput.style.display = <span class="string">"none"</span>;</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">"链接复制成功"</span>);</span><br></pre></td></tr></table></figure><h3 id="十二:禁止微信用户修改字体大小"><a href="#十二:禁止微信用户修改字体大小" class="headerlink" title="十二:禁止微信用户修改字体大小"></a>十二:禁止微信用户修改字体大小</h3><p>微信 webview 内置了调整字体大小的功能,用户可以根据实际情况进行调整。</p><p><strong>安卓:</strong></p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><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"><script></span><br><span class="line"> (<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> WeixinJSBridge == <span class="string">"object"</span> && <span class="keyword">typeof</span> WeixinJSBridge.invoke == <span class="string">"function"</span>) {</span><br><span class="line"> handleFontSize();</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">document</span>.addEventListener) {</span><br><span class="line"> <span class="built_in">document</span>.addEventListener(<span class="string">"WeixinJSBridgeReady"</span>, handleFontSize, <span class="literal">false</span>);</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (<span class="built_in">document</span>.attachEvent) {</span><br><span class="line"> <span class="built_in">document</span>.attachEvent(<span class="string">"WeixinJSBridgeReady"</span>, handleFontSize);</span><br><span class="line"> <span class="built_in">document</span>.attachEvent(<span class="string">"onWeixinJSBridgeReady"</span>, handleFontSize); }</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">handleFontSize</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="comment">// 设置网页字体为默认大小</span></span><br><span class="line"> WeixinJSBridge.invoke(<span class="string">'setFontSizeCallback'</span>, { <span class="string">'fontSize'</span> : <span class="number">0</span> });</span><br><span class="line"> <span class="comment">// 重写设置网页字体大小的事件</span></span><br><span class="line"> WeixinJSBridge.on(<span class="string">'menu:setfont'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> WeixinJSBridge.invoke(<span class="string">'setFontSizeCallback'</span>, { <span class="string">'fontSize'</span> : <span class="number">0</span> });</span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line"> })();</span><br><span class="line"><<span class="regexp">/script></span></span><br></pre></td></tr></table></figure><p><strong>ios</strong></p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">body</span> {</span><br><span class="line"> <span class="comment">/* IOS禁止微信调整字体大小 */</span></span><br><span class="line"> <span class="attribute">-webkit-text-size-adjust</span>: <span class="number">100%</span> <span class="meta">!important</span>;</span><br><span class="line"> <span class="attribute">text-size-adjust</span>: <span class="number">100%</span> <span class="meta">!important</span>;</span><br><span class="line"> <span class="attribute">-moz-text-size-adjust</span>: <span class="number">100%</span> <span class="meta">!important</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="十三:px-与-rem-换算"><a href="#十三:px-与-rem-换算" class="headerlink" title="十三:px 与 rem 换算"></a>十三:px 与 rem 换算</h3><p>rem 是根据 iPhone6 换算的,根据设计出的 px 尺寸除以 100 带上 rem 单位即可,平常 14px 换算成 rem 是 0.28rem</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//rem换算</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">doc, win</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> docEl = doc.documentElement,</span><br><span class="line"> resizeEvt = <span class="string">"orientationchange"</span> <span class="keyword">in</span> <span class="built_in">window</span> ? <span class="string">"orientationchange"</span> : <span class="string">"resize"</span>,</span><br><span class="line"> recalc = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> clientWidth = docEl.clientWidth;</span><br><span class="line"> <span class="keyword">if</span> (!clientWidth) <span class="keyword">return</span>;</span><br><span class="line"> <span class="keyword">if</span> (clientWidth >= <span class="number">750</span>) {</span><br><span class="line"> docEl.style.fontSize = <span class="string">"100px"</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> docEl.style.fontSize = <span class="number">100</span> * (clientWidth / <span class="number">750</span>) + <span class="string">"px"</span>;</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> <span class="keyword">if</span> (!doc.addEventListener) <span class="keyword">return</span>;</span><br><span class="line"> win.addEventListener(resizeEvt, recalc, <span class="literal">false</span>);</span><br><span class="line"> doc.addEventListener(<span class="string">"DOMContentLoaded"</span>, recalc, <span class="literal">false</span>);</span><br><span class="line">})(<span class="built_in">document</span>, <span class="built_in">window</span>);</span><br></pre></td></tr></table></figure><h4 id="十四、取整"><a href="#十四、取整" class="headerlink" title="十四、取整"></a>十四、取整</h4><h5 id="1、只保留整数部分"><a href="#1、只保留整数部分" class="headerlink" title="1、只保留整数部分"></a>1、只保留整数部分</h5><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="built_in">parseInt</span>(<span class="number">5.1234</span>); <span class="comment">// 5</span></span><br></pre></td></tr></table></figure><h5 id="2、向下取整-(效果等同于parseInt)"><a href="#2、向下取整-(效果等同于parseInt)" class="headerlink" title="2、向下取整 (效果等同于parseInt)"></a>2、向下取整 (效果等同于parseInt)</h5><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="built_in">Math</span>.floor(<span class="number">5.1234</span>); <span class="comment">// 5</span></span><br></pre></td></tr></table></figure><h5 id="3、向上取整-(有小数,整数部分-1)"><a href="#3、向上取整-(有小数,整数部分-1)" class="headerlink" title="3、向上取整 (有小数,整数部分+1)"></a>3、向上取整 (有小数,整数部分+1)</h5><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="built_in">Math</span>.ceil(<span class="number">5.1234</span>); <span class="comment">// 6</span></span><br></pre></td></tr></table></figure><h5 id="4、四舍五入"><a href="#4、四舍五入" class="headerlink" title="4、四舍五入"></a>4、四舍五入</h5><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Math</span>.round(<span class="number">5.1234</span>); <span class="comment">// 5</span></span><br><span class="line"><span class="built_in">Math</span>.round(<span class="number">5.6789</span>); <span class="comment">// 6</span></span><br></pre></td></tr></table></figure><h5 id="5、绝对值"><a href="#5、绝对值" class="headerlink" title="5、绝对值"></a>5、绝对值</h5><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="built_in">Math</span>.abs(<span class="number">-1</span>); <span class="comment">// 1</span></span><br></pre></td></tr></table></figure><h5 id="6、返回两数中的较大者"><a href="#6、返回两数中的较大者" class="headerlink" title="6、返回两数中的较大者"></a>6、返回两数中的较大者</h5><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="built_in">Math</span>.max(<span class="number">1</span>,<span class="number">2</span>); <span class="comment">// 2</span></span><br></pre></td></tr></table></figure><h5 id="7、返回两数中的较小者"><a href="#7、返回两数中的较小者" class="headerlink" title="7、返回两数中的较小者"></a>7、返回两数中的较小者</h5><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="built_in">Math</span>.min(<span class="number">1</span>,<span class="number">2</span>); <span class="comment">// 1</span></span><br></pre></td></tr></table></figure><h5 id="8、随机数"><a href="#8、随机数" class="headerlink" title="8、随机数"></a>8、随机数</h5><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="built_in">Math</span>.random();</span><br></pre></td></tr></table></figure><h4 id="十五、拷贝"><a href="#十五、拷贝" class="headerlink" title="十五、拷贝"></a>十五、拷贝</h4><h5 id="1、浅拷贝"><a href="#1、浅拷贝" class="headerlink" title="1、浅拷贝"></a>1、浅拷贝</h5><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a=[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>]</span><br><span class="line"><span class="keyword">let</span> b=a;</span><br><span class="line">b.push(<span class="number">4</span>);</span><br><span class="line"><span class="comment">//这时输出a的值为[1,2,3,4]; b的值也是[1,2,3,4]</span></span><br></pre></td></tr></table></figure><h5 id="2、深拷贝"><a href="#2、深拷贝" class="headerlink" title="2、深拷贝"></a>2、深拷贝</h5><blockquote><p>方法一</p></blockquote><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a=[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>]</span><br><span class="line"><span class="keyword">let</span> b=a.concat();</span><br><span class="line">b.push(<span class="number">4</span>);</span><br><span class="line"><span class="comment">//此时 a的值为[1, 2, 3],b的值为[1,2,3,4]</span></span><br></pre></td></tr></table></figure><blockquote><p>方法二</p></blockquote><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a=[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>]</span><br><span class="line"><span class="keyword">let</span> b=<span class="built_in">Object</span>.assign({}, a);</span><br><span class="line">b.push(<span class="number">4</span>);</span><br><span class="line"><span class="comment">//此时 a的值为[1, 2, 3],b的值为[1,2,3,4]</span></span><br></pre></td></tr></table></figure><h2 id="css相关"><a href="#css相关" class="headerlink" title="css相关"></a>css相关</h2><h3 id="一:超出部分省略"><a href="#一:超出部分省略" class="headerlink" title="一:超出部分省略"></a>一:超出部分省略</h3><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*行数限制,超出部分省略*/</span></span><br><span class="line"><span class="selector-tag">display</span>: <span class="selector-tag">-webkit-box</span>;</span><br><span class="line"><span class="selector-tag">-webkit-box-orient</span>: <span class="selector-tag">vertical</span>;</span><br><span class="line"><span class="selector-tag">-webkit-line-clamp</span>: 2;</span><br><span class="line"><span class="selector-tag">overflow</span>: <span class="selector-tag">hidden</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*宽度限制,超出部分省略*/</span></span><br><span class="line"><span class="selector-tag">max-width</span>: 4<span class="selector-class">.6rem</span>;</span><br><span class="line"><span class="selector-tag">overflow</span>: <span class="selector-tag">hidden</span>;</span><br><span class="line"><span class="selector-tag">text-overflow</span>: <span class="selector-tag">ellipsis</span>;</span><br><span class="line"><span class="selector-tag">white-space</span>: <span class="selector-tag">nowrap</span>;</span><br></pre></td></tr></table></figure><h3 id="二:文本两端对齐"><a href="#二:文本两端对齐" class="headerlink" title="二:文本两端对齐"></a>二:文本两端对齐</h3><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">text-align</span>: <span class="selector-tag">justify</span>;</span><br></pre></td></tr></table></figure><h3 id="三:中文间隔"><a href="#三:中文间隔" class="headerlink" title="三:中文间隔"></a>三:中文间隔</h3><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">letter-spacing</span>: 4<span class="selector-tag">px</span>;</span><br></pre></td></tr></table></figure><h3 id="四:英文自动换行"><a href="#四:英文自动换行" class="headerlink" title="四:英文自动换行"></a>四:英文自动换行</h3><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">word-wrap</span>: <span class="selector-tag">break-word</span></span><br></pre></td></tr></table></figure><h3 id="五:禁止图片长按保存"><a href="#五:禁止图片长按保存" class="headerlink" title="五:禁止图片长按保存"></a>五:禁止图片长按保存</h3><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">pointer-events</span><span class="selector-pseudo">:none</span>;</span><br></pre></td></tr></table></figure><h3 id="六:背景渐变色"><a href="#六:背景渐变色" class="headerlink" title="六:背景渐变色"></a>六:背景渐变色</h3><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">background</span>: <span class="selector-tag">-webkit-linear-gradient</span>(<span class="selector-tag">left</span> <span class="selector-tag">top</span>,<span class="selector-id">#F98530</span>, <span class="selector-id">#FAB03D</span>);</span><br></pre></td></tr></table></figure><h3 id="七:input-placeholder样式"><a href="#七:input-placeholder样式" class="headerlink" title="七:input placeholder样式"></a>七:input placeholder样式</h3><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">input</span><span class="selector-pseudo">::-webkit-input-placeholder</span> {</span><br><span class="line"> <span class="attribute">opacity</span>:<span class="number">0.3</span>;</span><br><span class="line"> <span class="attribute">color</span>:<span class="number">#fff</span> ;</span><br><span class="line"> }</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> vue </category>
</categories>
<tags>
<tag> vue </tag>
</tags>
</entry>
<entry>
<title>yarn使安装健步如飞</title>
<link href="/2020/06/01/yarn%E4%BD%BF%E5%AE%89%E8%A3%85%E5%81%A5%E6%AD%A5%E5%A6%82%E9%A3%9E/"/>
<url>/2020/06/01/yarn%E4%BD%BF%E5%AE%89%E8%A3%85%E5%81%A5%E6%AD%A5%E5%A6%82%E9%A3%9E/</url>
<content type="html"><![CDATA[<p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200721180103.png" alt=""></p><p>yarn 快速、可靠、安全的依赖管理工具。</p><a id="more"></a><h3 id="看栗子说话"><a href="#看栗子说话" class="headerlink" title="看栗子说话"></a>看栗子说话</h3><p><font color=#f44>采用 cnpm 和 yarn 安装 webpack 工具</font></p><p><strong>cnpm 效果图(总花费 60s)</strong></p><p><img src="https://s1.ax1x.com/2020/06/02/tYrdQH.png" alt="cnpm 效果图"></p><p><strong>yarn 效果图(总花费 11s)</strong></p><p><img src="https://s1.ax1x.com/2020/06/02/tYs3cQ.png" alt="yarn 效果图"></p><h3 id="🙄-为什么要用-yarn"><a href="#🙄-为什么要用-yarn" class="headerlink" title="🙄 为什么要用 yarn"></a>🙄 为什么要用 yarn</h3><p><strong>速度超快</strong></p><p>Yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率,因此安装速度更快。</p><p><strong>超级安全</strong></p><p>在执行代码之前,Yarn 会通过算法校验每个安装包的完整性。</p><p><strong>超级可靠</strong></p><p>使用详细、简洁的锁文件格式和明确的安装算法,Yarn 能够保证在不同系统上无差异的工作。</p><h3 id="🧐-更新淘宝源"><a href="#🧐-更新淘宝源" class="headerlink" title="🧐 更新淘宝源"></a>🧐 更新淘宝源</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># yarn+淘宝源,飞一般的速度</span><br><span class="line">yarn config <span class="keyword">get</span> registry</span><br><span class="line"># https://registry.yarnpkg.com</span><br><span class="line"></span><br><span class="line">yarn config <span class="keyword">set</span> registry https://registry.npm.taobao.org</span><br><span class="line"></span><br><span class="line">yarn config <span class="keyword">get</span> registry</span><br><span class="line"># https://registry.npm.taobao.org</span><br></pre></td></tr></table></figure><h3 id="从-npm-迁移"><a href="#从-npm-迁移" class="headerlink" title="从 npm 迁移"></a>从 npm 迁移</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">npm install === yarn</span><br><span class="line"></span><br><span class="line">npm install [package] --save === yarn add [package]</span><br><span class="line"></span><br><span class="line">npm install [package] --save-dev === yarn add [package] --dev</span><br><span class="line"></span><br><span class="line">npm install [package] --global === yarn global add [package]</span><br><span class="line"></span><br><span class="line">npm uninstall [package] --save === yarn remove [package]</span><br><span class="line"></span><br><span class="line">rm -rf node_modules && npm install === yarn upgrade</span><br></pre></td></tr></table></figure><p><a href="https://yarn.bootcss.com" target="_blank" rel="noopener">yarn 官网</a></p>]]></content>
<categories>
<category> vue </category>
<category> node </category>
</categories>
<tags>
<tag> npm,yarn </tag>
</tags>
</entry>
<entry>
<title>linux常用命令</title>
<link href="/2020/05/31/linux%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/"/>
<url>/2020/05/31/linux%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/</url>
<content type="html"><![CDATA[<p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200721180321.jpeg" alt="linux"></p><p>Linux,全称 GNU/Linux,是一套免费使用和自由传播的类 UNIX 操作系统</p><a id="more"></a><h3 id="文件相关"><a href="#文件相关" class="headerlink" title="文件相关"></a>文件相关</h3><ul><li><p>cd dirname 目录路径跳转</p></li><li><p>mkdir dirname 创建目录</p></li><li><p>touch filename 创建文件</p></li><li><p>vi filename 编辑文件</p></li><li><p>cat filename 查看文件</p></li><li><p>echo ‘123456’ >> test.txt 在 test.txt 文件尾部增加一行 ‘123123’</p></li><li><p>echo ‘123456’ > test.txt 覆盖 test.txt 文件的内容为 ‘hello world’</p></li><li><p>rm text.txt 删除 text.txt 文件</p></li><li><p>rm -r textdir 删除 testdir 目录</p></li><li><p>rm -rf 强制删除</p></li><li><p>wget 文件地址 下载文件</p></li><li><p>tar zxvf 文件 (如 apache-tomcat-9.0.17.tar.zg:解压缩文件 tar 后面的参数 z 代表 gz 等结尾的压缩文件,x 代表解压缩,v 显示所有的解压过程,f 代表归档的名字)</p></li><li><p>tar zcvf 文件名(如 apache-tomcat-9.0.18.tar.gz) 文件目录:讲文件目录 压缩为 文件名为 apache-tomcat-9.0.18.tar.gz</p></li><li><p>ps -ef | grep 进程名: 查看进程(筛选进程)</p></li><li><p>kill -9 进程 pid: 杀死 进程</p></li></ul><h3 id="查看系统服务"><a href="#查看系统服务" class="headerlink" title="查看系统服务"></a>查看系统服务</h3><ul><li>service 服务名 status: 如 (service sshd status :查询 ssh 服务的运行状态)</li><li>service 服务名 stop :关闭某个服务</li><li>service 服务名 restart:重启某个服务</li><li>systemctl status firewalld.service: 查看某个服务运行状态</li></ul><h3 id="使用-root-用户连接-linux-服务器"><a href="#使用-root-用户连接-linux-服务器" class="headerlink" title="使用 root 用户连接 linux 服务器"></a>使用 root 用户连接 linux 服务器</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 root@ip</span><br></pre></td></tr></table></figure><h3 id="防火墙设置"><a href="#防火墙设置" class="headerlink" title="防火墙设置"></a>防火墙设置</h3><p>检查防火墙</p><p><code>firewall-cmd --permanent --query-port=10022/tcp</code></p><p>如果是 no,就添加一下</p><p><code>firewall-cmd --permanent --add-port=10022/tcp</code></p><p>成功后再重载防火墙</p><p><code>firewall-cmd --reload</code></p><p>再重启下防火墙服务</p><p><code>systemctl restart firewalld.service</code></p>]]></content>
<categories>
<category> linux </category>
</categories>
<tags>
<tag> linux </tag>
</tags>
</entry>
<entry>
<title>常用Markdown语法</title>
<link href="/2020/05/24/%E5%B8%B8%E7%94%A8Markdown%E8%AF%AD%E6%B3%95/"/>
<url>/2020/05/24/%E5%B8%B8%E7%94%A8Markdown%E8%AF%AD%E6%B3%95/</url>
<content type="html"><![CDATA[<p><img src="https://cdn.jsdelivr.net/gh/superliebe/picGo/20200721180345.png" alt=""></p><p>Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档</p><a id="more"></a><blockquote><p>💡 Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档。</p></blockquote><h2 id="一、标题"><a href="#一、标题" class="headerlink" title="一、标题"></a>一、标题</h2><ul><li>使用 # 表示标题,一级标题使用一个 # ,二级标题使用两个 ## ,以此类推,共有六级标题。# 和标题之间记得有个空格哦。</li></ul><h1 id="一级标题"><a href="#一级标题" class="headerlink" title="一级标题"></a>一级标题</h1><h2 id="二级标题"><a href="#二级标题" class="headerlink" title="二级标题"></a>二级标题</h2><h3 id="三级标题"><a href="#三级标题" class="headerlink" title="三级标题"></a>三级标题</h3><h4 id="四级标题"><a href="#四级标题" class="headerlink" title="四级标题"></a>四级标题</h4><h5 id="五级标题"><a href="#五级标题" class="headerlink" title="五级标题"></a>五级标题</h5><h6 id="六级标题"><a href="#六级标题" class="headerlink" title="六级标题"></a>六级标题</h6><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"># 一级标题</span><br><span class="line">## 二级标题</span><br><span class="line">### 三级标题</span><br><span class="line">#### 四级标题</span><br><span class="line">##### 五级标题</span><br><span class="line">###### 六级标题</span><br></pre></td></tr></table></figure><h2 id="二、引用"><a href="#二、引用" class="headerlink" title="二、引用"></a>二、引用</h2><p>使用 > 表示引用, >> 表示引用里面再套一层引用,依次类推。</p><blockquote><p>❗ 部分编辑器不支持多级嵌套,建议不要使用</p></blockquote><p><em>示例</em></p><blockquote><p>这是一级引用</p><blockquote><p>这是二级引用</p><blockquote><p>这是三级引用</p></blockquote></blockquote></blockquote><blockquote><p>这是一级引用</p></blockquote><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></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">> > > 这是三级引用</span><br><span class="line"></span><br><span class="line">> 这是一级引用</span><br></pre></td></tr></table></figure><h2 id="三、代码块"><a href="#三、代码块" class="headerlink" title="三、代码块"></a>三、代码块</h2><p>使用 3 个连续的` 符号包围起来表示代码块。可以指定语言来使代码高亮。</p><p><em>示例</em></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">$(document).ready(function() {</span><br><span class="line"> $('pre code').each(function(i, block) {</span><br><span class="line"> hljs.highlightBlock(block);</span><br><span class="line"> });</span><br><span class="line">});</span><br></pre></td></tr></table></figure><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$(<span class="built_in">document</span>).ready(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> $(<span class="string">"pre code"</span>).each(<span class="function"><span class="keyword">function</span> (<span class="params">i, block</span>) </span>{</span><br><span class="line"> hljs.highlightBlock(block);</span><br><span class="line"> });</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p><strong>行内代码</strong></p><p>使用``表示行内代码。本页部分文字中间的英文字母就是使用行内代码标记标记的。</p><p><em>示例</em></p><p>这是 <code>javascript</code> 代码</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">这是`javascript`代码</span><br></pre></td></tr></table></figure><h2 id="四、链接"><a href="#四、链接" class="headerlink" title="四、链接"></a>四、链接</h2><p>使用 <font color=#2196f3><code>[](link)</code></font> 表示行内链接。其中:</p><ul><li><p><font color=#2196f3>[]</font> 内的内容为要添加链接的文字。</p></li><li><p><font color=#2196f3>link</font> 为链接地址。</p></li></ul><p><em>示例</em></p><p>这是跳转<a href="https://www.baidu.com" target="_blank" rel="noopener">百度</a>的链接</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">这是跳转[百度](https://www.baidu.com)的链接</span><br></pre></td></tr></table></figure><h2 id="五、导入图片"><a href="#五、导入图片" class="headerlink" title="五、导入图片"></a>五、导入图片</h2><p>使用 <code>![Alt text](/path/to/img.jpg)</code> 导入图片。其中:</p><ul><li><font color=#2196f3>Alt text</font> 为如果图片无法显示时显示的文字;</li><li><font color=#2196f3>/path/to/img.jpg</font> 为图片所在路径;</li></ul><ol><li><strong>本地引用</strong>是图片直接存储到本地通过相对路径引用,无需网络连接</li><li><strong>上传图片</strong>将把图片上传至<a href="https://imgchr.com" target="_blank" rel="noopener">图床</a>,这样在文档或图片移动时认可访问图片</li></ol><p><em>示例</em></p><p><img src="https://i.loli.net/2020/03/14/I8wCZN4r9UltqTd.jpg" alt="Markdown"></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">![Markdown](https://i.loli.net/2020/03/14/I8wCZN4r9UltqTd.jpg)</span><br></pre></td></tr></table></figure><h2 id="六、Todo-List"><a href="#六、Todo-List" class="headerlink" title="六、Todo List"></a>六、Todo List</h2><p>小写 x 表示已完成, 空格表示未完成</p><ul><li><input checked="" disabled="" type="checkbox"> 支持数学公式</li><li><input checked="" disabled="" type="checkbox"> 支持 TodoList</li><li><input checked="" disabled="" type="checkbox"> 支持自定义样式</li><li><input disabled="" type="checkbox"> 支持自定义图床</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></pre></td><td class="code"><pre><span class="line">- [x] 支持数学公式</span><br><span class="line">- [x] 支持TodoList</span><br><span class="line">- [x] 支持自定义样式</span><br><span class="line">- [ ] 支持自定义图床</span><br></pre></td></tr></table></figure><h2 id="七、粗体,斜体,高亮和删除线"><a href="#七、粗体,斜体,高亮和删除线" class="headerlink" title="七、粗体,斜体,高亮和删除线"></a>七、粗体,斜体,高亮和删除线</h2><ul><li>使用 <code>**</code> 表示<strong>粗体</strong>。</li></ul><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">**粗体**</span><br></pre></td></tr></table></figure><ul><li>使用 <code>*</code> 或者 <code>_</code> 表示 _斜体_。</li></ul><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">*斜体*</span><br></pre></td></tr></table></figure><ul><li>使用 <code>***</code> 表示 <strong><em>全部粗体和斜体</em></strong></li></ul><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">***全部粗体和斜体***</span><br></pre></td></tr></table></figure><ul><li>使用 <code>==</code> 表示 ==高亮==</li></ul><blockquote><p>❗ 部分编辑器不支持高亮</p></blockquote><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">==高亮==</span><br></pre></td></tr></table></figure><ul><li>使用<code>~~</code>表示 <del>删除</del></li></ul><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">~~删除~~</span><br></pre></td></tr></table></figure><h2 id="八、列表"><a href="#八、列表" class="headerlink" title="八、列表"></a>八、列表</h2><p>使用 <code>1. 1. 1.</code> 表示有序列表,使用 <code>*</code> 或 <code>-</code> 或 <code>+</code> 表示无序列表。</p><ol><li><p>无序列表或有序列表标记和后面的文字之间要有一个空格隔开。</p></li><li><p>有序列表标记不是按照你写的数字进行显示的,而是根据当前有序列表标记所在位置显示的,如示例 1 所示。</p></li><li><p>无序列表的项目符号是按照实心圆、空心圆、实心方格的层级关系递进的,如例 2 所示。通常情况下,同一层级使用同一种标记表示,便于自己查看和管理。</p></li></ol><p>_示例 1_:有序列表</p><ol><li>第 1 行</li><li>第 2 行</li><li>第 3 行</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></pre></td><td class="code"><pre><span class="line">1. 第1行</span><br><span class="line">1. 第2行</span><br><span class="line">1. 第3行</span><br></pre></td></tr></table></figure><p>_示例 2_:无序列表</p><ul><li>一级无序列表内容<ul><li>二级无序列表内容<ul><li>三级无序列表内容</li></ul></li></ul></li></ul><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></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></pre></td></tr></table></figure><h2 id="九、分割线"><a href="#九、分割线" class="headerlink" title="九、分割线"></a>九、分割线</h2><p>使用 <code>---</code> 或者 <code>***</code> 或者 <code>* * *</code> 表示水平分割线。</p><ol><li>只要 <code>*</code> 或者 <code>-</code> 大于等于三个就可组成一条平行线。</li><li>使用 <code>---</code> 作为水平分割线时,要在它的前后都空一行,防止 <code>---</code> 被当成标题标记的表示方式。</li></ol><p><em>示例</em></p><hr><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">---</span><br><span class="line"></span><br><span class="line">***</span><br><span class="line"></span><br><span class="line">* * *</span><br></pre></td></tr></table></figure><h2 id="十、表格"><a href="#十、表格" class="headerlink" title="十、表格"></a>十、表格</h2><p>默认表格<br>Heading | Heading | Heading<br>——- | ——- | ——-<br>Cell | Cell | Cell<br>Cell | Cell | Cell</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">Heading | Heading | Heading</span><br><span class="line">------- | ------- | -------</span><br><span class="line">Cell | Cell | Cell</span><br><span class="line">Cell | Cell | Cell</span><br></pre></td></tr></table></figure><p>对齐方式:<br>Heading | Heading | Heading<br>:—– | :—-: | ——:<br>Left | Center | Right<br>Left | Center | Right</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">Heading | Heading | Heading</span><br><span class="line">:----- | :----: | ------:</span><br><span class="line">Left | Center | Right</span><br><span class="line">Left | Center | Right</span><br></pre></td></tr></table></figure><h2 id="十一、emoji"><a href="#十一、emoji" class="headerlink" title="十一、emoji"></a>十一、emoji</h2><p>使用 <code>:emoji</code>代码: 在 markdown 里添加 emoji 👻</p><p><a href="https://www.webfx.com/tools/emoji-cheat-sheet/" target="_blank" rel="noopener">点击这里查看所有支持的 emoji 代码</a></p><blockquote><p>❗ 部分编辑器不支持 emoji code <br><br>建议直接输入 emoji,<a href="https://www.emojidaquan.com" target="_blank" rel="noopener">点击这里查看并复制 emoji</a></p></blockquote>]]></content>
<categories>
<category> Markdown </category>
</categories>
<tags>
<tag> Markdown </tag>
</tags>
</entry>
<entry>
<title>kbone+vue创建支持web和微信小程序的项目</title>
<link href="/2020/04/26/kbone-vue%E5%88%9B%E5%BB%BA%E6%94%AF%E6%8C%81web%E5%92%8C%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E7%9A%84%E9%A1%B9%E7%9B%AE/"/>
<url>/2020/04/26/kbone-vue%E5%88%9B%E5%BB%BA%E6%94%AF%E6%8C%81web%E5%92%8C%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E7%9A%84%E9%A1%B9%E7%9B%AE/</url>
<content type="html"><![CDATA[<p><img src="https://pic1.zhimg.com/v2-7a735d09695218bec1d69477f6a243bc_1200x500.jpg" alt=""></p><p>Kbone 是腾讯开发的解决微信小程序和 Web 端同构的框架。简单来说就是只写一套代码,编译结果可以在 web 端和小程序上运行。</p><a id="more"></a><h3 id="Kbone-特点"><a href="#Kbone-特点" class="headerlink" title="Kbone 特点"></a>Kbone 特点</h3><ol><li>支持多种前端框架,如:vue、react、preact 等,并且能够保持该框架的完整;</li><li>页面渲染的内容需要用 js 中的 document 方法来渲染,提供常用的 DOM/BOM 接口;</li><li>小程序端开发仍可使用小程序本身特性;</li><li>更专注于微信和小程序的开发;</li><li>Webpack 与 Kbone 是强耦合的,开发需借助 Webpack 提供的基本依赖</li></ol><h3 id="一:安装-kbone-cli"><a href="#一:安装-kbone-cli" class="headerlink" title="一:安装 kbone-cli"></a>一:安装 kbone-cli</h3><p>命令行安装<strong>kbone-cli</strong>脚手架,用于创建<strong>kbone</strong>项目</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">cnpm install -g kbone-cli</span><br></pre></td></tr></table></figure><p><img src="https://img-blog.csdnimg.cn/20200426100558340.png" alt=""></p><h3 id="二:创建对应的-kbone-项目"><a href="#二:创建对应的-kbone-项目" class="headerlink" title="二:创建对应的 kbone 项目"></a>二:创建对应的 kbone 项目</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">kbone init my-app</span><br></pre></td></tr></table></figure><p>可以根据自己所用到的技术选择对应的选项(本项目采用<strong>kbone+vue</strong>),回车确定。</p><p><img src="https://img-blog.csdnimg.cn/20200426100919899.png" alt=""></p><p>创建成功之后,基本目录情况和 vue-cli4 目录差不多,其中在 build 文件夹里 miniprogram.config.js 进行小程序的配置,比如 appid 之类</p><p><img src="https://img-blog.csdnimg.cn/20200426101814636.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1cGVyS00=,size_16,color_FFFFFF,t_70" alt=""></p><h3 id="三:在-main-js-中引入-kbone-ui,使项目-ui-更贴近微信风格(可选)"><a href="#三:在-main-js-中引入-kbone-ui,使项目-ui-更贴近微信风格(可选)" class="headerlink" title="三:在 main.js 中引入 kbone-ui,使项目 ui 更贴近微信风格(可选)"></a>三:在 main.js 中引入 kbone-ui,使项目 ui 更贴近微信风格(可选)</h3><p>安装 kbone-ui</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">npm i kbone-ui</span><br></pre></td></tr></table></figure><p>main.js 中引入样式文件</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> KboneUI <span class="keyword">from</span> <span class="string">"kbone-ui"</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="string">"kbone-ui/lib/weui/weui.css"</span>;</span><br><span class="line"></span><br><span class="line">Vue.use(KboneUI);</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">// 开发小程序端</span><br><span class="line">npm run mp</span><br><span class="line"></span><br><span class="line">// 开发 Web 端</span><br><span class="line">npm run web</span><br><span class="line"></span><br><span class="line">// 构建 Web 端</span><br><span class="line">npm run build</span><br></pre></td></tr></table></figure><p><strong>web端运行效果图</strong></p><p><img src="https://img-blog.csdnimg.cn/20200426144813734.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1cGVyS00=,size_16,color_FFFFFF,t_70" alt=""></p><p><strong>小程序端运行效果图</strong><br>npm run mp 之后 会在dis文件中创建对应的小程序文件,使用微信开发者工具打开预览,</p><p><img src="https://img-blog.csdnimg.cn/20200426145140903.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1cGVyS00=,size_16,color_FFFFFF,t_70" alt=""></p><p><font color=#f44>注意:官方提醒,尽量使用kbone-ui开发,目前功能正在逐步完善兼容,使用其他组件库可能会出现问题</font></p><p><strong><font color=blue><a href="https://wechat-miniprogram.github.io/kbone/docs/ui/intro/quickstart.html#安装使用" target="_blank" rel="noopener">kbone 官方文档</a></font></strong></p>]]></content>
<categories>
<category> vue </category>
<category> 微信小程序 </category>
</categories>
<tags>
<tag> kbone,vue </tag>
</tags>
</entry>
</search>