-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathatom.xml
More file actions
530 lines (261 loc) · 707 KB
/
atom.xml
File metadata and controls
530 lines (261 loc) · 707 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>IMAGINE</title>
<subtitle>IMAGINE的搬砖日志</subtitle>
<link href="http://imagineblog.host/atom.xml" rel="self"/>
<link href="http://imagineblog.host/"/>
<updated>2022-08-31T08:04:19.377Z</updated>
<id>http://imagineblog.host/</id>
<author>
<name>Peng</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>解决Element-ui选择器(ElSelect)因数据量大导致页面卡顿的问题</title>
<link href="http://imagineblog.host/scroll_select/"/>
<id>http://imagineblog.host/scroll_select/</id>
<published>2022-08-31T07:30:45.000Z</published>
<updated>2022-08-31T08:04:19.377Z</updated>
<content type="html"><![CDATA[<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><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br></pre></td><td class="code"><pre><span class="line"><!--</span><br><span class="line"> * @Author: luopeng</span><br><span class="line"> * @Description: el-select下拉滚动加载</span><br><span class="line"> * @<span class="built_in">Date</span>: <span class="number">2022</span>-<span class="number">08</span>-<span class="number">31</span> <span class="number">09</span>:<span class="number">22</span>:<span class="number">49</span></span><br><span class="line"> * @LastEditTime: <span class="number">2022</span>-<span class="number">08</span>-<span class="number">31</span> <span class="number">15</span>:<span class="number">53</span>:<span class="number">35</span></span><br><span class="line">--></span><br><span class="line"><template></span><br><span class="line"> <div <span class="class"><span class="keyword">class</span></span>=<span class="string">"content"</span>></span><br><span class="line"> <el-select</span><br><span class="line"> :value=<span class="string">"value"</span></span><br><span class="line"> clearable</span><br><span class="line"> :size=<span class="string">"size"</span></span><br><span class="line"> :multiple=<span class="string">"multiple"</span></span><br><span class="line"> :filter-method=<span class="string">"filterMethod"</span></span><br><span class="line"> v-bind=<span class="string">"$attrs"</span></span><br><span class="line"> v-select-showmore=<span class="string">"showMore(rangeNumber)"</span></span><br><span class="line"> @visible-change=<span class="string">"visibleChange"</span></span><br><span class="line"> @input=<span class="string">"handleInput"</span></span><br><span class="line"> @change=<span class="string">"handleChange"</span></span><br><span class="line"> ></span><br><span class="line"> <el-option</span><br><span class="line"> v-<span class="keyword">for</span>=<span class="string">"item in options.slice(0, rangeNumber)"</span></span><br><span class="line"> :key=<span class="string">"item.value"</span></span><br><span class="line"> :label=<span class="string">"item.label"</span></span><br><span class="line"> :value=<span class="string">"item[valueKey]"</span></span><br><span class="line"> ></el-option></span><br><span class="line"> </el-select></span><br><span class="line"> </div></span><br><span class="line"></template></span><br><span class="line"></span><br><span class="line"><script></span><br><span class="line"><span class="keyword">import</span> { debounce } <span class="keyword">from</span> <span class="string">'lodash'</span>;</span><br><span class="line"><span class="keyword">import</span> { deepClone } <span class="keyword">from</span> <span class="string">'@/utils'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> {</span><br><span class="line"> props: {</span><br><span class="line"> value: { <span class="attr">type</span>: [<span class="built_in">String</span>, <span class="built_in">Number</span>, <span class="built_in">Array</span>] },</span><br><span class="line"> list: {</span><br><span class="line"> type: <span class="built_in">Array</span>,</span><br><span class="line"> <span class="keyword">default</span>: <span class="function">() =></span> [],</span><br><span class="line"> },</span><br><span class="line"> valueKey: {</span><br><span class="line"> type: <span class="built_in">String</span>,</span><br><span class="line"> <span class="keyword">default</span>: <span class="string">'value'</span>,</span><br><span class="line"> },</span><br><span class="line"> size: {</span><br><span class="line"> type: <span class="built_in">String</span>,</span><br><span class="line"> <span class="keyword">default</span>: <span class="string">'mini'</span>,</span><br><span class="line"> },</span><br><span class="line"> multiple: {</span><br><span class="line"> type: <span class="built_in">Boolean</span>,</span><br><span class="line"> <span class="keyword">default</span>: <span class="literal">false</span>,</span><br><span class="line"> },</span><br><span class="line"> },</span><br><span class="line"> <span class="function"><span class="title">data</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> options: [],</span><br><span class="line"> rangeNumber: <span class="number">10</span>,</span><br><span class="line"> };</span><br><span class="line"> },</span><br><span class="line"> computed: {</span><br><span class="line"> <span class="function"><span class="title">initValue</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="keyword">const</span> newArr = deepClone(<span class="built_in">this</span>.list);</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">this</span>.value) {</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">this</span>.multiple) {</span><br><span class="line"> <span class="keyword">const</span> checks = <span class="built_in">this</span>.list.filter(<span class="function">(<span class="params">item</span>) =></span> <span class="built_in">this</span>.value.includes(item[<span class="built_in">this</span>.valueKey]));</span><br><span class="line"> checks.forEach(<span class="function">(<span class="params">item</span>) =></span> {</span><br><span class="line"> <span class="keyword">const</span> index = <span class="built_in">this</span>.list.indexOf(item);</span><br><span class="line"> newArr.unshift(newArr.splice(index, <span class="number">1</span>)[<span class="number">0</span>]);</span><br><span class="line"> });</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">const</span> checks = <span class="built_in">this</span>.list.find(<span class="function">(<span class="params">item</span>) =></span> item[<span class="built_in">this</span>.valueKey] === <span class="built_in">this</span>.value);</span><br><span class="line"> <span class="keyword">const</span> index = <span class="built_in">this</span>.list.indexOf(checks);</span><br><span class="line"> newArr.unshift(newArr.splice(index, <span class="number">1</span>)[<span class="number">0</span>]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> newArr;</span><br><span class="line"> },</span><br><span class="line"> },</span><br><span class="line"> methods: {</span><br><span class="line"> <span class="comment">// elementui下拉超过7条会出滚动条,如果初始不出滚动条无法触发loadMore方法</span></span><br><span class="line"> <span class="function"><span class="title">showMore</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="comment">/* eslint-disable no-return-assign */</span></span><br><span class="line"> <span class="keyword">return</span> <span class="function">() =></span> (<span class="built_in">this</span>.rangeNumber += <span class="number">10</span>); <span class="comment">// 每次滚动到底部可以新增条数</span></span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// 筛选方法</span></span><br><span class="line"> filterMethod: debounce(<span class="function"><span class="keyword">function</span> <span class="title">filterFun</span>(<span class="params">filterVal</span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> query = filterVal?.trim() || <span class="string">''</span>;</span><br><span class="line"> <span class="keyword">if</span> (query) {</span><br><span class="line"> <span class="comment">/* eslint-disable max-len */</span></span><br><span class="line"> <span class="keyword">const</span> filterArr = <span class="built_in">this</span>.list.filter(<span class="function">(<span class="params">item</span>) =></span> item.label?.toLowerCase().includes(query.toLowerCase()));</span><br><span class="line"> <span class="built_in">this</span>.options = filterArr;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">// this.options = this.list;</span></span><br><span class="line"> <span class="built_in">this</span>.options = <span class="built_in">this</span>.initValue;</span><br><span class="line"> }</span><br><span class="line"> }, <span class="number">300</span>),</span><br><span class="line"> <span class="comment">// 下拉框出现时,调用过滤方法</span></span><br><span class="line"> <span class="function"><span class="title">visibleChange</span>(<span class="params">flag</span>)</span> {</span><br><span class="line"> <span class="keyword">if</span> (flag) {</span><br><span class="line"> <span class="built_in">this</span>.filterMethod();</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="title">handleChange</span>(<span class="params">value</span>)</span> {</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">this</span>.multiple) {</span><br><span class="line"> <span class="keyword">const</span> selectList = <span class="built_in">this</span>.options.filter(<span class="function">(<span class="params">item</span>) =></span> value.includes(item[<span class="built_in">this</span>.valueKey]));</span><br><span class="line"> <span class="built_in">this</span>.$emit(<span class="string">'change'</span>, selectList);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">const</span> selectObj = <span class="built_in">this</span>.options.find(<span class="function">(<span class="params">item</span>) =></span> item[<span class="built_in">this</span>.valueKey] === value);</span><br><span class="line"> <span class="built_in">this</span>.$emit(<span class="string">'change'</span>, selectObj);</span><br><span class="line"> },</span><br><span class="line"> <span class="function"><span class="title">handleInput</span>(<span class="params">val</span>)</span> {</span><br><span class="line"> <span class="built_in">this</span>.$emit(<span class="string">'input'</span>, val);</span><br><span class="line"> },</span><br><span class="line"> },</span><br><span class="line"> <span class="function"><span class="title">mounted</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="built_in">this</span>.options = <span class="built_in">this</span>.initValue;</span><br><span class="line"> },</span><br><span class="line"> directives: {</span><br><span class="line"> <span class="string">'select-showmore'</span>: <span class="function">(<span class="params">el, binding</span>) =></span> {</span><br><span class="line"> <span class="keyword">const</span> selectWrapDom = el.querySelector(<span class="string">'.el-select-dropdown .el-select-dropdown__wrap'</span>);</span><br><span class="line"> <span class="keyword">if</span> (selectWrapDom) {</span><br><span class="line"> <span class="keyword">const</span> scrollFun = <span class="function">() =></span> {</span><br><span class="line"> <span class="comment">/* 如果元素滚动到底, 下面等式返回true, 没有则返回false */</span></span><br><span class="line"> <span class="keyword">const</span> condition = selectWrapDom.scrollHeight - selectWrapDom.scrollTop <= selectWrapDom.clientHeight;</span><br><span class="line"> <span class="keyword">if</span> (condition) binding.value();</span><br><span class="line"> };</span><br><span class="line"> selectWrapDom.addEventListener(<span class="string">'scroll'</span>, scrollFun);</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"> },</span><br><span class="line">};</span><br><span class="line"></script></span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="l</summary>
<category term="Vue" scheme="http://imagineblog.host/categories/Vue/"/>
<category term="Vue" scheme="http://imagineblog.host/tags/Vue/"/>
</entry>
<entry>
<title>el-form表单封装</title>
<link href="http://imagineblog.host/form_component/"/>
<id>http://imagineblog.host/form_component/</id>
<published>2022-01-15T07:30:45.000Z</published>
<updated>2022-08-31T08:04:19.377Z</updated>
<content type="html"><![CDATA[<h2 id="缘由"><a href="#缘由" class="headerlink" title="缘由"></a>缘由</h2><blockquote><p>系统页面大部分为<code>form+tabel</code>的结构,系统复杂起来代码就看起来非常冗余,要修改起来也很麻烦,于是决定将表单封装起来。</p></blockquote><hr><h2 id="结构"><a href="#结构" class="headerlink" title="结构"></a>结构</h2><ol><li><p>业务与逻辑区分</p><ul><li>新建<code>const.js</code>文件,处理表单逻辑</li></ul></li><li><p>配置化</p><ul><li><code>json</code>对象化配置表单属性</li></ul></li><li><p>扩展&特殊处理</p><ul><li>配置<code>slot</code>插槽</li></ul></li></ol><hr><h2 id="开始"><a href="#开始" class="headerlink" title="开始"></a>开始</h2><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><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br></pre></td><td class="code"><pre><span class="line"><template></span><br><span class="line"> <el-form</span><br><span class="line"> ref=<span class="string">"form"</span></span><br><span class="line"> :id=<span class="string">"formConfig.id"</span></span><br><span class="line"> :<span class="class"><span class="keyword">class</span></span>=<span class="string">"formConfig.className"</span></span><br><span class="line"> :label-width=<span class="string">"formConfig.labelWidth || '100px'"</span></span><br><span class="line"> :size=<span class="string">"formConfig.size || 'medium'"</span></span><br><span class="line"> :rules=<span class="string">"formConfig.rules"</span></span><br><span class="line"> :model=<span class="string">"formData"</span></span><br><span class="line"> ></span><br><span class="line"> <template</span><br><span class="line"> v-<span class="keyword">for</span>=<span class="string">"(item, index) in getConfigList()"</span></span><br><span class="line"> :key=<span class="string">"index"</span></span><br><span class="line"> ></span><br><span class="line"> <el-form-item</span><br><span class="line"> :prop=<span class="string">"item.value"</span></span><br><span class="line"> :label=<span class="string">"item.label"</span></span><br><span class="line"> :label-width=<span class="string">"item.labelWidth"</span></span><br><span class="line"> :<span class="class"><span class="keyword">class</span></span>=<span class="string">"item.className"</span></span><br><span class="line"> ></span><br><span class="line"> <!-- solt --></span><br><span class="line"> <template v-<span class="keyword">if</span>=<span class="string">"item.type === 'slot'"</span>></span><br><span class="line"> <slot :name=<span class="string">"'form-' + item.value"</span> /></span><br><span class="line"> </template></span><br><span class="line"> <component</span><br><span class="line"> :is=<span class="string">"item.type"</span></span><br><span class="line"> v-model=<span class="string">"formData[item.value]"</span></span><br><span class="line"> :type=<span class="string">"item.dataType"</span></span><br><span class="line"> :picker-options=<span class="string">"item.timePickerOptions"</span></span><br><span class="line"> :clearable=<span class="string">"item.clearable"</span></span><br><span class="line"> :disabled=<span class="string">"item.disabled"</span></span><br><span class="line"> :start-placeholder=<span class="string">"item.startPlaceholder"</span></span><br><span class="line"> :end-placeholder=<span class="string">"item.endPlaceholder"</span></span><br><span class="line"> :range-separator=<span class="string">"item.rangeSeparator || '-'"</span></span><br><span class="line"> :filterable=<span class="string">"item.filterable"</span></span><br><span class="line"> :multiple=<span class="string">"item.multiple"</span></span><br><span class="line"> :collapse-tags=<span class="string">"item.collapseTags"</span></span><br><span class="line"> <span class="keyword">default</span>-first-option</span><br><span class="line"> :allow-create=<span class="string">"item.allowCreate"</span></span><br><span class="line"> :no-data-text=<span class="string">"item.noDataText || ''"</span></span><br><span class="line"> :placeholder=<span class="string">"getPlaceholder(item)"</span></span><br><span class="line"> :value-format=<span class="string">"item.valueFormat"</span></span><br><span class="line"> :format=<span class="string">"item.valueFormat"</span></span><br><span class="line"> :style=<span class="string">"{ width: item.width || '100%' }"</span></span><br><span class="line"> :maxlength=<span class="string">"item.maxLength"</span></span><br><span class="line"> :autosize=<span class="string">"item.autosize || { minRows: 2, maxRows: 10 }"</span></span><br><span class="line"> @click=<span class="string">"handleEvent(item.event, formData[item.value], 'click')"</span></span><br><span class="line"> @change=<span class="string">"handleEvent(item.event, formData[item.value], 'change')"</span></span><br><span class="line"> @input=<span class="string">"handleEvent(item.event, formData[item.value], 'input')"</span></span><br><span class="line"> @blur=<span class="string">"handleEvent(item.event, formData[item.value], 'blur')"</span></span><br><span class="line"> ></span><br><span class="line"> <template v-<span class="keyword">if</span>=<span class="string">"item.type === 'el-select'"</span>></span><br><span class="line"> <el-option</span><br><span class="line"> v-<span class="keyword">for</span>=<span class="string">"(childItem, childIndex) in listTypeInfo[item.list]"</span></span><br><span class="line"> :key=<span class="string">"`${childItem.value}${childIndex}`"</span></span><br><span class="line"> :label=<span class="string">"childItem.label"</span></span><br><span class="line"> :value=<span class="string">"childItem.value"</span></span><br><span class="line"> ></el-option></span><br><span class="line"> </template></span><br><span class="line"> {{ item.title || <span class="string">''</span> }}</span><br><span class="line"> </component></span><br><span class="line"> </el-form-item></span><br><span class="line"> </template></span><br><span class="line"> </el-form></span><br><span class="line"></template></span><br><span class="line"><script></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"> name: <span class="string">'FormItemComp'</span>,</span><br><span class="line"> <span class="function"><span class="title">data</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="keyword">return</span> { <span class="attr">formData</span>: {} };</span><br><span class="line"> },</span><br><span class="line"> props: {</span><br><span class="line"> <span class="comment">// 表单配置项</span></span><br><span class="line"> formConfig: {</span><br><span class="line"> type: <span class="built_in">Object</span>,</span><br><span class="line"> <span class="keyword">default</span>: <span class="function">() =></span> {},</span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// 表单数据</span></span><br><span class="line"> data: { <span class="attr">type</span>: <span class="built_in">Object</span> },</span><br><span class="line"> <span class="comment">// 下拉选项list</span></span><br><span class="line"> listTypeInfo: { <span class="attr">type</span>: <span class="built_in">Object</span> },</span><br><span class="line"> <span class="comment">// ref</span></span><br><span class="line"> refObj: { <span class="attr">type</span>: <span class="built_in">Object</span> },</span><br><span class="line"> },</span><br><span class="line"> watch: {</span><br><span class="line"> data: {</span><br><span class="line"> <span class="function"><span class="title">handler</span>(<span class="params">val</span>)</span> {</span><br><span class="line"> <span class="keyword">if</span> (!val) <span class="keyword">return</span>;</span><br><span class="line"> <span class="built_in">this</span>.formData = val;</span><br><span class="line"> <span class="comment">// 将form实例返回到父级</span></span><br><span class="line"> <span class="built_in">this</span>.$emit(<span class="string">'update:refObj'</span>, <span class="built_in">this</span>.$refs.form);</span><br><span class="line"> },</span><br><span class="line"> deep: <span class="literal">true</span>,</span><br><span class="line"> },</span><br><span class="line"> },</span><br><span class="line"> <span class="function"><span class="title">mounted</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="built_in">this</span>.formData = <span class="built_in">this</span>.data;</span><br><span class="line"> <span class="comment">// 将form实例返回到父级</span></span><br><span class="line"> <span class="built_in">this</span>.$emit(<span class="string">'update:refObj'</span>, <span class="built_in">this</span>.$refs.form);</span><br><span class="line"> },</span><br><span class="line"> methods: {</span><br><span class="line"> <span class="comment">// 获取字段列表</span></span><br><span class="line"> <span class="function"><span class="title">getConfigList</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>.formConfig.fieldList.filter(</span><br><span class="line"> (item) => !<span class="built_in">Object</span>.prototype.hasOwnProperty.call(item, <span class="string">'show'</span>)</span><br><span class="line"> || (<span class="built_in">Object</span>.prototype.hasOwnProperty.call(item, <span class="string">'show'</span>) && item.show),</span><br><span class="line"> );</span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// 得到placeholder的显示</span></span><br><span class="line"> <span class="function"><span class="title">getPlaceholder</span>(<span class="params">row</span>)</span> {</span><br><span class="line"> <span class="keyword">let</span> placeholder;</span><br><span class="line"> <span class="keyword">const</span> types = [<span class="string">'el-select'</span>, <span class="string">'el-date-picker'</span>];</span><br><span class="line"> <span class="keyword">if</span> (row.type === <span class="string">'el-input'</span>) {</span><br><span class="line"> placeholder = <span class="string">`请输入<span class="subst">${row.placeholder || <span class="string">''</span>}</span>`</span>;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (types.includes(row.type)) {</span><br><span class="line"> placeholder = <span class="string">`请选择<span class="subst">${row.placeholder || <span class="string">''</span>}</span>`</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> placeholder = row.label;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> placeholder;</span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// 表单事件派发</span></span><br><span class="line"> <span class="function"><span class="title">handleEvent</span>(<span class="params">event, data, type</span>)</span> {</span><br><span class="line"> <span class="built_in">this</span>.$emit(<span class="string">'handleEvent'</span>, { event, data, type });</span><br><span class="line"> },</span><br><span class="line"> },</span><br><span class="line">};</span><br><span class="line"></script></span><br><span class="line"></span><br></pre></td></tr></table></figure><hr><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// const.js</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> FormJson = {</span><br><span class="line"> id: <span class="string">'form'</span>,</span><br><span class="line"> rules: {},</span><br><span class="line"> labelWidth: <span class="string">'100px'</span>,</span><br><span class="line"> size: <span class="string">'mini'</span>,</span><br><span class="line"> className: <span class="string">'el-form-component'</span>,</span><br><span class="line"> fieldList: [</span><br><span class="line"> {</span><br><span class="line"> label: <span class="string">'名称:'</span>,</span><br><span class="line"> value: <span class="string">'name'</span>,</span><br><span class="line"> type: <span class="string">'el-select'</span>,</span><br><span class="line"> clearable: <span class="literal">true</span>,</span><br><span class="line"> list: <span class="string">'nameList'</span>,</span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> label: <span class="string">'来源:'</span>,</span><br><span class="line"> value: <span class="string">'source'</span>,</span><br><span class="line"> type: <span class="string">'el-select'</span>,</span><br><span class="line"> clearable: <span class="literal">true</span>,</span><br><span class="line"> list: <span class="string">'formSelect1'</span>,</span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> label: <span class="string">'主体:'</span>,</span><br><span class="line"> value: <span class="string">'subject'</span>,</span><br><span class="line"> type: <span class="string">'el-input'</span>,</span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> label: <span class="string">'分类:'</span>,</span><br><span class="line"> value: <span class="string">'nature'</span>,</span><br><span class="line"> type: <span class="string">'el-select'</span>,</span><br><span class="line"> clearable: <span class="literal">true</span>,</span><br><span class="line"> list: <span class="string">'formSelect2'</span>,</span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> label: <span class="string">'日期:'</span>,</span><br><span class="line"> value: <span class="string">'date'</span>,</span><br><span class="line"> type: <span class="string">'el-date-picker'</span>,</span><br><span class="line"> dataType: <span class="string">'daterange'</span>,</span><br><span class="line"> valueFormat: <span class="string">'yyyy-MM-dd'</span>,</span><br><span class="line"> startPlaceholder: <span class="string">'开始日期'</span>,</span><br><span class="line"> endPlaceholder: <span class="string">'结束日期'</span>,</span><br><span class="line"> rangeSeparator: <span class="string">'至'</span>,</span><br><span class="line"> clearable: <span class="literal">true</span>,</span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> label: <span class="string">'状态:'</span>,</span><br><span class="line"> value: <span class="string">'status'</span>,</span><br><span class="line"> type: <span class="string">'el-select'</span>,</span><br><span class="line"> clearable: <span class="literal">true</span>,</span><br><span class="line"> list: <span class="string">'projectStatus'</span>,</span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// slot插槽</span></span><br><span class="line"> {</span><br><span class="line"> label: <span class="string">''</span>,</span><br><span class="line"> value: <span class="string">'btn'</span>,</span><br><span class="line"> type: <span class="string">'slot'</span>,</span><br><span class="line"> colWidth: <span class="number">18</span>,</span><br><span class="line"> className: <span class="string">'text-right'</span>,</span><br><span class="line"> },</span><br><span class="line"> ],</span><br><span class="line">};</span><br></pre></td></tr></table></figure><hr><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></pre></td><td class="code"><pre><span class="line"><template></span><br><span class="line"> <FormItemComp</span><br><span class="line"> :formConfig=<span class="string">"FormJson"</span></span><br><span class="line"> :refObj.sync=<span class="string">"formRef"</span></span><br><span class="line"> :data=<span class="string">"formData"</span></span><br><span class="line"> :listTypeInfo=<span class="string">"listTypeInfo"</span></span><br><span class="line"> @handleEvent=<span class="string">"handleEvent"</span></span><br><span class="line"> ></span><br><span class="line"> <template slot=<span class="string">"form-btn"</span>></span><br><span class="line"> <div></span><br><span class="line"> <el-button type=<span class="string">"search"</span> @click=<span class="string">""</span>>查询</el-button></span><br><span class="line"> <el-button type=<span class="string">"reset"</span> @click=<span class="string">""</span>>重置</el-button></span><br><span class="line"> </div></span><br><span class="line"> </template></span><br><span class="line"> </FormItemComp></span><br><span class="line"></template></span><br><span class="line"></span><br><span class="line"><script></span><br><span class="line"><span class="keyword">import</span> FormItemComp <span class="keyword">from</span> <span class="string">'./FormItemComp'</span></span><br><span class="line"><span class="keyword">import</span> { FormJson } <span class="keyword">from</span> <span class="string">'./const.js'</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> {</span><br><span class="line"> <span class="function"><span class="title">data</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> FormJson,</span><br><span class="line"> formRef: <span class="literal">null</span>, <span class="comment">// form ref</span></span><br><span class="line"> formData: {</span><br><span class="line"> name: <span class="string">''</span>,</span><br><span class="line"> source: <span class="string">''</span>,</span><br><span class="line"> subject: <span class="string">''</span>,</span><br><span class="line"> nature: <span class="string">''</span>,</span><br><span class="line"> date: <span class="string">''</span>,</span><br><span class="line"> status: <span class="string">''</span>,</span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// el-select选项</span></span><br><span class="line"> listTypeInfo: {</span><br><span class="line"> formSelect1:[],</span><br><span class="line"> formSelect2:[],</span><br><span class="line"> projectStatus:[],</span><br><span class="line"> nameList:[],</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"> components: { FormItemComp },</span><br><span class="line"></span><br><span class="line"> methods: {</span><br><span class="line"> <span class="comment">// 表单的相关事件</span></span><br><span class="line"> <span class="function"><span class="title">handleEvent</span>(<span class="params">val</span>)</span> {</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></script></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><h2 id="缘由"><a href="#缘由" class="headerlink" title="缘由"></a>缘由</h2><blockquote>
<p>系统页面大部分为<code>form+tabel</code>的结构,系统复杂起来代码就看起来非常冗余,要修改起来</summary>
<category term="Vue" scheme="http://imagineblog.host/categories/Vue/"/>
<category term="Vue" scheme="http://imagineblog.host/tags/Vue/"/>
</entry>
<entry>
<title>Hexo部署到个人云服务器</title>
<link href="http://imagineblog.host/deploy/"/>
<id>http://imagineblog.host/deploy/</id>
<published>2022-01-13T05:25:58.000Z</published>
<updated>2022-08-31T08:04:19.373Z</updated>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><blockquote><p>最近趁着活动薅羊毛又把服务器续上了,既然白嫖到了不用白不用,就将个人博客挪个窝;顺便记录一下。</p></blockquote><hr><h2 id="购买服务器"><a href="#购买服务器" class="headerlink" title="购买服务器"></a>购买服务器</h2><p>首先我们需要有一台云服务器,我这里是买的<a href="https://cloud.tencent.com/product/cvm">腾讯云</a>的<br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/1642056347000.png"></p><hr><h2 id="通过git生成ssh秘钥"><a href="#通过git生成ssh秘钥" class="headerlink" title="通过git生成ssh秘钥"></a>通过git生成ssh秘钥</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 假如没有设置git的全局信息需要先设置 设置过了可以忽略</span></span><br><span class="line">git config --<span class="built_in">global</span> user.name <span class="string">"yourname"</span></span><br><span class="line">git config --<span class="built_in">global</span> user.email youremail@example.com</span><br><span class="line"><span class="comment">// 生成SSH密钥</span></span><br><span class="line">ssh-keygen -t rsa -C <span class="string">"youremail@example.com"</span></span><br><span class="line"><span class="comment">// 禁用自动转换,这个不设置后面上传时会出现警告</span></span><br><span class="line">git config --<span class="built_in">global</span> core.autocrlf <span class="literal">false</span></span><br></pre></td></tr></table></figure><hr><h2 id="配置服务器git"><a href="#配置服务器git" class="headerlink" title="配置服务器git"></a>配置服务器git</h2><ol><li>登录服务器<br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/1642056955000.png"></li><li>安装git<br>通过git –version命令查看是否存在git命令,我这里已经安装好了;如果显示的是not found, 需要去安装<br><code>yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-devel -y yum install -y git</code></li></ol><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/1642057165000.png"></p><ol start="3"><li>创建用户并配置仓库<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">useradd git <span class="comment">// 创建用户</span></span><br><span class="line">passwd git <span class="comment">// 设置密码</span></span><br><span class="line">su git <span class="comment">// 切换用户</span></span><br><span class="line">cd /home/git/ <span class="comment">// 进入git用户所在home目录</span></span><br><span class="line">mkdir -p projects/blog <span class="comment">// 创建项目存放的目录(可以自行创建命名)</span></span><br><span class="line">mkdir repos && cd repos <span class="comment">// 创建文件夹</span></span><br><span class="line">git init --bare blog.git <span class="comment">// 创建一个裸露的仓库</span></span><br><span class="line">cd blog.git/hooks <span class="comment">// 创建 hook 钩子函数</span></span><br><span class="line">vi post-receive <span class="comment">// 编辑hook钩子</span></span><br></pre></td></tr></table></figure>在编辑区输入以下内容:<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">#!/bin/sh </span><br><span class="line">git --work-tree=<span class="regexp">/home/gi</span>t/projects/blog --git-dir=<span class="regexp">/home/gi</span>t/repos/blog.git checkout -f</span><br><span class="line"></span><br><span class="line"><span class="comment">// /home/git/projects/blog 项目存放地址 </span></span><br><span class="line"><span class="comment">// /home/git/repos/blog.git git远程服务器仓库</span></span><br></pre></td></tr></table></figure><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/1642058145000.png"></li></ol><p>按住<code>ESC</code>,然后输出<code>:wq</code>保存退出!</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">chmod +x post-receive <span class="comment">// 为刚才的文件添加可执行的权限</span></span><br><span class="line"><span class="comment">// 退出切换到 root 登录</span></span><br><span class="line">exit </span><br><span class="line">su root</span><br><span class="line">chown -R git:git /home/git/repos/blog.git <span class="comment">// 添加权限</span></span><br></pre></td></tr></table></figure><ol start="4"><li>测试本地能否将其clone</li></ol><p>在电脑上随便找个位置新建一个文件夹,并且将<code>bash</code>或者其他命令行工具切换到这里。开始执行以下命令(注意替换成你的服务器ip),测试能否将仓库<code>clone</code>下来。<br><code>git clone git@server_ip:/home/git/repos/blog.git</code></p><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/1642058987000.png"></p><ol start="5"><li>建立SSH信任关系(免密登录)<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">su git <span class="comment">// 切换到git用户</span></span><br><span class="line">cd ~</span><br><span class="line">mkdir .ssh <span class="comment">// 创建.ssh目录</span></span><br><span class="line">chmod <span class="number">700</span> .ssh/ <span class="comment">// 赋予权限</span></span><br><span class="line">cd .ssh <span class="comment">// 进入.ssh目录</span></span><br><span class="line">vi authorized_keys <span class="comment">// 编辑一个名为authorized_keys的文件,并写入公钥(id_rsa.pub)内容</span></span><br><span class="line">chmod <span class="number">600</span> authorized_keys <span class="comment">//添加完成后赋予权限 </span></span><br></pre></td></tr></table></figure>在本地测试能否连接成功<br><code>ssh git@server_ip</code>此时登录就只需要输入一次密码就好了。</li></ol><hr><h2 id="配置NGINX服务器"><a href="#配置NGINX服务器" class="headerlink" title="配置NGINX服务器"></a>配置NGINX服务器</h2><ol><li>安装<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="comment">// 安装依赖 </span></span><br><span class="line">sudo yum install -y yum-utils </span><br><span class="line"><span class="comment">// 安装nginx服务 </span></span><br><span class="line">sudo yum install -y nginx</span><br></pre></td></tr></table></figure></li><li>配置<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="comment">//切换到nginx的配置文件目录</span></span><br><span class="line">cd /etc/nginx</span><br><span class="line"><span class="comment">// 编辑文件</span></span><br><span class="line">vi nginx.conf <span class="comment">// 将 user 改成 root</span></span><br></pre></td></tr></table></figure><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/1642060172000.png"></li></ol><p>修改<code>root</code>解析路径(<code>/home/git/projects/blog/</code>)<br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/1642060636000.png"></p><p>运行<code>nginx</code>此时在浏览器直接访问你的服务器ip地址即可看到一个404页面。</p><hr><h2 id="配置Hexo-deploy"><a href="#配置Hexo-deploy" class="headerlink" title="配置Hexo deploy"></a>配置Hexo deploy</h2><ol><li>配置博客根目录下的_config.yml文件<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><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="attr">deploy:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">type:</span> <span class="string">git</span></span><br><span class="line"> <span class="attr">repo:</span> <span class="string">git@github.com:lp-Imagine/lp-Imagine.github.io.git</span></span><br><span class="line"> <span class="attr">branch:</span> <span class="string">master</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">type:</span> <span class="string">git</span></span><br><span class="line"> <span class="attr">repo:</span> <span class="string">git@42.192.205.229:/home/git/repos/blog.git</span></span><br><span class="line"> <span class="attr">branch:</span> <span class="string">master</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">type:</span> <span class="string">baidu_url_submitter</span> <span class="string">//</span> <span class="string">百度主动推送</span></span><br></pre></td></tr></table></figure></li><li>本地三连<code>hexo clean && hexo g && hexo d</code></li></ol><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/1642061289000.png"></p>]]></content>
<summary type="html"><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><blockquote>
<p>最近趁着活动薅羊毛又把服务器续上了,既然白嫖到了不用白不用,就将个人博客挪个窝;顺便记录一下。</p>
</blo</summary>
<category term="hexo" scheme="http://imagineblog.host/categories/hexo/"/>
<category term="hexo" scheme="http://imagineblog.host/tags/hexo/"/>
</entry>
<entry>
<title>外挂标签</title>
<link href="http://imagineblog.host/tagplus/"/>
<id>http://imagineblog.host/tagplus/</id>
<published>2021-08-14T03:18:01.000Z</published>
<updated>2022-08-31T08:04:19.377Z</updated>
<content type="html">< 语法 %}</span><br><span class="line">{% checkbox red, 支持自定义颜色 %}</span><br><span class="line">{% checkbox green checked, 绿色 + 默认选中 %}</span><br><span class="line">{% checkbox yellow checked, 黄色 + 默认选中 %}</span><br><span class="line">{% checkbox cyan checked, 青色 + 默认选中 %}</span><br><span class="line">{% checkbox blue checked, 蓝色 + 默认选中 %}</span><br><span class="line">{% checkbox plus green checked, 增加 %}</span><br><span class="line">{% checkbox minus yellow checked, 减少 %}</span><br><span class="line">{% checkbox times red checked, 叉 %}</span><br></pre></td></tr></table></figure><hr><h2 id="单选列表-radio"><a href="#单选列表-radio" class="headerlink" title="单选列表 radio"></a>单选列表 radio</h2><div class='checkbox'><input type="radio" /> <p>纯文本测试</p> </div><div class='checkbox checked'><input type="radio" checked="checked"/> <p>支持简单的 <a href="https://guides.github.com/features/mastering-markdown/">markdown</a> 语法</p> </div><div class='checkbox red'><input type="radio" /> <p>支持自定义颜色</p> </div><div class='checkbox green'><input type="radio" /> <p>绿色</p> </div><div class='checkbox yellow'><input type="radio" /> <p>黄色</p> </div><div class='checkbox cyan'><input type="radio" /> <p>青色</p> </div><div class='checkbox blue'><input type="radio" /> <p>蓝色</p> </div><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">{% radio 纯文本测试 %}</span><br><span class="line">{% radio checked, 支持简单的 [markdown](https://guides.github.com/features/mastering-markdown/) 语法 %}</span><br><span class="line">{% radio red, 支持自定义颜色 %}</span><br><span class="line">{% radio green, 绿色 %}</span><br><span class="line">{% radio yellow, 黄色 %}</span><br><span class="line">{% radio cyan, 青色 %}</span><br><span class="line">{% radio blue, 蓝色 %}</span><br></pre></td></tr></table></figure><hr><h2 id="时间轴timeline"><a href="#时间轴timeline" class="headerlink" title="时间轴timeline"></a>时间轴timeline</h2><div class="timeline"><div class="timenode"><div class="meta"><p><p>2020-07-24 <a href="https://github.com/volantis-x/hexo-theme-volantis/releases">2.6.6 -> 3.0</a></p></p></div><div class="body"><ol><li>如果有 <code>hexo-lazyload-image</code> 插件,需要删除并重新安装最新版本,设置 <code>lazyload.isSPA: true</code>。</li><li>2.x 版本的 css 和 js 不适用于 3.x 版本,如果使用了 <code>use_cdn: true</code> 则需要删除。</li><li>2.x 版本的 fancybox 标签在 3.x 版本中被重命名为 gallery 。</li><li>2.x 版本的置顶 <code>top: true</code> 改为了 <code>pin: true</code>,并且同样适用于 <code>layout: page</code> 的页面。</li><li>如果使用了 <code>hexo-offline</code> 插件,建议卸载,3.0 版本默认开启了 pjax 服务。</li></ol></div></div><div class="timenode"><div class="meta"><p><p>2020-05-15 <a href="https://github.com/volantis-x/hexo-theme-volantis/releases/tag/2.6.6">2.6.3 -> 2.6.6</a></p></p></div><div class="body"><p>不需要额外处理。</p></div></div><div class="timenode"><div class="meta"><p><p>2020-04-20 <a href="https://github.com/volantis-x/hexo-theme-volantis/releases/tag/2.6.3">2.6.2 -> 2.6.3</a></p></p></div><div class="body"><ol><li>全局搜索 <code>seotitle</code> 并替换为 <code>seo_title</code>。</li><li>group 组件的索引规则有变,使用 group 组件的文章内,<code>group: group_name</code> 对应的组件名必须是 <code>group_name</code>。</li><li>group 组件的列表名优先显示文章的 <code>short_title</code> 其次是 <code>title</code>。</li></ol></div></div></div><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">{% timeline %}</span><br><span class="line"></span><br><span class="line">{% timenode 2020-07-24 [2.6.6 -> 3.0](https://github.com/volantis-x/hexo-theme-volantis/releases) %}</span><br><span class="line"></span><br><span class="line">1. 如果有 `hexo-lazyload-image` 插件,需要删除并重新安装最新版本,设置 `lazyload.isSPA: true`。</span><br><span class="line">2. 2.x 版本的 css 和 js 不适用于 3.x 版本,如果使用了 `use_cdn: true` 则需要删除。</span><br><span class="line">3. 2.x 版本的 fancybox 标签在 3.x 版本中被重命名为 gallery 。</span><br><span class="line">4. 2.x 版本的置顶 `top: true` 改为了 `pin: true`,并且同样适用于 `layout: page` 的页面。</span><br><span class="line">5. 如果使用了 `hexo-offline` 插件,建议卸载,3.0 版本默认开启了 pjax 服务。</span><br><span class="line"></span><br><span class="line">{% endtimenode %}</span><br><span class="line"></span><br><span class="line">{% timenode 2020-05-15 [2.6.3 -> 2.6.6](https://github.com/volantis-x/hexo-theme-volantis/releases/tag/2.6.6) %}</span><br><span class="line"></span><br><span class="line">不需要额外处理。</span><br><span class="line"></span><br><span class="line">{% endtimenode %}</span><br><span class="line"></span><br><span class="line">{% timenode 2020-04-20 [2.6.2 -> 2.6.3](https://github.com/volantis-x/hexo-theme-volantis/releases/tag/2.6.3) %}</span><br><span class="line"></span><br><span class="line">1. 全局搜索 `seotitle` 并替换为 `seo_title`。</span><br><span class="line">2. group 组件的索引规则有变,使用 group 组件的文章内,`group: group_name` 对应的组件名必须是 `group_name`。</span><br><span class="line">2. group 组件的列表名优先显示文章的 `short_title` 其次是 `title`。</span><br><span class="line"></span><br><span class="line">{% endtimenode %}</span><br><span class="line"></span><br><span class="line">{% endtimeline %}</span><br></pre></td></tr></table></figure><hr><h2 id="链接卡片-link"><a href="#链接卡片-link" class="headerlink" title="链接卡片 link"></a>链接卡片 link</h2><div class="tag link"><a class="link-card" title="imagine's blog" href="https://imagineblog.vercel.app/"><div class="left"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/Akilarlxh/akilarlxh.github.io/img/siteicon/favicon.ico"/></div><div class="right"><p class="text">imagine's blog</p><p class="url">https://imagineblog.vercel.app/</p></div></a></div><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% link imagine's blog, https://imagineblog.vercel.app/, https://cdn.jsdelivr.net/gh/Akilarlxh/akilarlxh.github.io/img/siteicon/favicon.ico %}</span><br></pre></td></tr></table></figure><hr><h2 id="按钮-btns"><a href="#按钮-btns" class="headerlink" title="按钮 btns"></a>按钮 btns</h2><div class="btns circle grid5"> <a class="button" href='https://xaoxuu.com' title='xaoxuu'><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src='https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png'>xaoxuu</a><a class="button" href='https://xaoxuu.com' title='xaoxuu'><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src='https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png'>xaoxuu</a><a class="button" href='https://xaoxuu.com' title='xaoxuu'><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src='https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png'>xaoxuu</a><a class="button" href='https://xaoxuu.com' title='xaoxuu'><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src='https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png'>xaoxuu</a><a class="button" href='https://xaoxuu.com' title='xaoxuu'><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src='https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png'>xaoxuu</a> </div><div class="btns rounded grid5"> <a class="button" href='/' title='下载源码'><i class='fas fa-download'></i>下载源码</a><a class="button" href='/' title='查看文档'><i class='fas fa-book-open'></i>查看文档</a> </div><div class="btns circle center grid5"> <a href='https://apps.apple.com/cn/app/heart-mate-pro-hrm-utility/id1463348922?ls=1'> <i class='fab fa-apple'></i> <b>心率管家</b> <p class='p red'>专业版</p> <img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src='https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/qrcode/heartmate_pro.png'></a><a href='https://apps.apple.com/cn/app/heart-mate-lite-hrm-utility/id1475747930?ls=1'> <i class='fab fa-apple'></i> <b>心率管家</b> <p class='p green'>免费版</p> <img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src='https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/qrcode/heartmate_lite.png'></a> </div><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><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">{% btns circle grid5 %}</span><br><span class="line">{% cell xaoxuu, https://xaoxuu.com, https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png %}</span><br><span class="line">{% cell xaoxuu, https://xaoxuu.com, https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png %}</span><br><span class="line">{% cell xaoxuu, https://xaoxuu.com, https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png %}</span><br><span class="line">{% cell xaoxuu, https://xaoxuu.com, https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png %}</span><br><span class="line">{% cell xaoxuu, https://xaoxuu.com, https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png %}</span><br><span class="line">{% endbtns %}</span><br><span class="line"></span><br><span class="line">{% btns rounded grid5 %}</span><br><span class="line">{% cell 下载源码, /, fas fa-download %}</span><br><span class="line">{% cell 查看文档, /, fas fa-book-open %}</span><br><span class="line">{% endbtns %}</span><br><span class="line"></span><br><span class="line">{% btns circle center grid5 %}</span><br><span class="line"><a href='https://apps.apple.com/cn/app/heart-mate-pro-hrm-utility/id1463348922?ls=1'></span><br><span class="line"> <i class='fab fa-apple'></i></span><br><span class="line"> <b>心率管家</b></span><br><span class="line"> {% p red, 专业版 %}</span><br><span class="line"> <img src='https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/qrcode/heartmate_pro.png'></span><br><span class="line"></a></span><br><span class="line"><a href='https://apps.apple.com/cn/app/heart-mate-lite-hrm-utility/id1475747930?ls=1'></span><br><span class="line"> <i class='fab fa-apple'></i></span><br><span class="line"> <b>心率管家</b></span><br><span class="line"> {% p green, 免费版 %}</span><br><span class="line"> <img src='https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/qrcode/heartmate_lite.png'></span><br><span class="line"></a></span><br><span class="line">{% endbtns %}</span><br></pre></td></tr></table></figure><hr><h2 id="github卡片"><a href="#github卡片" class="headerlink" title="github卡片"></a>github卡片</h2><table><thead><tr><th><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/xaoxuu"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://github-readme-stats.vercel.app/api/?username=xaoxuu&show_owner=true"/></a></th><th><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/xaoxuu"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://github-readme-stats.vercel.app/api/?username=xaoxuu&theme=vue&show_owner=true"/></a></th></tr></thead><tbody><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/xaoxuu"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://github-readme-stats.vercel.app/api/?username=xaoxuu&theme=buefy&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/xaoxuu"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://github-readme-stats.vercel.app/api/?username=xaoxuu&theme=solarized-light&show_owner=true"/></a></td></tr><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/xaoxuu"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://github-readme-stats.vercel.app/api/?username=xaoxuu&theme=onedark&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/xaoxuu"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://github-readme-stats.vercel.app/api/?username=xaoxuu&theme=solarized-dark&show_owner=true"/></a></td></tr><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/xaoxuu"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://github-readme-stats.vercel.app/api/?username=xaoxuu&theme=algolia&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/xaoxuu"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://github-readme-stats.vercel.app/api/?username=xaoxuu&theme=calm&show_owner=true"/></a></td></tr></tbody></table><ul><li>仓库卡片</li></ul><table><thead><tr><th><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&show_owner=true"/></a></th><th><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=vue&show_owner=true"/></a></th></tr></thead><tbody><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=buefy&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=solarized-light&show_owner=true"/></a></td></tr><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=onedark&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=solarized-dark&show_owner=true"/></a></td></tr><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=algolia&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=calm&show_owner=true"/></a></td></tr></tbody></table><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">| {% ghcard xaoxuu %} | {% ghcard xaoxuu, theme=vue %} |</span><br><span class="line">| -- | -- |</span><br><span class="line">| {% ghcard xaoxuu, theme=buefy %} | {% ghcard xaoxuu, theme=solarized-light %} |</span><br><span class="line">| {% ghcard xaoxuu, theme=onedark %} | {% ghcard xaoxuu, theme=solarized-dark %} |</span><br><span class="line">| {% ghcard xaoxuu, theme=algolia %} | {% ghcard xaoxuu, theme=calm %} |</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">| {% ghcard volantis-x/hexo-theme-volantis %} | {% ghcard volantis-x/hexo-theme-volantis, theme=vue %} |</span><br><span class="line">| -- | -- |</span><br><span class="line">| {% ghcard volantis-x/hexo-theme-volantis, theme=buefy %} | {% ghcard volantis-x/hexo-theme-volantis, theme=solarized-light %} |</span><br><span class="line">| {% ghcard volantis-x/hexo-theme-volantis, theme=onedark %} | {% ghcard volantis-x/hexo-theme-volantis, theme=solarized-dark %} |</span><br><span class="line">| {% ghcard volantis-x/hexo-theme-volantis, theme=algolia %} | {% ghcard volantis-x/hexo-theme-volantis, theme=calm %} |</span><br><span class="line"></span><br></pre></td></tr></table></figure><hr><h2 id="github徽标"><a href="#github徽标" class="headerlink" title="github徽标"></a>github徽标</h2><object class="ghbdage" style="margin-inline:5px" title="" standby="loading..." data="https://img.shields.io/badge/Butterfly-Theme-orange?logo=&color=orange&link=&"></object><object class="ghbdage" style="margin-inline:5px" title="" standby="loading..." data="https://img.shields.io/badge/Hexo-Frame-orange?logo=hexo&color=orange&link=&"></object><object class="ghbdage" style="margin-inline:5px" title="本站使用JsDelivr为静态资源提供CDN加速" standby="loading..." data="https://img.shields.io/badge/JsDelivr-CDN-orange?logo=jsDelivr&color=abcdef&link=https://metroui.org.ua/index.html&"></object><p>//如果是跨顺序省略可选参数,仍然需要写个逗号,用作分割</p><object class="ghbdage" style="margin-inline:5px" title="" standby="loading..." data="https://img.shields.io/badge/GitHub-Source-orange?logo=GitHub&color=orange&link=https://github.com/&"></object><object class="ghbdage" style="margin-inline:5px" title="本站采用双线部署,默认线路托管于Vercel" standby="loading..." data="https://img.shields.io/badge/Vercel-Hosted-orange?logo=Vercel&color=brightgreen&link=https://vercel.com/&style=social&logoWidth=20"></object><p>//如果是跨顺序省略可选参数组,仍然需要写双竖线||用作分割</p><object class="ghbdage" style="margin-inline:5px" title="" standby="loading..." data="https://img.shields.io/badge/Vercel-Hosted-orange?logo=Vercel&color=orange&link=&style=social&logoWidth=20&logoColor=violet"></object><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><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">{% bdage Theme,Butterfly %}</span><br><span class="line">{% bdage Frame,Hexo,hexo %}</span><br><span class="line"></span><br><span class="line">{% bdage CDN,JsDelivr,jsDelivr||abcdef,https://metroui.org.ua/index.html,本站使用JsDelivr为静态资源提供CDN加速 %}</span><br><span class="line"><span class="comment">//如果是跨顺序省略可选参数,仍然需要写个逗号,用作分割</span></span><br><span class="line">{% bdage Source,GitHub,GitHub||,https://github.com/ %}</span><br><span class="line"></span><br><span class="line">{% bdage Hosted,Vercel,Vercel||brightgreen,https://vercel.com/,本站采用双线部署,默认线路托管于Vercel||style=social&logoWidth=20 %}</span><br><span class="line"><span class="comment">//如果是跨顺序省略可选参数组,仍然需要写双竖线||用作分割</span></span><br><span class="line">{% bdage Hosted,Vercel,Vercel||||style=social&logoWidth=20&logoColor=violet %}</span><br></pre></td></tr></table></figure><hr><h2 id="网站卡片-sites"><a href="#网站卡片-sites" class="headerlink" title="网站卡片 sites"></a>网站卡片 sites</h2><div class="site-card-group"><a class="site-card" href="https://xaoxuu.com"><div class="img"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://i.loli.net/2020/08/21/VuSwWZ1xAeUHEBC.jpg"/></div><div class="info"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png"/><span class="title">xaoxuu</span><span class="desc">简约风格</span></div></a><a class="site-card" href="https://inkss.cn"><div class="img"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://i.loli.net/2020/08/21/Vzbu3i8fXs6Nh5Y.jpg"/></div><div class="info"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/inkss/common@master/static/web/avatar.jpg"/><span class="title">inkss</span><span class="desc">这是一段关于这个网站的描述文字</span></div></a><a class="site-card" href="https://blog.mhuig.top"><div class="img"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://i.loli.net/2020/08/22/d24zpPlhLYWX6D1.png"/></div><div class="info"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/MHuiG/imgbed@master/data/p.png"/><span class="title">MHuiG</span><span class="desc">这是一段关于这个网站的描述文字</span></div></a><a class="site-card" href="https://colsrch.top"><div class="img"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://i.loli.net/2020/08/22/dFRWXm52OVu8qfK.png"/></div><div class="info"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/Colsrch/images/Colsrch/avatar.jpg"/><span class="title">Colsrch</span><span class="desc">这是一段关于这个网站的描述文字</span></div></a><a class="site-card" href="https://linhk1606.github.io"><div class="img"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://i.loli.net/2020/08/21/3PmGLCKicnfow1x.png"/></div><div class="info"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://i.loli.net/2020/02/09/PN7I5RJfFtA93r2.png"/><span class="title">Linhk1606</span><span class="desc">这是一段关于这个网站的描述文字</span></div></a></div><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">{% sitegroup %}</span><br><span class="line">{% site xaoxuu, url=https://xaoxuu.com, screenshot=https://i.loli.net/2020/08/21/VuSwWZ1xAeUHEBC.jpg, avatar=https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png, description=简约风格 %}</span><br><span class="line">{% site inkss, url=https://inkss.cn, screenshot=https://i.loli.net/2020/08/21/Vzbu3i8fXs6Nh5Y.jpg, avatar=https://cdn.jsdelivr.net/gh/inkss/common@master/static/web/avatar.jpg, description=这是一段关于这个网站的描述文字 %}</span><br><span class="line">{% site MHuiG, url=https://blog.mhuig.top, screenshot=https://i.loli.net/2020/08/22/d24zpPlhLYWX6D1.png, avatar=https://cdn.jsdelivr.net/gh/MHuiG/imgbed@master/data/p.png, description=这是一段关于这个网站的描述文字 %}</span><br><span class="line">{% site Colsrch, url=https://colsrch.top, screenshot=https://i.loli.net/2020/08/22/dFRWXm52OVu8qfK.png, avatar=https://cdn.jsdelivr.net/gh/Colsrch/images/Colsrch/avatar.jpg, description=这是一段关于这个网站的描述文字 %}</span><br><span class="line">{% site Linhk1606, url=https://linhk1606.github.io, screenshot=https://i.loli.net/2020/08/21/3PmGLCKicnfow1x.png, avatar=https://i.loli.net/2020/02/09/PN7I5RJfFtA93r2.png, description=这是一段关于这个网站的描述文字 %}</span><br><span class="line">{% endsitegroup %}</span><br></pre></td></tr></table></figure><hr><h2 id="行内图片inlineimage"><a href="#行内图片inlineimage" class="headerlink" title="行内图片inlineimage"></a>行内图片inlineimage</h2><p>这是 <img no-lazy class="inline" src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-emoji/aru-l/0000.gif" style="height:1.5em"/> 一段话。</p><p>这又是 <img no-lazy class="inline" src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-emoji/aru-l/5150.gif" style="height:40px;"/> 一段话。</p><figure class="highlight"><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">这是 {% inlineimage https://cdn.jsdelivr.net/gh/volantis-x/cdn-emoji/aru-l/0000.gif %} 一段话。</span><br><span class="line"></span><br><span class="line">这又是 {% inlineimage https://cdn.jsdelivr.net/gh/volantis-x/cdn-emoji/aru-l/5150.gif, height=40px %} 一段话。</span><br></pre></td></tr></table></figure><hr><h2 id="单张图片image"><a href="#单张图片image" class="headerlink" title="单张图片image"></a>单张图片image</h2><div class="img-wrap"><div class="img-bg"><img class="img" src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg" alt="没有什么故事。"/></div><span class="image-caption">没有什么故事。</span></div><div class="img-wrap"><div class="img-bg"><img class="img" src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg" style="width:400px;"/></div></div><div class="img-wrap"><div class="img-bg"><img class="img" src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg" alt="没有什么故事。" style="width:400px;"/></div><span class="image-caption">没有什么故事。</span></div><div class="img-wrap"><div class="img-bg" style="background:#1D0C04"><img class="img" src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg" alt="优化不同宽度浏览的观感" style="width:400px;"/></div><span class="image-caption">优化不同宽度浏览的观感</span></div><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">{% image https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg, alt=没有什么故事。 %}</span><br><span class="line"></span><br><span class="line">{% image https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg, width=400px %}</span><br><span class="line"></span><br><span class="line">{% image https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg, width=400px, alt=没有什么故事。 %}</span><br><span class="line"></span><br><span class="line">{% image https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg, width=400px, bg=#1D0C04, alt=优化不同宽度浏览的观感 %}</span><br></pre></td></tr></table></figure><hr><h2 id="音频-audio"><a href="#音频-audio" class="headerlink" title="音频 audio"></a>音频 audio</h2><div class="audio"><audio controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/Lumia1020.mp3' type='audio/mp3'>Your browser does not support the audio tag.</audio></div><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% audio https://github.com/volantis-x/volantis-docs/releases/download/assets/Lumia1020.mp3 %}</span><br></pre></td></tr></table></figure><h2 id="视频-video"><a href="#视频-video" class="headerlink" title="视频 video"></a>视频 video</h2><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="videos" col='2'><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div></div><div class="videos" col='4'><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div></div><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><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">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov %}</span><br><span class="line"></span><br><span class="line">{% videos, 2 %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov %}</span><br><span class="line">{% endvideos %}</span><br><span class="line"></span><br><span class="line">{% videos, 4 %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov %}</span><br><span class="line">{% endvideos %}</span><br></pre></td></tr></table></figure><hr><h2 id="相册"><a href="#相册" class="headerlink" title="相册"></a>相册</h2><div class="gallery-group-main"> <figure class="gallery-group"> <img class="gallery-group-img" src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src='https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/4.jpg' alt="Group Image Gallery"> <figcaption> <div class="gallery-group-name">MC</div> <p>在Rikkaの六花服务器里留下的足迹</p> <a href='/gallery/MC/'></a> </figcaption> </figure> <figure class="gallery-group"> <img class="gallery-group-img" src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src='https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/6.jpg' alt="Group Image Gallery"> <figcaption> <div class="gallery-group-name">Gundam</div> <p>哦咧哇gundam哒!</p> <a href='/gallery/Gundam/'></a> </figcaption> </figure> </div><div class="justified-gallery"><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://i.loli.net/2019/12/25/Fze9jchtnyJXMHN.jpg"><br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://i.loli.net/2019/12/25/ryLVePaqkYm4TEK.jpg"><br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://i.loli.net/2019/12/25/gEy5Zc1Ai6VuO4N.jpg"><br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://i.loli.net/2019/12/25/d6QHbytlSYO4FBG.jpg"><br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://i.loli.net/2019/12/25/6nepIJ1xTgufatZ.jpg"><br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://i.loli.net/2019/12/25/E7Jvr4eIPwUNmzq.jpg"><br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://i.loli.net/2019/12/25/mh19anwBSWIkGlH.jpg"><br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://i.loli.net/2019/12/25/2tu9JC8ewpBFagv.jpg"></p> </div><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><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"><div class="gallery-group-main"></span><br><span class="line">{% galleryGroup MC 在Rikkaの六花服务器里留下的足迹 '/gallery/MC/' https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/4.jpg %}</span><br><span class="line">{% galleryGroup Gundam 哦咧哇gundam哒! '/gallery/Gundam/' https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/6.jpg %}</span><br><span class="line"></div></span><br><span class="line"></span><br><span class="line">{% gallery %}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">{% endgallery %}</span><br></pre></td></tr></table></figure><hr><h2 id="折叠框-folding"><a href="#折叠框-folding" class="headerlink" title="折叠框 folding"></a>折叠框 folding</h2><details ><summary> 查看图片测试 </summary> <div class='content'> <p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper/abstract/41F215B9-261F-48B4-80B5-4E86E165259E.jpeg"></p> </div> </details><details cyan open><summary> 查看默认打开的折叠框 </summary> <div class='content'> <p>这是一个默认打开的折叠框。</p> </div> </details><details green><summary> 查看代码测试 </summary> <div class='content'> <p>假装这里有代码块(代码块没法嵌套代码块)</p> </div> </details><details yellow><summary> 查看列表测试 </summary> <div class='content'> <ul><li>haha</li><li>hehe</li></ul> </div> </details><details red><summary> 查看嵌套测试 </summary> <div class='content'> <details blue><summary> 查看嵌套测试2 </summary> <div class='content'> <details ><summary> 查看嵌套测试3 </summary> <div class='content'> <p>hahaha <span><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src='https://cdn.jsdelivr.net/gh/volantis-x/cdn-emoji/tieba/%E6%BB%91%E7%A8%BD.png' style='height:24px'></span></p> </div> </details> </div> </details> </div> </details><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">{% folding 查看图片测试 %}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">{% endfolding %}</span><br><span class="line"></span><br><span class="line">{% folding cyan open, 查看默认打开的折叠框 %}</span><br><span class="line"></span><br><span class="line">这是一个默认打开的折叠框。</span><br><span class="line"></span><br><span class="line">{% endfolding %}</span><br><span class="line"></span><br><span class="line">{% folding green, 查看代码测试 %}</span><br><span class="line">假装这里有代码块(代码块没法嵌套代码块)</span><br><span class="line">{% endfolding %}</span><br><span class="line"></span><br><span class="line">{% folding yellow, 查看列表测试 %}</span><br><span class="line"></span><br><span class="line">- haha</span><br><span class="line">- hehe</span><br><span class="line"></span><br><span class="line">{% endfolding %}</span><br><span class="line"></span><br><span class="line">{% folding red, 查看嵌套测试 %}</span><br><span class="line"></span><br><span class="line">{% folding blue, 查看嵌套测试2 %}</span><br><span class="line"></span><br><span class="line">{% folding 查看嵌套测试3 %}</span><br><span class="line"></span><br><span class="line">hahaha <span><img src='https://cdn.jsdelivr.net/gh/volantis-x/cdn-emoji/tieba/%E6%BB%91%E7%A8%BD.png' style='height:24px'></span></span><br><span class="line"></span><br><span class="line">{% endfolding %}</span><br><span class="line"></span><br><span class="line">{% endfolding %}</span><br><span class="line"></span><br><span class="line">{% endfolding %}</span><br></pre></td></tr></table></figure><hr><h2 id="分栏tab"><a href="#分栏tab" class="headerlink" title="分栏tab"></a>分栏tab</h2><div class="tabs" id="test1"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#test1-1">test1 1</button></li><li class="tab"><button type="button" data-href="#test1-2">test1 2</button></li><li class="tab"><button type="button" data-href="#test1-3">test1 3</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="test1-1"><p><strong>This is Tab 1.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="test1-2"><p><strong>This is Tab 2.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="test1-3"><p><strong>This is Tab 3.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><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">{% tabs test1 %}</span><br><span class="line"><!-- tab --></span><br><span class="line">**This is Tab 1.**</span><br><span class="line"><!-- endtab --></span><br><span class="line"></span><br><span class="line"><!-- tab --></span><br><span class="line">**This is Tab 2.**</span><br><span class="line"><!-- endtab --></span><br><span class="line"></span><br><span class="line"><!-- tab --></span><br><span class="line">**This is Tab 3.**</span><br><span class="line"><!-- endtab --></span><br><span class="line">{% endtabs %}</span><br></pre></td></tr></table></figure><hr><h2 id="诗词poem"><a href="#诗词poem" class="headerlink" title="诗词poem"></a>诗词poem</h2><div class='poem'><div class='poem-title'>水调歌头</div><div class='poem-author'>苏轼</div><p>丙辰中秋,欢饮达旦,大醉,作此篇,兼怀子由。<br>明月几时有?把酒问青天。<br>不知天上宫阙,今夕是何年?<br>我欲乘风归去,又恐琼楼玉宇,高处不胜寒。<br>起舞弄清影,何似在人间?</p><p>转朱阁,低绮户,照无眠。<br>不应有恨,何事长向别时圆?<br>人有悲欢离合,月有阴晴圆缺,此事古难全。<br>但愿人长久,千里共婵娟。</p></div><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><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">{% poem 水调歌头,苏轼 %}</span><br><span class="line">丙辰中秋,欢饮达旦,大醉,作此篇,兼怀子由。</span><br><span class="line">明月几时有?把酒问青天。</span><br><span class="line">不知天上宫阙,今夕是何年?</span><br><span class="line">我欲乘风归去,又恐琼楼玉宇,高处不胜寒。</span><br><span class="line">起舞弄清影,何似在人间?</span><br><span class="line"></span><br><span class="line">转朱阁,低绮户,照无眠。</span><br><span class="line">不应有恨,何事长向别时圆?</span><br><span class="line">人有悲欢离合,月有阴晴圆缺,此事古难全。</span><br><span class="line">但愿人长久,千里共婵娟。</span><br><span class="line">{% endpoem %}</span><br></pre></td></tr></table></figure><hr><h2 id="进度条progress"><a href="#进度条progress" class="headerlink" title="进度条progress"></a>进度条progress</h2><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-red" style="width: 10%" aria-valuenow="10" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-yellow" style="width: 30%" aria-valuenow="30" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-green" style="width: 50%" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-cyan" style="width: 70%" aria-valuenow="70" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-blue" style="width: 90%" aria-valuenow="90" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-gray" style="width: 100%" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><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">{% progress 10 red 进度条样式预览 %}</span><br><span class="line">{% progress 30 yellow 进度条样式预览 %}</span><br><span class="line">{% progress 50 green 进度条样式预览 %}</span><br><span class="line">{% progress 70 cyan 进度条样式预览 %}</span><br><span class="line">{% progress 90 blue 进度条样式预览 %}</span><br><span class="line">{% progress 100 gray 进度条样式预览 %}</span><br></pre></td></tr></table></figure><hr><h2 id="注释nota"><a href="#注释nota" class="headerlink" title="注释nota"></a>注释nota</h2><span class='nota' data-nota='可以看到注解内容出现在顶栏'>把鼠标移动到我上面试试</span><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% nota 把鼠标移动到我上面试试 ,可以看到注解内容出现在顶栏 %}</span><br></pre></td></tr></table></figure><hr><h2 id="旋转相册"><a href="#旋转相册" class="headerlink" title="旋转相册"></a>旋转相册</h2><div id='SF' class='carousel'><div id="SF-drag-container" class="drag-container"><div id="SF-spin-container" class="spin-container"><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/0.jpg"><br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/04.jpg"><br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/1.jpg"><br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/2.jpg"><br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/3.jpg"><br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/4.jpg"><br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/6.jpg"><br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/1.jpg"><br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/2.jpg"><br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/3.jpg"><p>strike freedom</p></div><div id="SF-carousel-ground" class="carousel-ground"></div></div></div><script type="text/javascript">carouselinit('SF');</script><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><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">{% carousel 'SF','strike freedom' %}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">{% endcarousel %}</span><br></pre></td></tr></table></figure><hr>]]></content>
<summary type="html"><h2 id="行内文本样式-text"><a href="#行内文本样式-text" class="headerlink" title="行内文本样式 text"></a>行内文本样式 text</h2><ol>
<li>带 <u>下划线</u> 的文本</li>
<li>带 </summary>
<category term="hexo" scheme="http://imagineblog.host/categories/hexo/"/>
<category term="hexo" scheme="http://imagineblog.host/tags/hexo/"/>
</entry>
<entry>
<title>Element-UI问题清单</title>
<link href="http://imagineblog.host/el/"/>
<id>http://imagineblog.host/el/</id>
<published>2021-08-14T02:30:56.000Z</published>
<updated>2022-08-31T08:04:19.377Z</updated>
<content type="html"><![CDATA[<blockquote><p>部分内容转载自:<a href="https://juejin.cn/user/1239904849499911">8号的凌晨4点</a>的<a href="https://juejin.cn/post/6981083988286767117">一份 ElementUI 问题清单</a></p></blockquote><h2 id="form表单只有一个-input-时回车键刷新页面"><a href="#form表单只有一个-input-时回车键刷新页面" class="headerlink" title="form表单只有一个 input 时回车键刷新页面"></a>form表单只有一个 input 时回车键刷新页面</h2><div class="tip bell faa-horizontal animated"><p>原因:触发了表单默认的提交行为,给el-form加上<span class='p red'>@submit.native.prevent</span>就行了。</p></div><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">el-form</span> <span class="attr">inline</span> @<span class="attr">submit.native.prevent</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">el-form-item</span> <span class="attr">label</span>=<span class="string">"订单号"</span>></span></span><br><span class="line"> <el-input</span><br><span class="line"> v-model="query.orderNo"</span><br><span class="line"> :placeholder="输入订单号查询"</span><br><span class="line"> clearable</span><br><span class="line"> @keyup.enter.native="enterInput"</span><br><span class="line"> /></span><br><span class="line"> <span class="tag"></<span class="name">el-form-item</span>></span></span><br><span class="line"><span class="tag"></<span class="name">el-form</span>></span></span><br></pre></td></tr></table></figure><hr><h2 id="动态表单form重置遇到的问题"><a href="#动态表单form重置遇到的问题" class="headerlink" title="动态表单form重置遇到的问题"></a>动态表单form重置遇到的问题</h2><div class="tip bolt faa-horizontal animated"><p>相对于动态表单(有条件的对表单进行渲染)而言,需要使用<span class='p red'>v-show</span>实现显示隐藏功能。如果使用<span class='p red'>v-if</span>会报错,但不会影响重置结果,报错的大概内容是<span class='p red'>‘indexOf’ is not function</span>。</p></div><hr><h2 id="解决表格线条不对齐"><a href="#解决表格线条不对齐" class="headerlink" title="解决表格线条不对齐"></a>解决表格线条不对齐</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">body</span> <span class="selector-class">.el-table</span> <span class="selector-tag">th</span><span class="selector-class">.gutter</span> { </span><br><span class="line"> <span class="attribute">display</span>: table-cell <span class="meta">!important</span>; </span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="表格固定列最后一行显示不全"><a href="#表格固定列最后一行显示不全" class="headerlink" title="表格固定列最后一行显示不全"></a>表格固定列最后一行显示不全</h2><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/1628947994000.webp"></p><div class="tip bell faa-horizontal animated"><p>这种情况有时在宽度刚好处于临界值状态时会出现。因为固定列是独立于表格body动态计算高度的,出现了固定列高度小于表格高度所以造成最后一行被遮挡。</p></div><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><br><span class="line"><span class="selector-class">.el-table__fixed-right</span> {</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">100%</span> <span class="meta">!important</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="气泡确认框文档里的confirm事件不生效"><a href="#气泡确认框文档里的confirm事件不生效" class="headerlink" title="气泡确认框文档里的confirm事件不生效"></a>气泡确认框文档里的confirm事件不生效</h2><div class="tip warning"><p>版本:element-ui: “2.13.2”, vue: “2.6.10”</p></div><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">// 将confirm改为onConfirm</span></span><br><span class="line">@onConfirm=<span class="string">"onDeleteOrder(row.id)"</span></span><br></pre></td></tr></table></figure><hr><h2 id="输入框用正则限制但绑定值未更新"><a href="#输入框用正则限制但绑定值未更新" class="headerlink" title="输入框用正则限制但绑定值未更新"></a>输入框用正则限制但绑定值未更新</h2><p>为了做输入框的正则限制,常采用下面的方式:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">el-input</span> </span></span><br><span class="line"><span class="tag"> <span class="attr">v-model</span>=<span class="string">"form.retailMinOrder"</span> </span></span><br><span class="line"><span class="tag"> <span class="attr">placeholder</span>=<span class="string">"请输入"</span> </span></span><br><span class="line"><span class="tag"> <span class="attr">onkeyup</span>=<span class="string">"value=value.replace(/[^\d.]/g,'')"</span> </span></span><br><span class="line"><span class="tag">/></span></span><br></pre></td></tr></table></figure><p>这样做虽然输入框的显示是正确的,但绑定的值是没有更新的,将 onkeyup 改为<span class='p red'>oninput</span> 即可。<br>输入中文后 v-model 会失效问题,可以这样写:</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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">el-input</span> </span></span><br><span class="line"><span class="tag"> <span class="attr">v-model</span>=<span class="string">"form.retailMinOrder"</span> </span></span><br><span class="line"><span class="tag"> <span class="attr">placeholder</span>=<span class="string">"请输入"</span> </span></span><br><span class="line"><span class="tag"> @<span class="attr">keyup.native</span>=<span class="string">"form.retailMinOrder=form.retailMinOrder.replace(/[^\d.]/g,'')"</span></span></span><br><span class="line"><span class="tag">/></span></span><br></pre></td></tr></table></figure><hr><h2 id="去除type-”number”输入框聚焦时的上下箭头"><a href="#去除type-”number”输入框聚焦时的上下箭头" class="headerlink" title="去除type=”number”输入框聚焦时的上下箭头"></a>去除type=”number”输入框聚焦时的上下箭头</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><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="selector-class">.clear-number-input</span><span class="selector-class">.el-input</span>::-webkit-outer-spin-button,</span><br><span class="line">.clear-number-input.el-input::-webkit-inner-spin-button {</span><br><span class="line"> margin: <span class="number">0</span>;</span><br><span class="line"> -webkit-appearance: none <span class="meta">!important</span>;</span><br><span class="line">} </span><br><span class="line"><span class="selector-class">.clear-number-input</span><span class="selector-class">.el-input</span> <span class="selector-tag">input</span><span class="selector-attr">[type=<span class="string">"number"</span>]</span>::-webkit-outer-spin-button,</span><br><span class="line">.clear-number-input.el-input input[type=<span class="string">"number"</span>]::-webkit-inner-spin-button {</span><br><span class="line"> margin: <span class="number">0</span>;</span><br><span class="line"> -webkit-appearance: none <span class="meta">!important</span>;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.clear-number-input</span><span class="selector-class">.el-input</span> {</span><br><span class="line"> -moz-appearance: textfield;</span><br><span class="line">} </span><br><span class="line"><span class="selector-class">.clear-number-input</span><span class="selector-class">.el-input</span> <span class="selector-tag">input</span><span class="selector-attr">[type=<span class="string">"number"</span>]</span> {</span><br><span class="line"> -moz-appearance: textfield;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><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">el-input</span> <span class="attr">type</span>=<span class="string">"number"</span> <span class="attr">class</span>=<span class="string">"clear-number-input"</span> /></span></span><br></pre></td></tr></table></figure><hr><h2 id="只校验表单中的某一个-些字段"><a href="#只校验表单中的某一个-些字段" class="headerlink" title="只校验表单中的某一个/些字段"></a>只校验表单中的某一个/些字段</h2><div class="tip bolt"><p>在一些用户注册场景中,提交整个表单前有时候我们会做一些单独字段的校验,例如发送手机验证码,发送时我们只需要校验手机号码这个字段,可以这样做:</p></div><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="built_in">this</span>.$refs[<span class="string">'form'</span>].validateField(<span class="string">'mobile'</span>, <span class="function"><span class="params">valid</span> =></span> {</span><br><span class="line"> <span class="keyword">if</span> (valid) {</span><br><span class="line"> <span class="comment">// 发送验证码</span></span><br><span class="line"> }</span><br><span class="line">})</span><br></pre></td></tr></table></figure><p>需要多个字段,将参数改为数组形式即可。</p><hr><h2 id="移除对应表单项的校验结果"><a href="#移除对应表单项的校验结果" class="headerlink" title="移除对应表单项的校验结果"></a>移除对应表单项的校验结果</h2><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">el-form-item</span> <span class="attr">label</span>=<span class="string">"链接"</span> <span class="attr">prop</span>=<span class="string">"url"</span> <span class="attr">ref</span>=<span class="string">"refUrl"</span> <span class="attr">v-show</span>=<span class="string">"ruleForm.status==3"</span>></span></span><br><span class="line"><span class="tag"><<span class="name">el-input</span> <span class="attr">v-model</span>=<span class="string">"ruleForm.url"</span> <span class="attr">placeholder</span>=<span class="string">"请输入链接"</span>></span><span class="tag"></<span class="name">el-input</span>></span></span><br><span class="line"><span class="tag"></<span class="name">el-form-item</span>></span></span><br><span class="line"></span><br><span class="line">```js</span><br><span class="line">changeStatus() {</span><br><span class="line">this.$refs.refPath.clearValidate();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="弹窗重新打开时表单上次的校验信息未清除"><a href="#弹窗重新打开时表单上次的校验信息未清除" class="headerlink" title="弹窗重新打开时表单上次的校验信息未清除"></a>弹窗重新打开时表单上次的校验信息未清除</h2><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">el-dialog</span> @<span class="attr">close</span>=<span class="string">"onClose"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">el-form</span> <span class="attr">ref</span>=<span class="string">"form"</span>></span><span class="tag"></<span class="name">el-form</span>></span></span><br><span class="line"><span class="tag"></<span class="name">el-dialog</span>></span></span><br><span class="line"></span><br><span class="line">// 弹窗关闭时重置表单</span><br><span class="line">onClose() {</span><br><span class="line"> this.$refs['form'].resetFields()</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="表头与内容错位"><a href="#表头与内容错位" class="headerlink" title="表头与内容错位"></a>表头与内容错位</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">// 全局设置</span><br><span class="line"><span class="selector-class">.el-table--scrollable-y</span> <span class="selector-class">.el-table__body-wrapper</span> {</span><br><span class="line"> <span class="attribute">overflow-y</span>: overlay <span class="meta">!important</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="表单多级数据结构校验问题"><a href="#表单多级数据结构校验问题" class="headerlink" title="表单多级数据结构校验问题"></a>表单多级数据结构校验问题</h2><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">el-form</span> <span class="attr">:model</span>=<span class="string">"form"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">el-form-item</span> <span class="attr">label</span>=<span class="string">"部门"</span> <span class="attr">prop</span>=<span class="string">"dept"</span>></span><span class="tag"></<span class="name">el-form-item</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">el-form-item</span> <span class="attr">label</span>=<span class="string">"姓名"</span> <span class="attr">prop</span>=<span class="string">"user.name"</span>></span><span class="tag"></<span class="name">el-form-item</span>></span></span><br><span class="line"><span class="tag"></<span class="name">el-form</span>></span></span><br><span class="line"></span><br><span class="line">rules: {</span><br><span class="line"> 'user.name': [{ required: true, message: '姓名不能为空', trigger: 'blur' }]</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="表格跨分页多选"><a href="#表格跨分页多选" class="headerlink" title="表格跨分页多选"></a>表格跨分页多选</h2><div class="tip bell faa-horizontal animated"><p>其实根据文档,只需加上<span class='p red'>row-key</span>和<span class='p red'>reserve-selection</span>即可。</p></div><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">el-table</span> <span class="attr">row-key</span>=<span class="string">"id"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">el-table-column</span> <span class="attr">type</span>=<span class="string">"selection"</span> <span class="attr">reserve-selection</span>></span><span class="tag"></<span class="name">el-table-column</span>></span></span><br><span class="line"><span class="tag"></<span class="name">el-table</span>></span></span><br></pre></td></tr></table></figure><hr><h2 id="根据条件高亮行并去除默认hover颜色"><a href="#根据条件高亮行并去除默认hover颜色" class="headerlink" title="根据条件高亮行并去除默认hover颜色"></a>根据条件高亮行并去除默认hover颜色</h2><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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">el-table</span> <span class="attr">:row-class-name</span>=<span class="string">"tableRowClassName"</span>></span></span><br><span class="line"><span class="tag"></<span class="name">el-table</span>></span></span><br><span class="line"></span><br><span class="line">tableRowClassName({ row }) {</span><br><span class="line"> return row.status === 2 ? 'highlight' : ''</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// 设置全局</span><br><span class="line">.el-table .highlight {</span><br><span class="line"> background-color: #b6e8fe;</span><br><span class="line"> &:hover > td {</span><br><span class="line"> background-color: initial !important;</span><br><span class="line"> }</span><br><span class="line"> td {</span><br><span class="line"> background-color: initial !important;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="表单不想显示label但又想显示必填星号怎么办"><a href="#表单不想显示label但又想显示必填星号怎么办" class="headerlink" title="表单不想显示label但又想显示必填星号怎么办"></a>表单不想显示label但又想显示必填星号怎么办</h2><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">// label给个空格即可</span><br><span class="line"><span class="tag"><<span class="name">el-form</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">el-table</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">el-table-column</span> <span class="attr">label</span>=<span class="string">"名称"</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">el-form-item</span> <span class="attr">label</span>=<span class="string">" "</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">el-input</span> <span class="attr">placeholder</span>=<span class="string">"名称不能为空"</span> /></span></span><br><span class="line"> <span class="tag"></<span class="name">el-form-item</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">el-table-column</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">el-table</span>></span></span><br><span class="line"><span class="tag"></<span class="name">el-form</span>></span></span><br></pre></td></tr></table></figure><hr><h2 id="table-内嵌-input-调用-focus-方法无效"><a href="#table-内嵌-input-调用-focus-方法无效" class="headerlink" title="table 内嵌 input 调用 focus 方法无效"></a>table 内嵌 input 调用 focus 方法无效</h2><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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">el-table</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">el-table-column</span> <span class="attr">label</span>=<span class="string">"名称"</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">el-input</span> <span class="attr">ref</span>=<span class="string">"inputRef"</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">el-table-column</span>></span></span><br><span class="line"><span class="tag"></<span class="name">el-table</span>></span></span><br><span class="line"></span><br><span class="line">// 无效</span><br><span class="line">this.$refs['inputRef'].focus()</span><br><span class="line">this.$refs['inputRef'][0].focus()</span><br><span class="line">this.$refs['inputRef'].$el.children[0].focus()</span><br><span class="line"></span><br><span class="line">// 有效</span><br><span class="line"><span class="tag"><<span class="name">el-input</span> <span class="attr">id</span>=<span class="string">"inputRef"</span> /></span></span><br><span class="line">document.getElementById('inputRef').focus()</span><br></pre></td></tr></table></figure><hr><h2 id="表格内容超出省略"><a href="#表格内容超出省略" class="headerlink" title="表格内容超出省略"></a>表格内容超出省略</h2><figure class="highlight html"><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="tag"><<span class="name">el-table-column</span> <span class="attr">label</span>=<span class="string">"名称"</span> <span class="attr">prop</span>=<span class="string">"customerName"</span> <span class="attr">show-overflow-tooltip</span>></span></span><br><span class="line"><span class="tag"></<span class="name">el-table-column</span>></span></span><br></pre></td></tr></table></figure><hr><h2 id="el-tree-展开-收起所有节点"><a href="#el-tree-展开-收起所有节点" class="headerlink" title="el-tree 展开/收起所有节点"></a>el-tree 展开/收起所有节点</h2><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">el-tree</span> <span class="attr">ref</span>=<span class="string">"tree"</span>></span><span class="tag"></<span class="name">el-tree</span>></span></span><br><span class="line"></span><br><span class="line">expandTree(expand = true) {</span><br><span class="line"> const nodes = this.$refs['tree'].store._getAllNodes()</span><br><span class="line"> nodes.forEach(node => {</span><br><span class="line"> node.expanded = expand</span><br><span class="line"> })</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="修改el-input的高度"><a href="#修改el-input的高度" class="headerlink" title="修改el-input的高度"></a>修改el-input的高度</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">// 方式一:无效果</span><br><span class="line">>>> <span class="selector-class">.el-input__inner</span> {</span><br><span class="line"><span class="attribute">height</span>: <span class="number">37px</span> <span class="meta">!important</span>;</span><br><span class="line"><span class="attribute">line-height</span>: <span class="number">37px</span> <span class="meta">!important</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// 方式二:页面报错</span><br><span class="line">/deep/ <span class="selector-class">.el-input__inner</span> {</span><br><span class="line"><span class="attribute">height</span>: <span class="number">37px</span> <span class="meta">!important</span>;</span><br><span class="line"><span class="attribute">line-height</span>: <span class="number">37px</span> <span class="meta">!important</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// 方式三:成功</span><br><span class="line">::v-deep .el-input__inner {</span><br><span class="line">height: <span class="number">37px</span> <span class="meta">!important</span>;</span><br><span class="line"><span class="attribute">line-height</span>: <span class="number">37px</span> <span class="meta">!important</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="手动获取el-input焦点"><a href="#手动获取el-input焦点" class="headerlink" title="手动获取el-input焦点"></a>手动获取el-input焦点</h2><ul><li>需求:<blockquote><p>输入框一开始是隐藏的,点击按钮显示输入框并获取焦点。</p></blockquote><div class="tip cogs faa-horizontal animated"><p>把手动获取焦点的那段代码写在$nextTick()中即可。首先给标签加个属性ref=“searchBox”,然后点击按钮把控制显示的字段赋值为true,接着写下这行代码就好了。</p></div><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="built_in">this</span>.$nextTick(<span class="function">() =></span> {</span><br><span class="line"><span class="built_in">this</span>.$refs.searchBox.focus()</span><br><span class="line">});</span><br></pre></td></tr></table></figure></li></ul><hr><h2 id="el-table用v-if隐藏显示列和预期不符问题"><a href="#el-table用v-if隐藏显示列和预期不符问题" class="headerlink" title="el-table用v-if隐藏显示列和预期不符问题"></a>el-table用v-if隐藏显示列和预期不符问题</h2><div class="tip success"><p>给<span class='p red'>el-table-column</span>加一个<span class='p red'>key</span>属性,<span class='p red'>:key=Math.random()</span>或者其他的,确保每列的<span class='p red'>key</span>值不同即可。</p></div><hr><h2 id="对表格中的数据做处理"><a href="#对表格中的数据做处理" class="headerlink" title="对表格中的数据做处理"></a>对表格中的数据做处理</h2><blockquote><p>在使用<span class='p red'>el-table</span>的时候有的时候需要对表格中的数据做处理,需要用到<span class='p red'>filter</span>,虽然官方也有提供过滤的方法<span class='p red'>filter-method</span>,但是还是用自定义列,然后用<span class='p red'>filter</span>复用性好一些。</p></blockquote><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">el-table-column</span> <span class="attr">label</span>=<span class="string">"日期"</span>></span></span><br><span class="line"><span class="tag"><<span class="name">template</span> <span class="attr">slot-scope</span>=<span class="string">"scope"</span>></span></span><br><span class="line"><span class="tag"><<span class="name">span</span>></span>{{scope.row.date | dateConvert}}<span class="tag"></<span class="name">span</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">el-table-column</span>></span></span><br></pre></td></tr></table></figure><hr><h2 id="tabs标签中的name属性"><a href="#tabs标签中的name属性" class="headerlink" title="tabs标签中的name属性"></a>tabs标签中的name属性</h2><div class="tip cogs faa-horizontal animated"><p>因为给<span class='p red'>name</span>绑定了数字类型的数据,所以报错。<span class='p red'>name</span>属性要求的是字符串类型。在使用过滤器时,需要使用<span class='p red'>v-bind:name=item.id</span>来实现,使用<span class='p red'>:name=item.id</span>无法实现 </p></div><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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">el-tabs</span> <span class="attr">v-model</span>=<span class="string">"indexTab"</span>></span></span><br><span class="line"><span class="comment"><!-- 注意:indexTab属性也要为字符串。 --></span></span><br><span class="line"><span class="comment"><!-- 方案一:直接在标签属性上使用.toString() --></span></span><br><span class="line"><span class="comment"><!-- :name="item.id.toString()" --></span></span><br><span class="line"><span class="comment"><!-- 方案二:使用过滤器 --></span></span><br><span class="line"><el-tab-pane</span><br><span class="line">v-for="item in tabBar"</span><br><span class="line">:key="item.id"</span><br><span class="line">:label="item.title"</span><br><span class="line">v-bind:name="item.id | numToStr"</span><br><span class="line">></span><br><span class="line">用户管理</span><br><span class="line"><span class="tag"></<span class="name">el-tab-pane</span>></span></span><br><span class="line"><span class="tag"></<span class="name">el-tabs</span>></span></span><br></pre></td></tr></table></figure><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">filters: {</span><br><span class="line"><span class="function"><span class="title">numToStr</span>(<span class="params">num</span>)</span> {</span><br><span class="line">num = num.toString();</span><br><span class="line"><span class="keyword">return</span> num;</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="引入日期时间的时候遇到英文问题"><a href="#引入日期时间的时候遇到英文问题" class="headerlink" title="引入日期时间的时候遇到英文问题"></a>引入日期时间的时候遇到英文问题</h2><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> locale <span class="keyword">from</span> <span class="string">"element-ui/lib/locale/lang/zh-CN"</span>;</span><br><span class="line">Vue.use(ElementUI, {locale})</span><br></pre></td></tr></table></figure><p>表示全局配置element多语言组件</p><hr><h2 id="选择完成的日期时间结果打印"><a href="#选择完成的日期时间结果打印" class="headerlink" title="选择完成的日期时间结果打印"></a>选择完成的日期时间结果打印</h2><div class="tip cogs faa-horizontal animated"><p>框架返回的时间是这样的:Fri Nov 10 2000 04:01:01 GMT+0800 (中国标准时间),可以通过以下方式转换成:2021-08-14 10:01:20 </p></div>}<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> Day = <span class="keyword">new</span> <span class="built_in">Date</span>(e[<span class="number">0</span>]);</span><br><span class="line"><span class="keyword">let</span> Time = Day.getFullYear() +<span class="string">"-"</span> +<span class="built_in">this</span>.double(d.getMonth() + <span class="number">1</span>) + <span class="string">"-"</span> +<span class="built_in">this</span>.double(d.getDate()) + <span class="string">" "</span> +<span class="built_in">this</span>.double(d.getHours())+<span class="string">":"</span> +<span class="built_in">this</span>.double(d.getMinutes()) +<span class="string">":"</span> +<span class="built_in">this</span>.double(d.getSeconds());</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">double</span>(<span class="params">num</span>)</span> {</span><br><span class="line"><span class="keyword">if</span> (num < <span class="number">10</span>) {</span><br><span class="line"><span class="keyword">return</span> <span class="string">"0"</span> + num; <span class="comment">//如果时分秒少于10,则在前面加字符串0</span></span><br><span class="line">} <span class="keyword">else</span> {</span><br><span class="line"><span class="keyword">return</span> <span class="string">""</span> + num; <span class="comment">//否则,直接返回原有数字</span></span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="隐藏的el-scrollbar组件"><a href="#隐藏的el-scrollbar组件" class="headerlink" title="隐藏的el-scrollbar组件"></a>隐藏的el-scrollbar组件</h2><div class="tip cogs faa-horizontal animated"><p>element-ui中有个隐藏的组件官方并未给出文档,他是自带的一个自定义滚动组件,也是非常好用的~ </p></div><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">el-scrollbar</span> <span class="attr">wrap-class</span>=<span class="string">""</span> <span class="attr">view-class</span>=<span class="string">""</span> <span class="attr">:native</span>=<span class="string">"false"</span> ></span></span><br><span class="line">......</span><br><span class="line"><span class="tag"></<span class="name">el-scrollbar</span>></span></span><br></pre></td></tr></table></figure><hr><h2 id="相关文章"><a href="#相关文章" class="headerlink" title="相关文章"></a>相关文章</h2><div class="btns rounded grid5"> <a class="button" href='https://segmentfault.com/a/1190000024479045' title='element-ui之el-table的使用合集'><i class='fas fa-book-open'></i>element-ui之el-table的使用合集</a><a class="button" href='https://segmentfault.com/a/1190000023256421' title='Element-ui使用中遇到的问题总结'><i class='fas fa-book-open'></i>Element-ui使用中遇到的问题总结</a> </div>]]></content>
<summary type="html"><blockquote>
<p>部分内容转载自:<a href="https://juejin.cn/user/1239904849499911">8号的凌晨4点</a>的<a href="https://juejin.cn/post/6981083988286767117">一</summary>
<category term="Element-UI" scheme="http://imagineblog.host/categories/Element-UI/"/>
<category term="Element-UI" scheme="http://imagineblog.host/tags/Element-UI/"/>
</entry>
<entry>
<title>常用的一些CSS样式</title>
<link href="http://imagineblog.host/common-css/"/>
<id>http://imagineblog.host/common-css/</id>
<published>2021-08-08T16:00:00.000Z</published>
<updated>2022-08-31T08:04:19.373Z</updated>
<content type="html"><![CDATA[<h2 id="文本溢出隐藏"><a href="#文本溢出隐藏" class="headerlink" title="文本溢出隐藏"></a>文本溢出隐藏</h2><ul><li>单行文本<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">p</span>{</span><br><span class="line"> <span class="attribute">width</span>:<span class="number">200px</span>;</span><br><span class="line"> <span class="attribute">overflow</span>: hidden;</span><br><span class="line"> <span class="attribute">text-overflow</span>:ellipsis;</span><br><span class="line"> <span class="attribute">white-space</span>: nowrap;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li>多行文本<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">p</span> {</span><br><span class="line"> <span class="attribute">display</span>: -webkit-box;</span><br><span class="line"> -webkit-box-orient: vertical;</span><br><span class="line"> -webkit-line-clamp: <span class="number">3</span>;</span><br><span class="line"> <span class="attribute">overflow</span>: hidden;</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h2 id="中英文自动换行"><a href="#中英文自动换行" class="headerlink" title="中英文自动换行"></a>中英文自动换行</h2><blockquote><p>word-break:break-all;只对英文起作用,以字母作为换行依据word-wrap:break-word; 只对英文起作用,以单词作为换行依据white-space:pre-wrap; 只对中文起作用,强制换行white-space:nowrap; 强制不换行,都起作用</p></blockquote></li></ul><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">p</span>{</span><br><span class="line"> <span class="attribute">word-wrap</span>: break-word;</span><br><span class="line"> <span class="attribute">white-space</span>: normal;</span><br><span class="line"> <span class="attribute">word-break</span>: break-all;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">//不换行</span><br><span class="line"><span class="selector-class">.wrap</span> {</span><br><span class="line"> <span class="attribute">white-space</span>:nowrap;</span><br><span class="line">}</span><br><span class="line">//自动换行</span><br><span class="line"><span class="selector-class">.wrap</span> {</span><br><span class="line"> <span class="attribute">word-wrap</span>: break-word;</span><br><span class="line"> <span class="attribute">word-break</span>: normal;</span><br><span class="line">}</span><br><span class="line">//强制换行</span><br><span class="line"><span class="selector-class">.wrap</span> {</span><br><span class="line"> <span class="attribute">word-break</span>:break-all;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="文字阴影"><a href="#文字阴影" class="headerlink" title="文字阴影"></a>文字阴影</h2><blockquote><p>X-offset:指阴影居于字体水平偏移的位置。<br>Y-offset:指阴影居于字体垂直偏移的位置。<br>Blur:指阴影的模糊值。<br>color:指阴影的颜色。</p></blockquote><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></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">p</span>{</span><br><span class="line"><span class="attribute">text-shadow</span>: <span class="number">5px</span> <span class="number">5px</span> <span class="number">5px</span> <span class="number">#FF0000</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="设置placeholder属性的字体样式"><a href="#设置placeholder属性的字体样式" class="headerlink" title="设置placeholder属性的字体样式"></a>设置placeholder属性的字体样式</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">input</span>::-webkit-input-placeholder { /* Chrome/Opera/Safari */</span><br><span class="line"> color: red;</span><br><span class="line">}</span><br><span class="line"><span class="selector-tag">input</span>::-moz-placeholder { /* Firefox <span class="number">19</span>+ */</span><br><span class="line"> color: red;</span><br><span class="line">}</span><br><span class="line"><span class="selector-tag">input</span>:-ms-input-placeholder { /* IE <span class="number">10</span>+ */</span><br><span class="line"> color: red;</span><br><span class="line">}</span><br><span class="line"><span class="selector-tag">input</span>:-moz-placeholder { /* Firefox <span class="number">18</span>- */</span><br><span class="line"> color: red;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="IOS页面滑动卡顿"><a href="#IOS页面滑动卡顿" class="headerlink" title="IOS页面滑动卡顿"></a>IOS页面滑动卡顿</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">body</span>,<span class="selector-tag">html</span>{</span><br><span class="line"> -webkit-<span class="attribute">overflow</span>-scrolling: touch;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="滚动条样式"><a href="#滚动条样式" class="headerlink" title="滚动条样式"></a>滚动条样式</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.test</span>::-webkit-scrollbar{</span><br><span class="line"> /*滚动条整体样式*/</span><br><span class="line"> width : <span class="number">10px</span>; <span class="comment">/*高宽分别对应横竖滚动条的尺寸*/</span></span><br><span class="line"> <span class="attribute">height</span>: <span class="number">1px</span>;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.test</span>::-webkit-scrollbar-thumb {</span><br><span class="line"> /*滚动条里面小方块*/</span><br><span class="line"> border-radius : <span class="number">10px</span>;</span><br><span class="line"> <span class="attribute">background-color</span>: skyblue;</span><br><span class="line"> <span class="attribute">background-image</span>: <span class="built_in">-webkit-linear-gradient</span>(</span><br><span class="line"> <span class="number">45deg</span>,</span><br><span class="line"> <span class="built_in">rgba</span>(<span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>, <span class="number">0.2</span>) <span class="number">25%</span>,</span><br><span class="line"> transparent <span class="number">25%</span>,</span><br><span class="line"> transparent <span class="number">50%</span>,</span><br><span class="line"> <span class="built_in">rgba</span>(<span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>, <span class="number">0.2</span>) <span class="number">50%</span>,</span><br><span class="line"> <span class="built_in">rgba</span>(<span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>, <span class="number">0.2</span>) <span class="number">75%</span>,</span><br><span class="line"> transparent <span class="number">75%</span>,</span><br><span class="line"> transparent</span><br><span class="line"> );</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.test</span>::-webkit-scrollbar-track {</span><br><span class="line"> /*滚动条里面轨道*/</span><br><span class="line"> box-shadow : inset <span class="number">0</span> <span class="number">0</span> <span class="number">5px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.2</span>);</span><br><span class="line"> <span class="attribute">background</span> : <span class="number">#ededed</span>;</span><br><span class="line"> <span class="attribute">border-radius</span>: <span class="number">10px</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="selector-class">.demo</span>::-webkit-scrollbar {</span><br><span class="line"> display: none; <span class="comment">/* Chrome Safari */</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.demo</span> {</span><br><span class="line"> scrollbar-<span class="attribute">width</span>: none; <span class="comment">/* firefox */</span></span><br><span class="line"> -ms-<span class="attribute">overflow</span>-style: none; <span class="comment">/* IE 10+ */</span></span><br><span class="line"> <span class="attribute">overflow-x</span>: hidden;</span><br><span class="line"> <span class="attribute">overflow-y</span>: auto;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="绘制三角形"><a href="#绘制三角形" class="headerlink" title="绘制三角形"></a>绘制三角形</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><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="selector-tag">div</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">0</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">0</span>;</span><br><span class="line"> <span class="attribute">border-width</span>: <span class="number">0</span> <span class="number">40px</span> <span class="number">40px</span>;</span><br><span class="line"> <span class="attribute">border-style</span>: solid;</span><br><span class="line"> <span class="attribute">border-color</span>: transparent transparent red;</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"><div id="blue"><div></span><br><span class="line"></span><br><span class="line"><span class="selector-id">#blue</span> {</span><br><span class="line"> <span class="attribute">position</span>:relative;</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">0</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">0</span>;</span><br><span class="line"> <span class="attribute">border-width</span>: <span class="number">0</span> <span class="number">40px</span> <span class="number">40px</span>;</span><br><span class="line"> <span class="attribute">border-style</span>: solid;</span><br><span class="line"> <span class="attribute">border-color</span>: transparent transparent blue;</span><br><span class="line">}</span><br><span class="line"><span class="selector-id">#blue</span>:after {</span><br><span class="line"> content: <span class="string">""</span>;</span><br><span class="line"> <span class="attribute">position</span>: absolute;</span><br><span class="line"> <span class="attribute">top</span>: <span class="number">1px</span>;</span><br><span class="line"> <span class="attribute">left</span>: -<span class="number">38px</span>;</span><br><span class="line"> <span class="attribute">border-width</span>: <span class="number">0</span> <span class="number">38px</span> <span class="number">38px</span>;</span><br><span class="line"> <span class="attribute">border-style</span>: solid;</span><br><span class="line"> <span class="attribute">border-color</span>: transparent transparent yellow;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="table表格边框合并"><a href="#table表格边框合并" class="headerlink" title="table表格边框合并"></a>table表格边框合并</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">table</span>,<span class="selector-tag">tr</span>,<span class="selector-tag">td</span>{</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#666</span>;</span><br><span class="line">}</span><br><span class="line"><span class="selector-tag">table</span>{</span><br><span class="line"> <span class="attribute">border-collapse</span>: collapse;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="css选取第n个标签元素"><a href="#css选取第n个标签元素" class="headerlink" title="css选取第n个标签元素"></a>css选取第n个标签元素</h2><ul><li>first-child 表示选择列表中的第一个标签</li><li>last-child 表示选择列表中的最后一个标签</li><li>nth-child(3) 表示选择列表中的第 3 个标签</li><li>nth-child(2n) 这个表示选择列表中的偶数标签</li><li>nth-child(2n-1) 这个表示选择列表中的奇数标签</li><li>nth-child(n+3) 这个表示选择列表中的标签从第 3 个开始到最后</li><li>nth-child(-n+3) 这个表示选择列表中的标签从 0 到 3,即小于 3 的标签</li><li>nth-last-child(3) 这个表示选择列表中的倒数第 3 个标签</li></ul><h2 id="onerror-处理图片异常"><a href="#onerror-处理图片异常" class="headerlink" title="onerror 处理图片异常"></a>onerror 处理图片异常</h2><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">img</span> <span class="attr">onerror</span>=<span class="string">"this.src='url;this.onerror=null'"</span> /></span></span><br></pre></td></tr></table></figure><h2 id="文字间距"><a href="#文字间距" class="headerlink" title="文字间距"></a>文字间距</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">p</span>{</span><br><span class="line"> <span class="attribute">text-indent</span>:<span class="number">10px</span>;//单词抬头距离</span><br><span class="line"> <span class="attribute">letter-spacing</span>:<span class="number">10px</span>;//间距</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="元素占满整个屏幕"><a href="#元素占满整个屏幕" class="headerlink" title="元素占满整个屏幕"></a>元素占满整个屏幕</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.dom</span>{</span><br><span class="line"> <span class="attribute">width</span>:<span class="number">100%</span>;</span><br><span class="line"> <span class="attribute">height</span>:<span class="number">100vh</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="文本两端对齐"><a href="#文本两端对齐" class="headerlink" title="文本两端对齐"></a>文本两端对齐</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.wrap</span> {</span><br><span class="line"> <span class="attribute">text-align</span>: justify;</span><br><span class="line"> text-justify: distribute-all-lines; //ie6-<span class="number">8</span></span><br><span class="line"> <span class="attribute">text-align-last</span>: justify; //一个块或行的最后一行对齐方式</span><br><span class="line"> -moz-<span class="attribute">text-align-last</span>: justify;</span><br><span class="line"> -webkit-<span class="attribute">text-align-last</span>: justify;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="文字竖向排版"><a href="#文字竖向排版" class="headerlink" title="文字竖向排版"></a>文字竖向排版</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">// 单列展示时</span><br><span class="line"><span class="selector-class">.wrap</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">25px</span>;</span><br><span class="line"> <span class="attribute">line-height</span>: <span class="number">18px</span>;</span><br><span class="line"> <span class="attribute">height</span>: auto;</span><br><span class="line"> <span class="attribute">font-size</span>: <span class="number">12px</span>;</span><br><span class="line"> <span class="attribute">padding</span>: <span class="number">8px</span> <span class="number">5px</span>;</span><br><span class="line"> <span class="attribute">word-wrap</span>: break-word;<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="selector-class">.wrap</span> {</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">210px</span>;</span><br><span class="line"> <span class="attribute">line-height</span>: <span class="number">30px</span>;</span><br><span class="line"> <span class="attribute">text-align</span>: justify;</span><br><span class="line"> writing-mode: vertical-lr; //从左向右 </span><br><span class="line"> writing-mode: tb-lr; //IE从左向右</span><br><span class="line"> //writing-mode: vertical-rl; -- 从右向左</span><br><span class="line"> //writing-mode: tb-rl; -- 从右向左</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="禁止用户选择"><a href="#禁止用户选择" class="headerlink" title="禁止用户选择"></a>禁止用户选择</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.wrap</span> {</span><br><span class="line"> -webkit-touch-callout: none;</span><br><span class="line"> -webkit-user-select: none;</span><br><span class="line"> -khtml-user-select: none;</span><br><span class="line"> -moz-user-select: none;</span><br><span class="line"> -ms-user-select: none;</span><br><span class="line"> user-select: none;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="页面动画出现闪烁问题"><a href="#页面动画出现闪烁问题" class="headerlink" title="页面动画出现闪烁问题"></a>页面动画出现闪烁问题</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.cube</span> {</span><br><span class="line"> -webkit-<span class="attribute">backface-visibility</span>: hidden;</span><br><span class="line"> <span class="attribute">backface-visibility</span>: hidden;</span><br><span class="line"> </span><br><span class="line"> -webkit-<span class="attribute">perspective</span>: <span class="number">1000</span>;</span><br><span class="line"> <span class="attribute">perspective</span>: <span class="number">1000</span>;</span><br><span class="line"> <span class="comment">/* Other transform properties here */</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">--------------------------------------------------------------------</span><br><span class="line"><span class="selector-class">.cube</span> {</span><br><span class="line"> -webkit-<span class="attribute">transform</span>: <span class="built_in">translate3d</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line"> <span class="attribute">transform</span>: <span class="built_in">translate3d</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line"> <span class="comment">/* Other transform properties here */</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="字母大小写转换"><a href="#字母大小写转换" class="headerlink" title="字母大小写转换"></a>字母大小写转换</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">p</span> {<span class="attribute">text-transform</span>: uppercase} // 将所有字母变成大写字母</span><br><span class="line"><span class="selector-tag">p</span> {<span class="attribute">text-transform</span>: lowercase} // 将所有字母变成小写字母</span><br><span class="line"><span class="selector-tag">p</span> {<span class="attribute">text-transform</span>: capitalize} // 首字母大写</span><br><span class="line"><span class="selector-tag">p</span> {<span class="attribute">font-variant</span>: small-caps} // 将字体变成小型的大写字母</span><br></pre></td></tr></table></figure><h2 id="将容器设置为透明"><a href="#将容器设置为透明" class="headerlink" title="将容器设置为透明"></a>将容器设置为透明</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.wrap</span> { </span><br><span class="line"> <span class="attribute">filter</span>:<span class="built_in">alpha</span>(opacity=<span class="number">50</span>); </span><br><span class="line"> -moz-<span class="attribute">opacity</span>:<span class="number">0.5</span>; </span><br><span class="line"> -khtml-<span class="attribute">opacity</span>: <span class="number">0.5</span>; </span><br><span class="line"> <span class="attribute">opacity</span>: <span class="number">0.5</span>; </span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="transition闪屏问题"><a href="#transition闪屏问题" class="headerlink" title="transition闪屏问题"></a>transition闪屏问题</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.wrap</span> {</span><br><span class="line"> -webkit-<span class="attribute">transform-style</span>: preserve-<span class="number">3</span>d;</span><br><span class="line"> -webkit-<span class="attribute">backface-visibility</span>: hidden;</span><br><span class="line"> -webkit-<span class="attribute">perspective</span>: <span class="number">1000</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="识别字符串里的-‘-n’-并换行"><a href="#识别字符串里的-‘-n’-并换行" class="headerlink" title="识别字符串里的 ‘\n’ 并换行"></a>识别字符串里的 ‘\n’ 并换行</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">body</span> {</span><br><span class="line"> <span class="attribute">white-space</span>: pre-line;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="移除a标签被点链接的边框"><a href="#移除a标签被点链接的边框" class="headerlink" title="移除a标签被点链接的边框"></a>移除a标签被点链接的边框</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">a</span> {</span><br><span class="line"> <span class="attribute">outline</span>: none;//或者outline: <span class="number">0</span></span><br><span class="line"> text-decoration:none; //取消默认下划线</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="显示链接之后的URL"><a href="#显示链接之后的URL" class="headerlink" title="显示链接之后的URL"></a>显示链接之后的URL</h2><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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"https://www.baidu.com"</span>></span>百度<span class="tag"></<span class="name">a</span>></span></span><br><span class="line"><span class="tag"><<span class="name">style</span>></span></span><br><span class="line"><span class="css"><span class="selector-tag">a</span>:after {content: <span class="string">" ("</span> <span class="built_in">attr</span>(href) <span class="string">")"</span>;}</span></span><br><span class="line"><span class="tag"></<span class="name">style</span>></span></span><br></pre></td></tr></table></figure><h2 id="select内容居中显示、下拉内容右对齐"><a href="#select内容居中显示、下拉内容右对齐" class="headerlink" title="select内容居中显示、下拉内容右对齐"></a>select内容居中显示、下拉内容右对齐</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">select{</span><br><span class="line"> <span class="attribute">text-align</span>: center;</span><br><span class="line"> <span class="attribute">text-align-last</span>: center;</span><br><span class="line">}</span><br><span class="line">select option {</span><br><span class="line"> <span class="attribute">direction</span>: rtl;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="修改input输入框中光标的颜色不改变字体的颜色"><a href="#修改input输入框中光标的颜色不改变字体的颜色" class="headerlink" title="修改input输入框中光标的颜色不改变字体的颜色"></a>修改input输入框中光标的颜色不改变字体的颜色</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">input</span>{</span><br><span class="line"> <span class="attribute">color</span>: <span class="number">#fff</span>;</span><br><span class="line"> caret-<span class="attribute">color</span>: red;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="子元素固定宽度-父元素宽度被撑开"><a href="#子元素固定宽度-父元素宽度被撑开" class="headerlink" title="子元素固定宽度 父元素宽度被撑开"></a>子元素固定宽度 父元素宽度被撑开</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">// 父元素下的子元素是行内元素</span><br><span class="line"><span class="selector-class">.wrap</span> {</span><br><span class="line"> <span class="attribute">white-space</span>: nowrap;</span><br><span class="line">}</span><br><span class="line">// 若父元素下的子元素是块级元素</span><br><span class="line"><span class="selector-class">.wrap</span> {</span><br><span class="line"> <span class="attribute">white-space</span>: nowrap; // 子元素不被换行</span><br><span class="line"> <span class="attribute">display</span>: inline-block;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="div里的图片和文字上下居中"><a href="#div里的图片和文字上下居中" class="headerlink" title="div里的图片和文字上下居中"></a>div里的图片和文字上下居中</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.wrap</span> {</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">100</span>,</span><br><span class="line"> line-height: <span class="number">100</span></span><br><span class="line">}</span><br><span class="line"><span class="selector-tag">img</span> {</span><br><span class="line"> vertival-align:middle</span><br><span class="line">}</span><br><span class="line">// <span class="attribute">vertical-align</span> css的属性<span class="attribute">vertical-align</span>用来指定行内元素(inline)或表格单元格(<span class="selector-tag">table</span>-cell)元素的垂直对齐方式。</span><br><span class="line">只对行内元素、表格单元格元素生效,不能用它垂直对齐块级元素</span><br><span class="line">// <span class="attribute">vertical-align</span>:baseline/<span class="attribute">top</span>/middle/<span class="attribute">bottom</span>/sub/text-<span class="attribute">top</span>;</span><br></pre></td></tr></table></figure><h2 id="宽高等比例自适应矩形"><a href="#宽高等比例自适应矩形" class="headerlink" title="宽高等比例自适应矩形"></a>宽高等比例自适应矩形</h2><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></pre></td><td class="code"><pre><span class="line">.scale {</span><br><span class="line"> width: 100%;</span><br><span class="line"> padding-bottom: 56.25%;</span><br><span class="line"> height: 0;</span><br><span class="line"> position: relative; </span><br><span class="line">}</span><br><span class="line">.item {</span><br><span class="line"> position: absolute; </span><br><span class="line"> width: 100%;</span><br><span class="line"> height: 100%;</span><br><span class="line"> background-color: #499e56;</span><br><span class="line">} </span><br><span class="line"><span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"scale"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"item"</span>></span></span><br><span class="line"> 这里是所有子元素的容器</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></pre></td></tr></table></figure><h2 id="css3动画"><a href="#css3动画" class="headerlink" title="css3动画"></a>css3动画</h2><h3 id="旋转动画"><a href="#旋转动画" class="headerlink" title="旋转动画"></a>旋转动画</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"loader"</span>></span><span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"><<span class="name">style</span>></span></span><br><span class="line">.loader {</span><br><span class="line"><span class="css"> <span class="attribute">border</span>: <span class="number">16px</span> solid <span class="number">#f3f3f3</span>;</span></span><br><span class="line"><span class="css"> <span class="attribute">border-radius</span>: <span class="number">50%</span>;</span></span><br><span class="line"><span class="css"> <span class="attribute">border-top</span>: <span class="number">16px</span> solid <span class="number">#3498db</span>;</span></span><br><span class="line"><span class="css"> <span class="attribute">width</span>: <span class="number">80px</span>;</span></span><br><span class="line"><span class="css"> <span class="attribute">height</span>: <span class="number">80px</span>;</span></span><br><span class="line"><span class="css"> -webkit-<span class="attribute">animation</span>: spin <span class="number">2s</span> linear infinite;</span></span><br><span class="line"><span class="css"> <span class="attribute">animation</span>: spin <span class="number">2s</span> linear infinite;</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="keyword">@-webkit-keyframes</span> spin {</span></span><br><span class="line"><span class="css"> <span class="number">0%</span> { -webkit-<span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">0deg</span>); }</span></span><br><span class="line"><span class="css"> <span class="number">100%</span> { -webkit-<span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">360deg</span>); }</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="keyword">@keyframes</span> spin {</span></span><br><span class="line"><span class="css"> <span class="number">0%</span> { <span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">0deg</span>); }</span></span><br><span class="line"><span class="css"> <span class="number">100%</span> { <span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">360deg</span>); }</span></span><br><span class="line">}</span><br><span class="line"><span class="tag"></<span class="name">style</span>></span></span><br><span class="line"></span><br><span class="line">### 文字/背景渐变</span><br><span class="line">```html</span><br><span class="line"><span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"text_signature "</span> ></span>前端css动画<span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"><<span class="name">style</span>></span></span><br><span class="line">.text_signature {</span><br><span class="line"><span class="css"> -webkit-<span class="attribute">background-clip</span>: text;</span></span><br><span class="line"><span class="css"> -webkit-text-fill-<span class="attribute">color</span>: transparent;</span></span><br><span class="line"><span class="css"> <span class="attribute">background-image</span>: <span class="built_in">linear-gradient</span>(to right, <span class="number">#ec2239</span>, <span class="number">#40a4e2</span>,<span class="number">#ea96f5</span>);</span></span><br><span class="line"><span class="css"> <span class="attribute">width</span>: <span class="number">320px</span>;</span></span><br><span class="line">}</span><br><span class="line"><span class="tag"></<span class="name">style</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">div</span> <span class="attr">class</span>=<span class="string">"text_gradient"</span>></span><span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"><<span class="name">style</span>></span> </span><br><span class="line">.text_gradient{</span><br><span class="line"><span class="css"> <span class="attribute">width</span>:<span class="number">500px</span>;</span></span><br><span class="line"><span class="css"> <span class="attribute">height</span>:<span class="number">100px</span>;</span></span><br><span class="line"><span class="css"> <span class="attribute">background</span>: <span class="built_in">linear-gradient</span>(<span class="number">25deg</span>, <span class="built_in">rgb</span>(<span class="number">79</span>, <span class="number">107</span>, <span class="number">208</span>), <span class="built_in">rgb</span>(<span class="number">98</span>, <span class="number">141</span>, <span class="number">185</span>), <span class="built_in">rgb</span>(<span class="number">102</span>, <span class="number">175</span>, <span class="number">161</span>), <span class="built_in">rgb</span>(<span class="number">92</span>, <span class="number">210</span>, <span class="number">133</span>)) <span class="built_in">rgb</span>(<span class="number">182</span>, <span class="number">228</span>, <span class="number">253</span>);</span></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><h3 id="边框阴影"><a href="#边框阴影" class="headerlink" title="边框阴影"></a>边框阴影</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"text_shadow"</span>></span><span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"><<span class="name">style</span>></span> </span><br><span class="line">.text_shadow{</span><br><span class="line"><span class="css"> <span class="attribute">width</span>:<span class="number">500px</span>;</span></span><br><span class="line"><span class="css"> <span class="attribute">height</span>:<span class="number">100px</span>;</span></span><br><span class="line"><span class="css"> <span class="attribute">box-shadow</span>: <span class="number">0px</span> <span class="number">0px</span> <span class="number">13px</span> <span class="number">1px</span> <span class="built_in">rgba</span>(<span class="number">51</span>, <span class="number">51</span>, <span class="number">51</span>, <span class="number">0.1</span>);</span></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><h3 id="文字立体效果"><a href="#文字立体效果" class="headerlink" title="文字立体效果"></a>文字立体效果</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"text_solid"</span>></span>文字立体效果<span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"><<span class="name">style</span>></span> </span><br><span class="line">.text_solid{</span><br><span class="line"><span class="css"> <span class="attribute">font-size</span>: <span class="number">32px</span>;</span></span><br><span class="line"><span class="css"> <span class="attribute">text-align</span>: center;</span></span><br><span class="line"><span class="css"> <span class="attribute">font-weight</span>: bold;</span></span><br><span class="line"><span class="css"> <span class="attribute">line-height</span>:<span class="number">100px</span>;</span></span><br><span class="line"><span class="css"> <span class="attribute">text-transform</span>:uppercase;</span></span><br><span class="line"><span class="css"> <span class="attribute">position</span>: relative;</span></span><br><span class="line"><span class="css"> <span class="attribute">background-color</span>: <span class="number">#333</span>;</span></span><br><span class="line"><span class="css"> <span class="attribute">color</span>:<span class="number">#fff</span>;</span></span><br><span class="line"><span class="css"> <span class="attribute">text-shadow</span>:</span></span><br><span class="line"> 0px 1px 0px #c0c0c0,</span><br><span class="line"> 0px 2px 0px #b0b0b0,</span><br><span class="line"> 0px 3px 0px #a0a0a0,</span><br><span class="line"> 0px 4px 0px #909090,</span><br><span class="line"> 0px 5px 10px rgba(0, 0, 0, 0.6);</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><hr><h2 id="全屏背景图"><a href="#全屏背景图" class="headerlink" title="全屏背景图"></a>全屏背景图</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.swper</span>{</span><br><span class="line"> <span class="attribute">background-image</span>: <span class="built_in">url</span>(<span class="string">./img/bg.jpg</span>);</span><br><span class="line"> <span class="attribute">width</span>:<span class="number">100%</span>;</span><br><span class="line"> <span class="attribute">height</span>:<span class="number">100%</span>;//父级高不为<span class="number">100%</span>请使用<span class="number">100vh</span></span><br><span class="line"> zoom: <span class="number">1</span>;</span><br><span class="line"> <span class="attribute">background-color</span>: <span class="number">#fff</span>;</span><br><span class="line"> <span class="attribute">background-repeat</span>: no-repeat;</span><br><span class="line"> <span class="attribute">background-size</span>: cover;</span><br><span class="line"> -webkit-<span class="attribute">background-size</span>: cover;</span><br><span class="line"> -o-<span class="attribute">background-size</span>: cover;</span><br><span class="line"> <span class="attribute">background-position</span>: center <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="文字描边"><a href="#文字描边" class="headerlink" title="文字描边"></a>文字描边</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.stroke</span> {</span><br><span class="line"> -webkit-text-stroke: <span class="number">1px</span> greenyellow;</span><br><span class="line"> text-stroke: <span class="number">1px</span> greenyellow;</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="selector-class">.stroke</span> {</span><br><span class="line"> <span class="attribute">text-shadow</span>:<span class="number">#000</span> <span class="number">1px</span> <span class="number">0</span> <span class="number">0</span>,<span class="number">#000</span> <span class="number">0</span> <span class="number">1px</span> <span class="number">0</span>,<span class="number">#000</span> -<span class="number">1px</span> <span class="number">0</span> <span class="number">0</span>,<span class="number">#000</span> <span class="number">0</span> -<span class="number">1px</span> <span class="number">0</span>;</span><br><span class="line"> -webkit-<span class="attribute">text-shadow</span>:<span class="number">#000</span> <span class="number">1px</span> <span class="number">0</span> <span class="number">0</span>,<span class="number">#000</span> <span class="number">0</span> <span class="number">1px</span> <span class="number">0</span>,<span class="number">#000</span> -<span class="number">1px</span> <span class="number">0</span> <span class="number">0</span>,<span class="number">#000</span> <span class="number">0</span> -<span class="number">1px</span> <span class="number">0</span>;</span><br><span class="line"> -moz-<span class="attribute">text-shadow</span>:<span class="number">#000</span> <span class="number">1px</span> <span class="number">0</span> <span class="number">0</span>,<span class="number">#000</span> <span class="number">0</span> <span class="number">1px</span> <span class="number">0</span>,<span class="number">#000</span> -<span class="number">1px</span> <span class="number">0</span> <span class="number">0</span>,<span class="number">#000</span> <span class="number">0</span> -<span class="number">1px</span> <span class="number">0</span>;</span><br><span class="line"> *<span class="attribute">filter</span>: <span class="built_in">Glow</span>(color=<span class="number">#000</span>, strength=<span class="number">1</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="解决1px边框变粗问题"><a href="#解决1px边框变粗问题" class="headerlink" title="解决1px边框变粗问题"></a>解决1px边框变粗问题</h2><p>比如在2倍屏时1px的像素实际对应2个物理像素</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></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.dom</span>{</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">1px</span>;</span><br><span class="line"> <span class="attribute">background</span>: <span class="number">#dbdbdb</span>;</span><br><span class="line"> <span class="attribute">transform</span>:<span class="built_in">scaleY</span>(<span class="number">0.5</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="css不同单位运算"><a href="#css不同单位运算" class="headerlink" title="css不同单位运算"></a>css不同单位运算</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.div</span>{ </span><br><span class="line"> <span class="attribute">width</span>: <span class="built_in">calc</span>(<span class="number">100%</span> - <span class="number">50px</span>); </span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="文字模糊效果"><a href="#文字模糊效果" class="headerlink" title="文字模糊效果"></a>文字模糊效果</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.vague_text</span>{</span><br><span class="line"> <span class="attribute">color</span>: transparent; </span><br><span class="line"> <span class="attribute">text-shadow</span>: <span class="number">#111</span> <span class="number">0</span> <span class="number">0</span> <span class="number">5px</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="通过滤镜让图标变灰"><a href="#通过滤镜让图标变灰" class="headerlink" title="通过滤镜让图标变灰"></a>通过滤镜让图标变灰</h2><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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">''</span> <span class="attr">class</span>=<span class="string">'icon'</span>></span><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">'01.jpg'</span> /></span><span class="tag"></<span class="name">a</span>></span></span><br><span class="line"><span class="tag"><<span class="name">style</span>></span></span><br><span class="line">.icon{</span><br><span class="line"><span class="css"> -webkit-<span class="attribute">filter</span>: <span class="built_in">grayscale</span>(<span class="number">100%</span>);</span></span><br><span class="line"><span class="css"> -moz-<span class="attribute">filter</span>: <span class="built_in">grayscale</span>(<span class="number">100%</span>);</span></span><br><span class="line"><span class="css"> -ms-<span class="attribute">filter</span>: <span class="built_in">grayscale</span>(<span class="number">100%</span>);</span></span><br><span class="line"><span class="css"> -o-<span class="attribute">filter</span>: <span class="built_in">grayscale</span>(<span class="number">100%</span>); </span></span><br><span class="line"><span class="css"> <span class="attribute">filter</span>: <span class="built_in">grayscale</span>(<span class="number">100%</span>);</span></span><br><span class="line"><span class="css"> <span class="attribute">filter</span>: gray;</span></span><br><span class="line">}</span><br><span class="line"><span class="css"><span class="selector-class">.icon</span><span class="selector-pseudo">:hover</span>{</span></span><br><span class="line"><span class="css"> <span class="attribute">filter</span>: none;</span></span><br><span class="line"><span class="css"> -webkit-<span class="attribute">filter</span>: <span class="built_in">grayscale</span>(<span class="number">0%</span>);</span></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>]]></content>
<summary type="html"><h2 id="文本溢出隐藏"><a href="#文本溢出隐藏" class="headerlink" title="文本溢出隐藏"></a>文本溢出隐藏</h2><ul>
<li>单行文本<figure class="highlight css"><table><tr><td</summary>
<category term="CSS" scheme="http://imagineblog.host/categories/CSS/"/>
<category term="CSS" scheme="http://imagineblog.host/tags/CSS/"/>
</entry>
<entry>
<title>css水平垂直居中</title>
<link href="http://imagineblog.host/gqs30l/"/>
<id>http://imagineblog.host/gqs30l/</id>
<published>2021-07-22T03:37:03.000Z</published>
<updated>2022-08-31T08:04:19.377Z</updated>
<content type="html"><![CDATA[<blockquote><p><em>这是一个很常见的样式布局,网上也有很多的实现方式,本文主要是针对一些比较常用到的方法做一下总结,记录一下。</em></p></blockquote><p>现有实现方式大致的思路归纳为以下几种:</p><ul><li>固定宽高居中<ul><li>absolute + margin auto</li><li>absolute + 负 margin</li><li>absolute + calc</li></ul></li><li>不定宽高居中<ul><li> lineheight</li><li>flex</li><li>absolute + transform</li><li>grid</li><li>table-cell</li></ul></li></ul><p>公共代码(后面代码都基于这里)</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"out"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"inner"</span>></span>水平垂直居中<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></pre></td></tr></table></figure><p>实现的效果:<br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/center.png"></p><hr><h2 id="absolute-margin-auto"><a href="#absolute-margin-auto" class="headerlink" title="absolute + margin auto"></a>absolute + margin auto</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><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="selector-class">.out</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#000</span>;</span><br><span class="line"> <span class="attribute">position</span>: relative;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.inner</span> {</span><br><span class="line"> <span class="attribute">background-color</span>: blueviolet;</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">300px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">300px</span>;</span><br><span class="line"> <span class="attribute">position</span>: absolute;</span><br><span class="line"> <span class="attribute">top</span>: <span class="number">0</span>;</span><br><span class="line"> <span class="attribute">left</span>: <span class="number">0</span>;</span><br><span class="line"> <span class="attribute">right</span>: <span class="number">0</span>;</span><br><span class="line"> <span class="attribute">bottom</span>: <span class="number">0</span>;</span><br><span class="line"> <span class="attribute">margin</span>: auto;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="absolute-负-margin"><a href="#absolute-负-margin" class="headerlink" title="absolute + 负 margin"></a>absolute + 负 margin</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.out</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#000</span>;</span><br><span class="line"> <span class="attribute">position</span>: relative;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.inner</span> {</span><br><span class="line"> <span class="attribute">background-color</span>: blueviolet;</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">300px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">300px</span>;</span><br><span class="line"> <span class="attribute">position</span>: absolute;</span><br><span class="line"> <span class="attribute">top</span>: <span class="number">50%</span>;</span><br><span class="line"> <span class="attribute">left</span>: <span class="number">50%</span>;</span><br><span class="line"> <span class="attribute">margin-left</span>: -<span class="number">150px</span>;</span><br><span class="line"> <span class="attribute">margin-top</span>: -<span class="number">150px</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="absolute-calc"><a href="#absolute-calc" class="headerlink" title="absolute + calc"></a>absolute + calc</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.out</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#000</span>;</span><br><span class="line"> <span class="attribute">position</span>: relative;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.inner</span> {</span><br><span class="line"> <span class="attribute">background-color</span>: blueviolet;</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">300px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">300px</span>;</span><br><span class="line"> <span class="attribute">position</span>: absolute;</span><br><span class="line"> <span class="attribute">top</span>: <span class="built_in">calc</span>(<span class="number">50%</span> - <span class="number">150px</span>);</span><br><span class="line"> <span class="attribute">left</span>: <span class="built_in">calc</span>(<span class="number">50%</span> - <span class="number">150px</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="lineheight"><a href="#lineheight" class="headerlink" title="lineheight"></a>lineheight</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.out</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#000</span>;</span><br><span class="line"> <span class="attribute">line-height</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">text-align</span>: center;</span><br><span class="line"> <span class="attribute">font-size</span>: <span class="number">0px</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.inner</span> {</span><br><span class="line"> <span class="attribute">font-size</span>: <span class="number">16px</span>;</span><br><span class="line"> <span class="attribute">background-color</span>: blueviolet;</span><br><span class="line"> <span class="attribute">display</span>: inline-block;</span><br><span class="line"> <span class="attribute">vertical-align</span>: middle;</span><br><span class="line"> <span class="attribute">line-height</span>: initial;</span><br><span class="line"> <span class="comment">/* 若需要设置元素的宽高时 */</span></span><br><span class="line"> <span class="comment">/* width: 300px;</span></span><br><span class="line"><span class="comment"> height: 300px; */</span></span><br><span class="line"> <span class="attribute">text-align</span>: center;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="flex"><a href="#flex" class="headerlink" title="flex"></a>flex</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.out</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#000</span>;</span><br><span class="line"> <span class="attribute">display</span>: flex;</span><br><span class="line"> <span class="attribute">justify-content</span>: center;</span><br><span class="line"> <span class="attribute">align-items</span>: center;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.inner</span> {</span><br><span class="line"> <span class="attribute">background-color</span>: blueviolet;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="absolute-transform"><a href="#absolute-transform" class="headerlink" title="absolute + transform"></a>absolute + transform</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.out</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#000</span>;</span><br><span class="line"> <span class="attribute">position</span>: relative;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.inner</span> {</span><br><span class="line"> <span class="attribute">background-color</span>: blueviolet;</span><br><span class="line"> <span class="attribute">position</span>: absolute;</span><br><span class="line"> <span class="attribute">top</span>: <span class="number">50%</span>;</span><br><span class="line"> <span class="attribute">left</span>: <span class="number">50%</span>;</span><br><span class="line"> <span class="attribute">transform</span>: <span class="built_in">translate</span>(-<span class="number">50%</span>, -<span class="number">50%</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="grid"><a href="#grid" class="headerlink" title="grid"></a>grid</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.out</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#000</span>;</span><br><span class="line"> <span class="attribute">display</span>: grid;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.inner</span> {</span><br><span class="line"> <span class="attribute">background-color</span>: blueviolet;</span><br><span class="line"> <span class="attribute">align-self</span>: center;</span><br><span class="line"> justify-self: center;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="table-cell"><a href="#table-cell" class="headerlink" title="table-cell"></a>table-cell</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.out</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#000</span>;</span><br><span class="line"> <span class="attribute">display</span>: table-cell;</span><br><span class="line"> <span class="attribute">text-align</span>: center;</span><br><span class="line"> <span class="attribute">vertical-align</span>: middle;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.inner</span> {</span><br><span class="line"> <span class="attribute">background-color</span>: blueviolet;</span><br><span class="line"> <span class="attribute">display</span>: inline-block;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><p><em>好了,基本上就这些了;还有些不怎么用到的就没去整理了。</em></p><blockquote><ul><li><em>PC 端:考虑兼容性的话推荐使用 absolute+负 margin 和</em><em>table-cell; 否则直接 flex。</em></li><li><em>移动端:首推</em><em>flex。</em></li></ul></blockquote>]]></content>
<summary type="html"><blockquote>
<p><em>这是一个很常见的样式布局,网上也有很多的实现方式,本文主要是针对一些比较常用到的方法做一下总结,记录一下。</em></p>
</blockquote>
<p>现有实现方式大致的思路归纳为以下几种:</p>
<ul>
<li>固定宽高居中<</summary>
<category term="CSS" scheme="http://imagineblog.host/categories/CSS/"/>
<category term="CSS" scheme="http://imagineblog.host/tags/CSS/"/>
</entry>
<entry>
<title>js if/else 语句优化策略</title>
<link href="http://imagineblog.host/sp8d6i/"/>
<id>http://imagineblog.host/sp8d6i/</id>
<published>2021-07-20T12:18:01.000Z</published>
<updated>2022-08-31T08:04:19.377Z</updated>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><ul><li>在项目当中,都会遇到需要做大量分支判断的情况,最常用到的就是用 if/else;但是用起来并不是很美观;所以当遇到大量分支判断嵌套在一起时,就会显得很难阅读。就要对应地做出一些优化。</li></ul><h2 id="简单逻辑判断"><a href="#简单逻辑判断" class="headerlink" title="简单逻辑判断"></a>简单逻辑判断</h2><h3 id="提前-return"><a href="#提前-return" class="headerlink" title="提前 return"></a>提前 return</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">if</span> (a) {</span><br><span class="line"> a = <span class="number">2</span>;</span><br><span class="line">} <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">return</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">if</span> (!a) {</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line">a = <span class="number">2</span>;</span><br></pre></td></tr></table></figure><h3 id=""><a href="#" class="headerlink" title="||"></a>||</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">if</span> (a) {</span><br><span class="line"> a = <span class="number">1</span>;</span><br><span class="line">} <span class="keyword">else</span> {</span><br><span class="line"> a = <span class="number">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">a = a || <span class="number">0</span>;</span><br></pre></td></tr></table></figure><h3 id="三元表达式"><a href="#三元表达式" class="headerlink" title="三元表达式"></a>三元表达式</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a = <span class="number">1</span>,</span><br><span class="line"> b = <span class="number">2</span>,</span><br><span class="line"> c = <span class="number">3</span>,</span><br><span class="line"> d = <span class="number">4</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (a === b) {</span><br><span class="line"> a = d;</span><br><span class="line">} <span class="keyword">else</span> {</span><br><span class="line"> a = c;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 修改为</span></span><br><span class="line">a = a === b ? d : c;</span><br></pre></td></tr></table></figure><h3 id="按位异或运算符"><a href="#按位异或运算符" class="headerlink" title="按位异或运算符^"></a>按位异或运算符^</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a =<span class="number">1</span>,b=<span class="number">2</span>,c=<span class="number">1</span>,</span><br><span class="line"><span class="keyword">if</span>(a === c){</span><br><span class="line"> c = b</span><br><span class="line">}<span class="keyword">else</span> <span class="keyword">if</span>(b === c){</span><br><span class="line"> c = a</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//写成</span></span><br><span class="line">a = a^b^c</span><br></pre></td></tr></table></figure><h2 id="复杂逻辑判断"><a href="#复杂逻辑判断" class="headerlink" title="复杂逻辑判断"></a>复杂逻辑判断</h2><h3 id="if-逻辑优化"><a href="#if-逻辑优化" class="headerlink" title="if 逻辑优化"></a>if 逻辑优化</h3><p>人们考虑的东西到时候,都会把最可能发生的情况先做好准备。优化 if 逻辑的时候也可以这样想:把最可能出现的条件放在前面,把最不可能出现的条件放在后面,这样程序执行时总会按照写的逻辑的先后顺序逐一检测所有的条件,知道发现匹配的条件才会停止继续检测。</p><ul><li>if 的优化目标:最小化找到分支之前所判断条件体的数量。</li><li>if 优化的方法:将最常见的条件放在首位。</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">if</span>(a < <span class="number">10</span>){</span><br><span class="line"> ...</span><br><span class="line">}<span class="keyword">else</span> <span class="keyword">if</span>(a > <span class="number">10</span> && a < <span class="number">100</span>){</span><br><span class="line"> ...</span><br><span class="line">}<span class="keyword">else</span>{</span><br><span class="line"> ...</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="switch-case"><a href="#switch-case" class="headerlink" title="switch/case"></a>switch/case</h3><p>switch 在性能上和 if/else 区别不是很大,在大量分支判断时会比 if/else 看上去整洁。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">formatData</span>(<span class="params">time, format</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> t = <span class="keyword">new</span> <span class="built_in">Date</span>(time);</span><br><span class="line"> <span class="keyword">var</span> tf = <span class="function"><span class="keyword">function</span> (<span class="params">i</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> (i < <span class="number">10</span> ? <span class="string">"0"</span> : <span class="string">""</span>) + i;</span><br><span class="line"> };</span><br><span class="line"> <span class="keyword">return</span> format.replace(<span class="regexp">/yyyy|MM|dd|HH|mm|ss/g</span>, <span class="function"><span class="keyword">function</span> (<span class="params">a</span>) </span>{</span><br><span class="line"> <span class="keyword">switch</span> (a) {</span><br><span class="line"> <span class="keyword">case</span> <span class="string">"yyyy"</span>:</span><br><span class="line"> <span class="keyword">return</span> tf(t.getFullYear());</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">"MM"</span>:</span><br><span class="line"> <span class="keyword">return</span> tf(t.getMonth() + <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">"mm"</span>:</span><br><span class="line"> <span class="keyword">return</span> tf(t.getMinutes());</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">"dd"</span>:</span><br><span class="line"> <span class="keyword">return</span> tf(t.getDate());</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">"HH"</span>:</span><br><span class="line"> <span class="keyword">return</span> tf(t.getHours());</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">"ss"</span>:</span><br><span class="line"> <span class="keyword">return</span> tf(t.getSeconds());</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><br></pre></td></tr></table></figure><h3 id="利用-Object-重构"><a href="#利用-Object-重构" class="headerlink" title="利用 Object 重构"></a>利用 Object 重构</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">if</span> (type === <span class="string">"type_1"</span>) {</span><br><span class="line"> a = <span class="number">10</span>;</span><br><span class="line">} <span class="keyword">else</span> <span class="keyword">if</span> (type === <span class="string">"type_2"</span>) {</span><br><span class="line"> a = <span class="number">20</span>;</span><br><span class="line">} <span class="keyword">else</span> <span class="keyword">if</span> (type === <span class="string">"type_3"</span>) {</span><br><span class="line"> a = <span class="number">30</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">const</span> obj = {</span><br><span class="line"> type_1: <span class="number">10</span>,</span><br><span class="line"> type_2: <span class="number">20</span>,</span><br><span class="line"> type_3: <span class="number">30</span>,</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(obj[type]);</span><br></pre></td></tr></table></figure><h3 id="利用-Map"><a href="#利用-Map" class="headerlink" title="利用 Map"></a>利用 Map</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">if</span> (type === <span class="string">"type_1"</span>) {</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">type1</span>(<span class="params"></span>) </span>{</span><br><span class="line"> a = <span class="number">10</span>;</span><br><span class="line"> }</span><br><span class="line">} <span class="keyword">else</span> <span class="keyword">if</span> (type === <span class="string">"type_2"</span>) {</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">type2</span>(<span class="params"></span>) </span>{</span><br><span class="line"> a = <span class="number">20</span>;</span><br><span class="line"> }</span><br><span class="line">} <span class="keyword">else</span> <span class="keyword">if</span> (type === <span class="string">"type_3"</span>) {</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">type3</span>(<span class="params"></span>) </span>{</span><br><span class="line"> a = <span class="number">30</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> action = <span class="keyword">new</span> <span class="built_in">Map</span>([</span><br><span class="line"> [</span><br><span class="line"> <span class="string">"type_1"</span>,</span><br><span class="line"> () => {</span><br><span class="line"> a = <span class="number">10</span>;</span><br><span class="line"> },</span><br><span class="line"> ],</span><br><span class="line"> [</span><br><span class="line"> <span class="string">"type_2"</span>,</span><br><span class="line"> () => {</span><br><span class="line"> a = <span class="number">20</span>;</span><br><span class="line"> },</span><br><span class="line"> ],</span><br><span class="line"> [</span><br><span class="line"> <span class="string">"type_3"</span>,</span><br><span class="line"> () => {</span><br><span class="line"> a = <span class="number">30</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> data = action.get(type);</span><br><span class="line"><span class="built_in">console</span>.log(data());</span><br></pre></td></tr></table></figure><p>相关文章:<a href="https://blog.csdn.net/qq_40259641/article/details/83866457?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242">JavaScript 复杂判断(if else / switch)的更优雅写法 优化冗余</a></p>]]></content>
<summary type="html"><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><ul>
<li>在项目当中,都会遇到需要做大量分支判断的情况,最常用到的就是用 if/else;但是用起来并不是很美观;所以当遇到大量分支判断嵌</summary>
<category term="javascript" scheme="http://imagineblog.host/categories/javascript/"/>
<category term="javascript" scheme="http://imagineblog.host/tags/javascript/"/>
</entry>
<entry>
<title>数组对象求和</title>
<link href="http://imagineblog.host/pt9g3x/"/>
<id>http://imagineblog.host/pt9g3x/</id>
<published>2021-06-20T07:51:55.000Z</published>
<updated>2022-08-31T08:04:19.377Z</updated>
<content type="html"><![CDATA[<blockquote><p>数组对象求和问题,在项目中有时会遇到列表求和的情况,这里记录一下。</p></blockquote><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="keyword">let</span> list = [</span><br><span class="line"> { <span class="attr">id</span>: <span class="number">1</span>, <span class="attr">value1</span>: <span class="number">5</span>, <span class="attr">value2</span>: <span class="number">10</span>, <span class="attr">value3</span>: <span class="number">20</span> },</span><br><span class="line"> { <span class="attr">id</span>: <span class="number">2</span>, <span class="attr">value1</span>: <span class="number">15</span>, <span class="attr">value2</span>: <span class="number">10</span>, <span class="attr">value3</span>: <span class="number">50</span> },</span><br><span class="line"> { <span class="attr">id</span>: <span class="number">3</span>, <span class="attr">value1</span>: <span class="number">40</span>, <span class="attr">value2</span>: <span class="number">20</span>, <span class="attr">value3</span>: <span class="number">20</span> },</span><br><span class="line">];</span><br></pre></td></tr></table></figure><h2 id="利用-reduce-和-Object-keys"><a href="#利用-reduce-和-Object-keys" class="headerlink" title="利用 reduce()和 Object.keys()"></a>利用 reduce()和 Object.keys()</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">mergeArr</span>(<span class="params">arr, data</span>) </span>{</span><br><span class="line"> <span class="keyword">let</span> result = arr.reduce(<span class="function">(<span class="params">acc, cur</span>) =></span> {</span><br><span class="line"> <span class="built_in">Object</span>.keys(acc).forEach(<span class="function">(<span class="params">item</span>) =></span> (acc[item] += cur[item]));</span><br><span class="line"> <span class="keyword">return</span> acc;</span><br><span class="line"> }, data);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> data = { <span class="attr">value1</span>: <span class="number">0</span>, <span class="attr">value2</span>: <span class="number">0</span>, <span class="attr">value3</span>: <span class="number">0</span> };</span><br><span class="line">mergeArr(list, data); <span class="comment">// {value1: 60, value2: 40, value3: 90}</span></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><blockquote>
<p>数组对象求和问题,在项目中有时会遇到列表求和的情况,这里记录一下。</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre></summary>
<category term="javascript" scheme="http://imagineblog.host/categories/javascript/"/>
<category term="javascript" scheme="http://imagineblog.host/tags/javascript/"/>
</entry>
<entry>
<title>js对象排序</title>
<link href="http://imagineblog.host/sortObj/"/>
<id>http://imagineblog.host/sortObj/</id>
<published>2021-06-15T02:15:24.000Z</published>
<updated>2022-08-31T08:04:19.377Z</updated>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><blockquote><p>记录一次在项目开发中遇到的情况。后台返回一个排好序的对象作为折线图的数据,按要求根据日期顺序进行展示。首先要清楚一点是js对象是无序的,即使后台排好了序,还是会错乱,所以需要在前端渲染前做一遍排序操作。</p></blockquote><hr><h2 id="排序"><a href="#排序" class="headerlink" title="排序"></a>排序</h2><ul><li>js对象是没办法直接进行排序的,可以针对对象的某个属性或键值来排序,最后将对应的value取出来。</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><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="keyword">let</span> obj = {</span><br><span class="line"><span class="number">20210601</span>:{<span class="attr">date</span>:<span class="number">20210601</span>,<span class="attr">name</span>:<span class="string">'a'</span>,<span class="attr">age</span>:<span class="number">22</span>},</span><br><span class="line"><span class="number">20210604</span>:{<span class="attr">date</span>:<span class="number">20210604</span>,<span class="attr">name</span>:<span class="string">'b'</span>,<span class="attr">age</span>:<span class="number">20</span>},</span><br><span class="line"><span class="number">20210602</span>:{<span class="attr">date</span>:<span class="number">20210602</span>,<span class="attr">name</span>:<span class="string">'c'</span>,<span class="attr">age</span>:<span class="number">18</span>},</span><br><span class="line"><span class="number">20210603</span>:{<span class="attr">date</span>:<span class="number">20210603</span>,<span class="attr">name</span>:<span class="string">'d'</span>,<span class="attr">age</span>:<span class="number">26</span>}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> arr = []</span><br><span class="line"></span><br><span class="line"><span class="comment">// 将key值排序</span></span><br><span class="line"><span class="keyword">let</span> sortKeys = <span class="built_in">Object</span>.keys(obj).sort(<span class="function">(<span class="params">a,b</span>)=></span>{</span><br><span class="line"><span class="keyword">return</span> obj[a] - obj[b]</span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(sortKeys) <span class="comment">// ["20210601", "20210602", "20210603", "20210604"]</span></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">var</span> index <span class="keyword">in</span> sortKeys) {</span><br><span class="line"> arr.push(obj[sortKeys[index]])</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(arr) </span><br></pre></td></tr></table></figure><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/1630034850000.png"></p><hr>]]></content>
<summary type="html"><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><blockquote>
<p>记录一次在项目开发中遇到的情况。后台返回一个排好序的对象作为折线图的数据,按要求根据日期顺序进行展示。首先要清楚一</summary>
<category term="javascript" scheme="http://imagineblog.host/categories/javascript/"/>
<category term="javascript" scheme="http://imagineblog.host/tags/javascript/"/>
</entry>
<entry>
<title>JavaScript 数组去重</title>
<link href="http://imagineblog.host/rs7zqd/"/>
<id>http://imagineblog.host/rs7zqd/</id>
<published>2021-06-10T03:18:01.000Z</published>
<updated>2022-08-31T08:04:19.377Z</updated>
<content type="html"><![CDATA[<blockquote><p>主要记录一下前端数组去重的几种方法,也方便后面查看。</p></blockquote><h2 id="ES6-new-Set-…-Array-from"><a href="#ES6-new-Set-…-Array-from" class="headerlink" title="ES6 new Set() + … || Array.from"></a>ES6 new Set() + … || Array.from</h2><p>ES6 提供了新的数据结构 Set。类似于数组,但是成员的值都是唯一的,没有重复的值。<br>Set 本身是一个构造函数,可以接受一个具有 iterable 接口数据结构作为参数(如数组,字符串),用来初始化。</p><div class="note info modern"><p>不考虑兼容性,这种去重的方法代码最少。这种方法还无法去掉“{}”空对象</p></div><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="keyword">const</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="literal">null</span>, <span class="string">"a"</span>, <span class="string">"b"</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="literal">null</span>, <span class="string">"a"</span>];</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> newArr = [...new <span class="built_in">Set</span>(arr)]; <span class="comment">// [1, 2, 3, null, "a", "b"]</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> newArr1 = <span class="built_in">Array</span>.from(<span class="keyword">new</span> <span class="built_in">Set</span>(arr)); <span class="comment">// [1, 2, 3, null, "a", "b"]</span></span><br></pre></td></tr></table></figure><h2 id="ES6-new-Map"><a href="#ES6-new-Map" class="headerlink" title="ES6 new Map()"></a>ES6 new Map()</h2><p>ES6 提供了新的数据结构 Map 。类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。</p><ul><li>set 方法设置键名 key 对应的键值为 value,然后返回整个 Map 结构。如果 key 已经有值,则键值会被更新,否则就新生成该键。</li><li>get 方法读取 key 对应的键值,如果找不到 key,返回 undefined。</li><li>has 方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="literal">null</span>, <span class="string">"a"</span>, <span class="string">"b"</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="literal">null</span>, <span class="string">"a"</span>];</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> map = <span class="keyword">new</span> <span class="built_in">Map</span>();</span><br><span class="line"><span class="keyword">let</span> newArr = [];</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>, len = arr.length; i < len; i++) {</span><br><span class="line"> <span class="keyword">if</span> (!map.has(arr[i])) {</span><br><span class="line"> map.set(arr[i], <span class="literal">true</span>);</span><br><span class="line"> newArr.push(arr[i]);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(newArr); <span class="comment">// [1, 2, 3, null, "a", "b"]</span></span><br></pre></td></tr></table></figure><h2 id="Array-includes"><a href="#Array-includes" class="headerlink" title="Array.includes()"></a>Array.includes()</h2><p>includes()方法:用来判断一个数组是否包含一个指定的值,如果是返回 true,否则 false。</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> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="literal">null</span>, <span class="string">"a"</span>, <span class="string">"b"</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="literal">null</span>, <span class="string">"a"</span>];</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> newArr = [];</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>, len = arr.length; i < len; i++) {</span><br><span class="line"> <span class="keyword">if</span> (!newArr.includes(arr[i])) newArr.push(arr[i]);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// forEach</span></span><br><span class="line">arr.forEach(<span class="function">(<span class="params">item</span>) =></span> (!newArr.includes(item) ? newArr.push(item) : <span class="string">""</span>));</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(newArr); <span class="comment">// [1, 2, 3, null, "a", "b"]</span></span><br></pre></td></tr></table></figure><h2 id="Array-indexOf"><a href="#Array-indexOf" class="headerlink" title="Array.indexOf()"></a>Array.indexOf()</h2><p>indexOf()方法:返回数组中某个指定元素的位置。该方法遍历数组,查找有无对应元素并返回元素第一次出现的索引,若未找到指定元素则返回-1。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="literal">null</span>, <span class="string">"a"</span>, <span class="string">"b"</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="literal">null</span>, <span class="string">"a"</span>];</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> newArr = [];</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>, len = arr.length; i < len; i++) {</span><br><span class="line"> <span class="keyword">if</span> (newArr.indexOf(arr[i]) === -<span class="number">1</span>) newArr.push(arr[i]);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//等同于使用forEach遍历</span></span><br><span class="line">arr.forEach(<span class="function">(<span class="params">item</span>) =></span> (newArr.indexOf(item) === -<span class="number">1</span> ? newArr.push(item) : <span class="string">""</span>));</span><br></pre></td></tr></table></figure><h2 id="Array-reduce-Array-includes"><a href="#Array-reduce-Array-includes" class="headerlink" title="Array.reduce + Array.includes"></a>Array.reduce + Array.includes</h2><p>reduce()方法:接收一个函数作为累加器,数组中的每个值从左到右开始计算,最终计算为一个值。</p><blockquote><p>语法:arr.reduce(function(total, currValue, currIndex, arr), initValue) > reduce()对于空数组是不会执行回调函数的。</p></blockquote><ul><li>total:必需。初始值, 或者计算结束后的返回值</li><li>currValue:必需。当前元素</li><li>currIndex:可选。当前元素的索引</li><li>arr :可选。当前数组对象。</li><li>initValue:可选。累加器初始值</li></ul><p>一个空数组调用 reduce()方法且沒有提供初始值,会报错。<br>一个空数组调用 reduce()方法且提供了初始值,将直接返回该初始值,不會调用 callback 函数。<br>非空数组调用 reduce()提供初始值,则 total 将会等于初始值,且 currValue 从第一个元素开始;若沒有提供初始值,则 total 会等于的第一个元素值,且 currValue 将会从第二个元素开始。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="literal">null</span>, <span class="string">"a"</span>, <span class="string">"b"</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="literal">null</span>, <span class="string">"a"</span>];</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> newArr = arr.reduce(<span class="function">(<span class="params">acc, cur</span>) =></span> {</span><br><span class="line"> <span class="keyword">return</span> acc.includes(cur) ? acc : acc.concat(cur); <span class="comment">// 1. 拼接方法</span></span><br><span class="line"> <span class="comment">// return acc.includes(cur) ? acc : [...acc, cur]; // 2. 扩展运算</span></span><br><span class="line">}, []);</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(newArr); <span class="comment">// [1, 2, 3, null, "a", "b"]</span></span><br></pre></td></tr></table></figure><h2 id="Array-filter-Array-indexOf"><a href="#Array-filter-Array-indexOf" class="headerlink" title="Array.filter + Array.indexOf"></a>Array.filter + Array.indexOf</h2><p>filter()方法:创建一个新数组,新数组中的元素是指定数组中符合某种条件的所有元素。如果没有符合条件的元素则返回空数组。</p><blockquote><p>语法:array.filter(function(item,index,arr))</p></blockquote><p>filter()不会对空数组进行检测。<br>filter()不会改变原始数组。</p><ul><li>原理:返回 item 第一次出现的位置等于当前的 index 的元素</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="literal">null</span>, <span class="string">"a"</span>, <span class="string">"b"</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="literal">null</span>, <span class="string">"a"</span>];</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> newArr = arr.filter(<span class="function">(<span class="params">item, index</span>) =></span> arr.indexOf(item) === index);</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(newArr); <span class="comment">// [1, 2, 3, null, "a", "b"]</span></span><br></pre></td></tr></table></figure><h2 id="Array-filter-Object-hasOwnProperty"><a href="#Array-filter-Object-hasOwnProperty" class="headerlink" title="Array.filter + Object.hasOwnProperty"></a>Array.filter + Object.hasOwnProperty</h2><p>hasOwnProperty()方法:返回一个布尔值,表示对象自身属性中是否具有指定的属性</p><ul><li>原理:利用对象的键名不可重复的特点。</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="literal">null</span>, <span class="string">"a"</span>, <span class="string">"b"</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="literal">null</span>, <span class="string">"a"</span>];</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> obj = {};</span><br><span class="line">arr.filter(<span class="function">(<span class="params">item</span>) =></span></span><br><span class="line"> obj.hasOwnProperty(<span class="keyword">typeof</span> item + item)</span><br><span class="line"> ? <span class="literal">false</span></span><br><span class="line"> : (obj[<span class="keyword">typeof</span> item + item] = <span class="literal">true</span>)</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">// [1, 2, 3, null, "a", "b"]</span></span><br></pre></td></tr></table></figure><h2 id="利用对象的-key-唯一"><a href="#利用对象的-key-唯一" class="headerlink" title="利用对象的 key 唯一"></a>利用对象的 key 唯一</h2><p>对象的 key 不可重复,否则后者将覆盖前者。利用该特性,实现数组去重,遍历数组,将数组的每一项做为对象的 key 值。</p><p>若当前元素重复,则与数组最后一位元素交换位置,i–再次进行判断即可,同时 length–,操作数组的长度实现删除数组的最后一个元素,这样便不会影响到数组中其他元素。</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="literal">null</span>, <span class="string">"a"</span>, <span class="string">"b"</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="literal">null</span>, <span class="string">"a"</span>];</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> obj = {};</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i < arr.length; i++) {</span><br><span class="line"> <span class="keyword">let</span> item = arr[i];</span><br><span class="line"> <span class="keyword">if</span> (obj[item] !== <span class="literal">undefined</span>) {</span><br><span class="line"> arr[i] = arr[arr.length - <span class="number">1</span>];</span><br><span class="line"> arr.length--;</span><br><span class="line"> i--;</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> }</span><br><span class="line"> obj[item] = item;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(arr); <span class="comment">// [1, 2, 3, null, "a", "b"]</span></span><br></pre></td></tr></table></figure><h2 id="利用-sort"><a href="#利用-sort" class="headerlink" title="利用 sort()"></a>利用 sort()</h2><p>利用 sort()排序方法,然后根据排序后的结果进行遍历及相邻元素比对。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">unique</span>(<span class="params">arr</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (!<span class="built_in">Array</span>.isArray(arr)) {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"type error!"</span>);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> arr = arr.sort();</span><br><span class="line"> <span class="keyword">var</span> arrry = [arr[<span class="number">0</span>]];</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">1</span>; i < arr.length; i++) {</span><br><span class="line"> <span class="keyword">if</span> (arr[i] !== arr[i - <span class="number">1</span>]) {</span><br><span class="line"> arrry.push(arr[i]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> arrry;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> arr = [</span><br><span class="line"> <span class="number">1</span>,</span><br><span class="line"> <span class="number">1</span>,</span><br><span class="line"> <span class="string">"true"</span>,</span><br><span class="line"> <span class="string">"true"</span>,</span><br><span class="line"> <span class="literal">true</span>,</span><br><span class="line"> <span class="literal">true</span>,</span><br><span class="line"> <span class="number">20</span>,</span><br><span class="line"> <span class="number">20</span>,</span><br><span class="line"> <span class="literal">false</span>,</span><br><span class="line"> <span class="literal">false</span>,</span><br><span class="line"> <span class="literal">undefined</span>,</span><br><span class="line"> <span class="literal">undefined</span>,</span><br><span class="line"> <span class="literal">null</span>,</span><br><span class="line"> <span class="literal">null</span>,</span><br><span class="line"> <span class="literal">NaN</span>,</span><br><span class="line"> <span class="literal">NaN</span>,</span><br><span class="line"> <span class="string">"NaN"</span>,</span><br><span class="line"> <span class="number">0</span>,</span><br><span class="line"> <span class="number">0</span>,</span><br><span class="line"> <span class="string">"a"</span>,</span><br><span class="line"> <span class="string">"a"</span>,</span><br><span class="line"> {},</span><br><span class="line"> {},</span><br><span class="line">];</span><br><span class="line"><span class="built_in">console</span>.log(unique(arr));</span><br><span class="line"><span class="comment">// [0, 1, 20, "NaN", NaN, NaN, {…}, {…}, "a", false, null, true, "true", undefined] //NaN、{}没有去重</span></span><br></pre></td></tr></table></figure><h2 id="双层-for-循环,splice-去重(ES5)"><a href="#双层-for-循环,splice-去重(ES5)" class="headerlink" title="双层 for 循环,splice 去重(ES5)"></a>双层 for 循环,splice 去重(ES5)</h2><p>双层循环,外层循环元素,内层循环时比较值。值相同时,则删去这个值。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">unique</span>(<span class="params">arr</span>) </span>{</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < arr.length; i++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> j = i + <span class="number">1</span>; j < arr.length; j++) {</span><br><span class="line"> <span class="keyword">if</span> (arr[i] == arr[j]) {</span><br><span class="line"> <span class="comment">//第一个等同于第二个,splice方法删除第二个</span></span><br><span class="line"> arr.splice(j, <span class="number">1</span>);</span><br><span class="line"> j--;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> arr;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">var</span> arr = [</span><br><span class="line"> <span class="number">1</span>,</span><br><span class="line"> <span class="number">1</span>,</span><br><span class="line"> <span class="string">"true"</span>,</span><br><span class="line"> <span class="string">"true"</span>,</span><br><span class="line"> <span class="literal">true</span>,</span><br><span class="line"> <span class="literal">true</span>,</span><br><span class="line"> <span class="number">15</span>,</span><br><span class="line"> <span class="number">15</span>,</span><br><span class="line"> <span class="literal">false</span>,</span><br><span class="line"> <span class="literal">false</span>,</span><br><span class="line"> <span class="literal">undefined</span>,</span><br><span class="line"> <span class="literal">undefined</span>,</span><br><span class="line"> <span class="literal">null</span>,</span><br><span class="line"> <span class="literal">null</span>,</span><br><span class="line"> <span class="literal">NaN</span>,</span><br><span class="line"> <span class="literal">NaN</span>,</span><br><span class="line"> <span class="string">"NaN"</span>,</span><br><span class="line"> <span class="number">0</span>,</span><br><span class="line"> <span class="number">0</span>,</span><br><span class="line"> <span class="string">"a"</span>,</span><br><span class="line"> <span class="string">"a"</span>,</span><br><span class="line"> {},</span><br><span class="line"> {},</span><br><span class="line">];</span><br><span class="line"><span class="built_in">console</span>.log(unique(arr));</span><br><span class="line"><span class="comment">//[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}] //NaN和{}没有去重,两个null直接消失了</span></span><br></pre></td></tr></table></figure><h2 id="递归去重"><a href="#递归去重" class="headerlink" title="递归去重"></a>递归去重</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">unique</span>(<span class="params">arr</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> array = arr;</span><br><span class="line"> <span class="keyword">var</span> len = array.length;</span><br><span class="line"> array.sort(<span class="function"><span class="keyword">function</span> (<span class="params">a, b</span>) </span>{</span><br><span class="line"> <span class="comment">//排序后更加方便去重</span></span><br><span class="line"> <span class="keyword">return</span> a - b;</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">loop</span>(<span class="params">index</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (index >= <span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">if</span> (array[index] === array[index - <span class="number">1</span>]) {</span><br><span class="line"> array.splice(index, <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> loop(index - <span class="number">1</span>); <span class="comment">//递归loop,然后数组去重</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> loop(len - <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">return</span> array;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">var</span> arr = [</span><br><span class="line"> <span class="number">1</span>,</span><br><span class="line"> <span class="number">1</span>,</span><br><span class="line"> <span class="string">"true"</span>,</span><br><span class="line"> <span class="string">"true"</span>,</span><br><span class="line"> <span class="literal">true</span>,</span><br><span class="line"> <span class="literal">true</span>,</span><br><span class="line"> <span class="number">15</span>,</span><br><span class="line"> <span class="number">15</span>,</span><br><span class="line"> <span class="literal">false</span>,</span><br><span class="line"> <span class="literal">false</span>,</span><br><span class="line"> <span class="literal">undefined</span>,</span><br><span class="line"> <span class="literal">undefined</span>,</span><br><span class="line"> <span class="literal">null</span>,</span><br><span class="line"> <span class="literal">null</span>,</span><br><span class="line"> <span class="literal">NaN</span>,</span><br><span class="line"> <span class="literal">NaN</span>,</span><br><span class="line"> <span class="string">"NaN"</span>,</span><br><span class="line"> <span class="number">0</span>,</span><br><span class="line"> <span class="number">0</span>,</span><br><span class="line"> <span class="string">"a"</span>,</span><br><span class="line"> <span class="string">"a"</span>,</span><br><span class="line"> {},</span><br><span class="line"> {},</span><br><span class="line">];</span><br><span class="line"><span class="built_in">console</span>.log(unique(arr));</span><br><span class="line"><span class="comment">//[1, "a", "true", true, 15, false, 1, {…}, null, NaN, NaN, "NaN", 0, "a", {…}, undefined]</span></span><br></pre></td></tr></table></figure><h2 id="根据数组中对象的某个属性值进行去重"><a href="#根据数组中对象的某个属性值进行去重" class="headerlink" title="根据数组中对象的某个属性值进行去重"></a>根据数组中对象的某个属性值进行去重</h2><blockquote><p>Map + filter</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [{<span class="attr">name</span>:<span class="string">'张三'</span>,age:<span class="number">20</span>},{<span class="attr">name</span>:<span class="string">'张三'</span>,age:<span class="number">22</span>},{<span class="attr">name</span>:<span class="string">'李四'</span>,age:<span class="number">24</span>}]</span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">unique</span>(<span class="params">arr</span>) </span>{</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">return</span> arr.filter(<span class="function">(<span class="params">a</span>) =></span> !res.has(a.name) && res.set(a.name, <span class="number">1</span>))</span><br><span class="line"></span><br><span class="line">unique(arr) <span class="comment">// [{name:'张三',age:20},{name:'李四',age:24}]</span></span><br></pre></td></tr></table></figure><ul><li>更多实现方式:<a href="https://blog.csdn.net/JxufeCarol/article/details/117766099">js 数组对象根据对象中的指定属性去重</a></li></ul><hr>]]></content>
<summary type="html"><blockquote>
<p>主要记录一下前端数组去重的几种方法,也方便后面查看。</p>
</blockquote>
<h2 id="ES6-new-Set-…-Array-from"><a href="#ES6-new-Set-…-Array-from" class="he</summary>
<category term="javascript" scheme="http://imagineblog.host/categories/javascript/"/>
<category term="javascript" scheme="http://imagineblog.host/tags/javascript/"/>
</entry>
<entry>
<title>ES6-ES12 特性</title>
<link href="http://imagineblog.host/eya8ra/"/>
<id>http://imagineblog.host/eya8ra/</id>
<published>2021-05-31T07:29:03.000Z</published>
<updated>2022-08-31T08:04:19.377Z</updated>
<content type="html"><![CDATA[<p>本文集合了 ES6 至 ES11 常用到的特性,包括还在规划的 ES12。</p><h2 id="ES6(2015)"><a href="#ES6(2015)" class="headerlink" title="ES6(2015)"></a>ES6(2015)</h2><h3 id="类(class)"><a href="#类(class)" class="headerlink" title="类(class)"></a>类(class)</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">People</span> </span>{</span><br><span class="line"> <span class="function"><span class="title">constructor</span>(<span class="params">name</span>)</span> {</span><br><span class="line"> <span class="built_in">this</span>.name = <span class="string">"a"</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="title">console</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="built_in">this</span>.name);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="keyword">const</span> people = <span class="keyword">new</span> People(<span class="string">"a"</span>);</span><br><span class="line">people.console(); <span class="comment">// a</span></span><br></pre></td></tr></table></figure><h3 id="模块化(ES-Module)"><a href="#模块化(ES-Module)" class="headerlink" title="模块化(ES Module)"></a>模块化(ES Module)</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// A.js 导出一个方法</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> addNum = <span class="function">(<span class="params">a, b</span>) =></span> a + b;</span><br><span class="line"></span><br><span class="line"><span class="comment">// B.js 导入并使用</span></span><br><span class="line"><span class="keyword">import</span> { addNum } <span class="keyword">from</span> <span class="string">"./A.js"</span>;</span><br><span class="line">addNum(<span class="number">1</span>, <span class="number">2</span>); <span class="comment">// 3</span></span><br></pre></td></tr></table></figure><h3 id="箭头函数"><a href="#箭头函数" class="headerlink" title="箭头函数"></a>箭头函数</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> addNum = <span class="function">(<span class="params">a, b</span>) =></span> a + b;</span><br><span class="line">addNum(<span class="number">1</span>, <span class="number">2</span>); <span class="comment">// 3</span></span><br></pre></td></tr></table></figure><h3 id="函数参数默认值"><a href="#函数参数默认值" class="headerlink" title="函数参数默认值"></a>函数参数默认值</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">func</span>(<span class="params">val = <span class="number">10</span>,list= []</span>)</span>{...}</span><br></pre></td></tr></table></figure><h3 id="字符串模板"><a href="#字符串模板" class="headerlink" title="字符串模板"></a>字符串模板</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> name = <span class="string">"张三"</span>;</span><br><span class="line"><span class="keyword">const</span> text = <span class="string">`this is <span class="subst">${name}</span>`</span>;</span><br></pre></td></tr></table></figure><h3 id="解构赋值"><a href="#解构赋值" class="headerlink" title="解构赋值"></a>解构赋值</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> obj = { <span class="attr">name</span>: <span class="string">"张三"</span>, <span class="attr">age</span>: <span class="number">22</span> };</span><br><span class="line"><span class="keyword">const</span> { name, age } = obj; <span class="comment">// "张三" 22</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> a = <span class="number">1</span>,</span><br><span class="line"> b = <span class="number">2</span>;</span><br><span class="line">[a, b] = [b, a]; <span class="comment">// a 2 b 1</span></span><br></pre></td></tr></table></figure><h3 id="展开运算符"><a href="#展开运算符" class="headerlink" title="展开运算符"></a>展开运算符</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> data = [...<span class="string">"hello"</span>]; <span class="comment">// ['h','e','l','l','o']</span></span><br></pre></td></tr></table></figure><h3 id="对象属性简写"><a href="#对象属性简写" class="headerlink" title="对象属性简写"></a>对象属性简写</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> name = <span class="string">"张三"</span>,</span><br><span class="line"> age = <span class="number">22</span>;</span><br><span class="line"><span class="keyword">const</span> obj = { name, age }; <span class="comment">// 张三 22 等同于const obj = {name:name,age:age}</span></span><br></pre></td></tr></table></figure><h3 id="Promise"><a href="#Promise" class="headerlink" title="Promise"></a>Promise</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Promise</span>.resolve().then(<span class="function">() =></span> {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="number">2</span>);</span><br><span class="line">});</span><br><span class="line"><span class="built_in">console</span>.log(<span class="number">1</span>);</span><br><span class="line"><span class="comment">// 先打印 1 ,再打印 2</span></span><br></pre></td></tr></table></figure><h3 id="let-const"><a href="#let-const" class="headerlink" title="let/const"></a>let/const</h3><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"><span class="keyword">let</span> a = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">const</span> b = {};</span><br></pre></td></tr></table></figure><hr><h2 id="ES7(2016)"><a href="#ES7(2016)" class="headerlink" title="ES7(2016)"></a>ES7(2016)</h2><h3 id="Array-prototype-includes"><a href="#Array-prototype-includes" class="headerlink" title="Array.prototype.includes()"></a>Array.prototype.includes()</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>].includes(<span class="number">2</span>); <span class="comment">// true</span></span><br></pre></td></tr></table></figure><h3 id="指数操作符"><a href="#指数操作符" class="headerlink" title="指数操作符"></a>指数操作符</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">2</span> ** <span class="number">10</span>; <span class="comment">// 1024</span></span><br></pre></td></tr></table></figure><hr><h2 id="ES8-(2017)"><a href="#ES8-(2017)" class="headerlink" title="ES8 (2017)"></a>ES8 (2017)</h2><h3 id="async-await"><a href="#async-await" class="headerlink" title="async/await"></a>async/await</h3><blockquote><p>异步解决方案</p></blockquote><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">Async</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> res = <span class="keyword">await</span> <span class="built_in">setTimeout</span>(<span class="function">() =></span> {});</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="Object-values"><a href="#Object-values" class="headerlink" title="Object.values()"></a>Object.values()</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Object</span>.values({ <span class="attr">a</span>: <span class="number">1</span>, <span class="attr">b</span>: <span class="number">2</span>, <span class="attr">c</span>: <span class="number">3</span> }); <span class="comment">// [1,2,3]</span></span><br></pre></td></tr></table></figure><h3 id="Object-entries"><a href="#Object-entries" class="headerlink" title="Object.entries()"></a>Object.entries()</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Object</span>.entries({ <span class="attr">a</span>: <span class="number">1</span>, <span class="attr">b</span>: <span class="number">2</span>, <span class="attr">c</span>: <span class="number">3</span> }); <span class="comment">// [["a", 1], ["b", 2], ["c", 3]]</span></span><br></pre></td></tr></table></figure><h3 id="String-padding"><a href="#String-padding" class="headerlink" title="String padding"></a>String padding</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// padStart</span></span><br><span class="line"><span class="string">"hello"</span>.padStart(<span class="number">10</span>); <span class="comment">// " hello"</span></span><br><span class="line"><span class="comment">// padEnd</span></span><br><span class="line"><span class="string">"hello"</span>.padEnd(<span class="number">10</span>); <span class="comment">//"hello "</span></span><br></pre></td></tr></table></figure><h3 id="Object-getOwnPropertyDescriptors"><a href="#Object-getOwnPropertyDescriptors" class="headerlink" title="Object.getOwnPropertyDescriptors()"></a>Object.getOwnPropertyDescriptors()</h3><blockquote><p>获取一个对象的所有自身属性的描述符,如果没有任何自身属性,则返回空对象。</p></blockquote><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> obj = { <span class="attr">name</span>: <span class="string">"张三"</span>, <span class="attr">age</span>: <span class="number">22</span>, <span class="attr">todo</span>: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{} };</span><br><span class="line"><span class="keyword">const</span> obj1 = {};</span><br><span class="line"><span class="built_in">Object</span>.getOwnPropertyDescriptors(obj);</span><br><span class="line"><span class="comment">//age: {value: 22, writable: true, enumerable: true, configurable: true}</span></span><br><span class="line"><span class="comment">//name: {value: "张三", writable: true, enumerable: true, configurable: true}</span></span><br><span class="line"><span class="comment">//todo: {writable: true, enumerable: true, configurable: true, value: ƒ}</span></span><br><span class="line"><span class="comment">//__proto__: Object</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">Object</span>.getOwnPropertyDescriptors(obj1); <span class="comment">// {}</span></span><br></pre></td></tr></table></figure><h3 id="SharedArrayBuffer-对象"><a href="#SharedArrayBuffer-对象" class="headerlink" title="SharedArrayBuffer 对象"></a>SharedArrayBuffer 对象</h3><blockquote><p>SharedArrayBuffer 对象用来表示一个通用的,固定长度的原始二进制数据缓冲区</p></blockquote><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">{*}</span> </span>length 所创建的数组缓冲区的大小,以字节(byte)为单位。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@returns <span class="type">{SharedArrayBuffer}</span> </span>一个大小指定的新 SharedArrayBuffer 对象。其内容被初始化为 0。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">new</span> SharedArrayBuffer(<span class="number">10</span>);</span><br></pre></td></tr></table></figure><hr><h2 id="ES9(2018)"><a href="#ES9(2018)" class="headerlink" title="ES9(2018)"></a>ES9(2018)</h2><h3 id="异步迭代"><a href="#异步迭代" class="headerlink" title="异步迭代"></a>异步迭代</h3><blockquote><p>await 可以和 for…of 循环一起使用,以串行的方式运行异步操作</p></blockquote><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="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">proess</span>(<span class="params">array</span>) </span>{</span><br><span class="line"> <span class="keyword">for</span> <span class="keyword">await</span> (<span class="keyword">let</span> i <span class="keyword">of</span> array) {</span><br><span class="line"> <span class="comment">//...</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="Promise-finally"><a href="#Promise-finally" class="headerlink" title="Promise.finally()"></a>Promise.finally()</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Promise</span>.resolve()</span><br><span class="line"> .then()</span><br><span class="line"> .catch(<span class="function">(<span class="params">e</span>) =></span> e)</span><br><span class="line"> .finally();</span><br></pre></td></tr></table></figure><h3 id="正则表达式命名捕获组"><a href="#正则表达式命名捕获组" class="headerlink" title="正则表达式命名捕获组"></a>正则表达式命名捕获组</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> reg = <span class="regexp">/(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/</span>;</span><br><span class="line"><span class="keyword">const</span> match = reg.exec(<span class="string">"2021-05-31"</span>);</span><br></pre></td></tr></table></figure><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/exec.png"></p><h3 id="正则表达式-dotAll-模式"><a href="#正则表达式-dotAll-模式" class="headerlink" title="正则表达式 dotAll 模式"></a>正则表达式 dotAll 模式</h3><blockquote><p>正则表达式中点.匹配除回车外的任何单字符,标记 s 改变这种行为,允许行终止符的出现</p></blockquote><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/hello.world/.test(<span class="string">"hello\nworld"</span>); <span class="comment">// false</span></span><br></pre></td></tr></table></figure><hr><h2 id="ES10(2019)"><a href="#ES10(2019)" class="headerlink" title="ES10(2019)"></a>ES10(2019)</h2><h3 id="Array-flat-Array-flatMap"><a href="#Array-flat-Array-flatMap" class="headerlink" title="Array.flat()/Array.flatMap()"></a>Array.flat()/Array.flatMap()</h3><ul><li>flat()</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[<span class="number">1</span>, <span class="number">2</span>, [<span class="number">3</span>, <span class="number">4</span>]].flat(<span class="literal">Infinity</span>); <span class="comment">// [1, 2, 3, 4]</span></span><br></pre></td></tr></table></figure><ul><li>flatMap()</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>].flatMap(<span class="function">(<span class="params">a</span>) =></span> [a ** <span class="number">2</span>]); <span class="comment">// [1, 4, 9, 16]</span></span><br></pre></td></tr></table></figure><h3 id="String-trimStart-String-trimEnd"><a href="#String-trimStart-String-trimEnd" class="headerlink" title="String.trimStart()/String.trimEnd()"></a>String.trimStart()/String.trimEnd()</h3><blockquote><p>去除字符串首尾空白字符</p></blockquote><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="comment">// trimStart()</span></span><br><span class="line"><span class="string">" hello"</span>.trimStart(); <span class="comment">// "hello"</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//trimEnd()</span></span><br><span class="line"><span class="string">"hello "</span>.trimEnd(); <span class="comment">// "hello"</span></span><br></pre></td></tr></table></figure><h3 id="String-prototype-matchAll"><a href="#String-prototype-matchAll" class="headerlink" title="String.prototype.matchAll"></a>String.prototype.matchAll</h3><blockquote><p>matchAll()为所有匹配的匹配对象返回一个迭代器</p></blockquote><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"><span class="keyword">const</span> raw_arr = <span class="string">"test1 test2 test3"</span>.matchAll(<span class="regexp">/t(e)(st(\d?))/g</span>);</span><br><span class="line"><span class="keyword">const</span> arr = [...raw_arr];</span><br></pre></td></tr></table></figure><h3 id="Symbol-prototype-description"><a href="#Symbol-prototype-description" class="headerlink" title="Symbol.prototype.description"></a>Symbol.prototype.description</h3><blockquote><p>只读属性,返回 Symbol 对象的可选描述的字符串。</p></blockquote><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Symbol</span>(<span class="string">"hello"</span>).description; <span class="comment">// "hello"</span></span><br></pre></td></tr></table></figure><h3 id="Object-fromEntries"><a href="#Object-fromEntries" class="headerlink" title="Object.fromEntries()"></a>Object.fromEntries()</h3><blockquote><p>返回一个给定对象自身可枚举属性的键值对数组</p></blockquote><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 通过 Object.fromEntries, 可以将 Map 转化为 Object:</span></span><br><span class="line"><span class="keyword">const</span> map = <span class="keyword">new</span> <span class="built_in">Map</span>([</span><br><span class="line"> [<span class="string">"foo"</span>, <span class="string">"bar"</span>],</span><br><span class="line"> [<span class="string">"baz"</span>, <span class="number">42</span>],</span><br><span class="line">]);</span><br><span class="line"><span class="built_in">console</span>.log(<span class="built_in">Object</span>.fromEntries(map)); <span class="comment">// { foo: "bar", baz: 42 }</span></span><br></pre></td></tr></table></figure><hr><h2 id="ES11(2020)"><a href="#ES11(2020)" class="headerlink" title="ES11(2020)"></a>ES11(2020)</h2><h3 id="Nullish-coalescing-Operator-空值处理"><a href="#Nullish-coalescing-Operator-空值处理" class="headerlink" title="Nullish coalescing Operator(空值处理)"></a>Nullish coalescing Operator(空值处理)</h3><blockquote><p>表达式在 ?? 的左侧运算符求值为 undefined 或 null,返回其右侧。</p></blockquote><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">let</span> user = {</span><br><span class="line"> u1: <span class="number">0</span>,</span><br><span class="line"> u2: <span class="literal">false</span>,</span><br><span class="line"> u3: <span class="literal">null</span>,</span><br><span class="line"> u4: <span class="literal">undefined</span>,</span><br><span class="line"> u5: <span class="string">""</span>,</span><br><span class="line">};</span><br><span class="line"><span class="keyword">let</span> u2 = user.u2 ?? <span class="string">"用户2"</span>; <span class="comment">// false</span></span><br><span class="line"><span class="keyword">let</span> u3 = user.u3 ?? <span class="string">"用户3"</span>; <span class="comment">// 用户3</span></span><br><span class="line"><span class="keyword">let</span> u4 = user.u4 ?? <span class="string">"用户4"</span>; <span class="comment">// 用户4</span></span><br><span class="line"><span class="keyword">let</span> u5 = user.u5 ?? <span class="string">"用户5"</span>; <span class="comment">// ''</span></span><br></pre></td></tr></table></figure><h3 id="Optional-chaining(可选链)"><a href="#Optional-chaining(可选链)" class="headerlink" title="Optional chaining(可选链)"></a>Optional chaining(可选链)</h3><blockquote><p>?.用户检测不确定的中间节点</p></blockquote><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> user = {};</span><br><span class="line"><span class="keyword">let</span> u1 = user.childer.name; <span class="comment">// TypeError: Cannot read property 'name' of undefined</span></span><br><span class="line"><span class="keyword">let</span> u1 = user.childer?.name; <span class="comment">// undefined</span></span><br></pre></td></tr></table></figure><h3 id="Promise-allSettled"><a href="#Promise-allSettled" class="headerlink" title="Promise.allSettled"></a>Promise.allSettled</h3><blockquote><p>返回一个在所有给定的 promise 已被决议或被拒绝后决议的 promise,并带有一个对象数组,每个对象表示对应的 promise 结果</p></blockquote><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> promise1 = <span class="built_in">Promise</span>.resolve(<span class="number">3</span>);</span><br><span class="line"><span class="keyword">const</span> promise2 = <span class="number">4</span>;</span><br><span class="line"><span class="keyword">const</span> promise3 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span></span><br><span class="line"> reject(<span class="string">"我是失败的Promise_1"</span>)</span><br><span class="line">);</span><br><span class="line"><span class="keyword">const</span> promise4 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span></span><br><span class="line"> reject(<span class="string">"我是失败的Promise_2"</span>)</span><br><span class="line">);</span><br><span class="line"><span class="keyword">const</span> promiseList = [promise1, promise2, promise3, promise4];</span><br><span class="line"><span class="built_in">Promise</span>.allSettled(promiseList).then(<span class="function">(<span class="params">values</span>) =></span> {</span><br><span class="line"> <span class="built_in">console</span>.log(values);</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.nlark.com/yuque/0/2021/png/13014187/1626774777942-7184998d-822e-4c4f-a41a-cbf1f6df1b1e.png#id=AM8Iw&originHeight=935&originWidth=1388&originalType=binary&ratio=1&status=done&style=none"></p><h3 id="import"><a href="#import" class="headerlink" title="import()"></a>import()</h3><blockquote><p>按需导入</p></blockquote><h3 id="新基本数据类型-BigInt"><a href="#新基本数据类型-BigInt" class="headerlink" title="新基本数据类型 BigInt"></a>新基本数据类型 BigInt</h3><blockquote><p>任意精度的整数</p></blockquote><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">BigInt</span>(<span class="number">12</span>); <span class="comment">// 12n</span></span><br></pre></td></tr></table></figure><h3 id="globalThis"><a href="#globalThis" class="headerlink" title="globalThis"></a>globalThis</h3><ul><li>浏览器:window</li><li>worker:self</li><li>node:global</li></ul><hr><h2 id="ES12(2021)"><a href="#ES12(2021)" class="headerlink" title="ES12(2021)"></a>ES12(2021)</h2><h3 id="replaceAll"><a href="#replaceAll" class="headerlink" title="replaceAll"></a>replaceAll</h3><blockquote><p>返回一个全新的字符串,所有符合匹配规则的字符都将被替换掉</p></blockquote><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"><span class="keyword">const</span> str = <span class="string">"hello world"</span>;</span><br><span class="line">str.replaceAll(<span class="string">"l"</span>, <span class="string">""</span>); <span class="comment">// "heo word"</span></span><br></pre></td></tr></table></figure><h3 id="Promise-any"><a href="#Promise-any" class="headerlink" title="Promise.any"></a>Promise.any</h3><blockquote><p>Promise.any() 接收一个 Promise 可迭代对象,只要其中的一个 promise 成功,就返回那个已经成功的 promise 。如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promise</p></blockquote><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> promise1 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span></span><br><span class="line"> reject(<span class="string">"我是失败的Promise_1"</span>)</span><br><span class="line">);</span><br><span class="line"><span class="keyword">const</span> promise2 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span></span><br><span class="line"> reject(<span class="string">"我是失败的Promise_2"</span>)</span><br><span class="line">);</span><br><span class="line"><span class="keyword">const</span> promiseList = [promise1, promise2];</span><br><span class="line"><span class="built_in">Promise</span>.any(promiseList)</span><br><span class="line"> .then(<span class="function">(<span class="params">values</span>) =></span> {</span><br><span class="line"> <span class="built_in">console</span>.log(values);</span><br><span class="line"> })</span><br><span class="line"> .catch(<span class="function">(<span class="params">e</span>) =></span> {</span><br><span class="line"> <span class="built_in">console</span>.log(e);</span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line"><span class="comment">// Promise {<fulfilled>: undefined}</span></span><br><span class="line"><span class="comment">// __proto__: Promise</span></span><br><span class="line"><span class="comment">// [[PromiseState]]: "fulfilled"</span></span><br><span class="line"><span class="comment">// [[PromiseResult]]: undefined</span></span><br></pre></td></tr></table></figure><h3 id="逻辑运算符和赋值表达式"><a href="#逻辑运算符和赋值表达式" class="headerlink" title="逻辑运算符和赋值表达式"></a>逻辑运算符和赋值表达式</h3><blockquote><p>逻辑运算符和赋值表达式,新特性结合了逻辑运算符(&&,||,??)和赋值表达式而 JavaScript 已存在的 复合赋值运算符有:</p></blockquote><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">a ||= b;</span><br><span class="line"><span class="comment">//等价于</span></span><br><span class="line">a = a || (a = b);</span><br><span class="line"></span><br><span class="line">a &&= b;</span><br><span class="line"><span class="comment">//等价于</span></span><br><span class="line">a = a && (a = b);</span><br><span class="line"></span><br><span class="line">a ??= b;</span><br><span class="line"><span class="comment">//等价于</span></span><br><span class="line">a = a ?? (a = b);</span><br></pre></td></tr></table></figure><h3 id="数字分隔符"><a href="#数字分隔符" class="headerlink" title="数字分隔符"></a>数字分隔符</h3><blockquote><p>数字分隔符,可以在数字之间创建可视化分隔符,通过_下划线来分割数字,使数字更具可读性</p></blockquote><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="keyword">const</span> money = <span class="number">1_000_000_000</span>;</span><br><span class="line"><span class="comment">//等价于</span></span><br><span class="line"><span class="keyword">const</span> money = <span class="number">1000000000</span>;</span><br><span class="line"></span><br><span class="line"><span class="number">1_000_000_000</span> === <span class="number">1000000000</span>; <span class="comment">// true</span></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><p>本文集合了 ES6 至 ES11 常用到的特性,包括还在规划的 ES12。</p>
<h2 id="ES6(2015)"><a href="#ES6(2015)" class="headerlink" title="ES6(2015)"></a>ES6(2015)</h2></summary>
<category term="ES6" scheme="http://imagineblog.host/categories/ES6/"/>
<category term="ES6" scheme="http://imagineblog.host/tags/ES6/"/>
</entry>
<entry>
<title>js笛卡尔积算法</title>
<link href="http://imagineblog.host/Cartesian-product/"/>
<id>http://imagineblog.host/Cartesian-product/</id>
<published>2021-05-26T06:55:30.000Z</published>
<updated>2022-08-31T08:04:19.373Z</updated>
<content type="html"><![CDATA[<h2 id="定义"><a href="#定义" class="headerlink" title="定义"></a>定义</h2><blockquote><p>在数学中的解释是,两个集合X和Y的<a href="https://baike.baidu.com/item/%E7%AC%9B%E5%8D%A1%E5%B0%94%E4%B9%98%E7%A7%AF/6323173?fromtitle=%E7%AC%9B%E5%8D%A1%E5%B0%94%E7%A7%AF&fromid=1434391&fr=aladdin">笛卡尓积(Cartesian product)</a>,又称直积,表示为X × Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员。</p></blockquote><p>假设集合A={a, b},集合B={0, 1, 2},则两个集合的笛卡尔积为{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。</p><div class="tip cogs"><p>简单来说就是多组数据的排列组合</p></div><hr><h2 id="应用场景"><a href="#应用场景" class="headerlink" title="应用场景"></a>应用场景</h2><ol><li>在电商项目中,常用于商品SKU的订单组合;根据商品的子类型和不同颜色尺寸生成n种可能的组合</li><li>MySql的多表查询</li><li>生成坐标<br>…….</li></ol><hr><h2 id="js代码"><a href="#js代码" class="headerlink" title="js代码"></a>js代码</h2><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="title">cartesianProduct</span> (<span class="params">array</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (array.length < <span class="number">2</span>) <span class="keyword">return</span> array[<span class="number">0</span>] || [];</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> [].reduce.call(array, <span class="function"><span class="keyword">function</span> (<span class="params">col, set</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> res = [];</span><br><span class="line"></span><br><span class="line"> col.forEach(<span class="function"><span class="keyword">function</span> (<span class="params">c</span>) </span>{</span><br><span class="line"> set.forEach(<span class="function"><span class="keyword">function</span> (<span class="params">s</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> t = [].concat(<span class="built_in">Array</span>.isArray(c) ? c : [c]);</span><br><span class="line"> t.push(s);</span><br><span class="line"> res.push(t);</span><br><span class="line"> })</span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> res;</span><br><span class="line"> });</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">cartesianProduct ([[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>],[<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>],[<span class="string">"张三"</span>,<span class="string">"李四"</span>,<span class="string">"王五"</span>]]) </span><br><span class="line"></span><br></pre></td></tr></table></figure><p>得到的结果:<br><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/1629962811000.png"></p><hr><h2 id="其它实现方法"><a href="#其它实现方法" class="headerlink" title="其它实现方法"></a>其它实现方法</h2><div class="btns rounded grid5"> <a class="button" href='https://blog.csdn.net/h785160953/article/details/104418306?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-4.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-4.control' title='笛卡尔积实现-JavaScript版'><i class='fas fa-book-open'></i>笛卡尔积实现-JavaScript版</a><a class="button" href='https://www.cnblogs.com/52fhy/p/5823934.html' title='飞鸿影的博客-笛卡尔积'><i class='fas fa-book-open'></i>飞鸿影的博客-笛卡尔积</a> </div><hr>]]></content>
<summary type="html"><h2 id="定义"><a href="#定义" class="headerlink" title="定义"></a>定义</h2><blockquote>
<p>在数学中的解释是,两个集合X和Y的<a href="https://baike.baidu.com/item/%E</summary>
<category term="javascript" scheme="http://imagineblog.host/categories/javascript/"/>
<category term="算法" scheme="http://imagineblog.host/tags/%E7%AE%97%E6%B3%95/"/>
</entry>
<entry>
<title>Chrome Extension(扩展程序)开发</title>
<link href="http://imagineblog.host/lomf3x/"/>
<id>http://imagineblog.host/lomf3x/</id>
<published>2021-05-21T07:51:55.000Z</published>
<updated>2022-08-31T08:04:19.377Z</updated>
<content type="html"><![CDATA[<h2 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h2><h3 id="chrome-扩展是什么?"><a href="#chrome-扩展是什么?" class="headerlink" title="chrome 扩展是什么?"></a>chrome 扩展是什么?</h3><p>一个应用(扩展)其实是压缩(.crx 后缀)在一起的一组文件,包括 HTML,CSS,Javascript 脚本,图片文件,还有其它任何需要的文件。 应用(扩展)本质上来说就是 web 页面,它们可以使用所有的浏览器提供的 API,从 XMLHttpRequest 到 JSON 到 HTML5 全都有。</p><p>应用(扩展)可以与 Web 页面交互,或者通过 content script 或 cross-origin XMLHttpRequests 与服务器交互。应用(扩展)还可以访问浏览器提供的内部功能,例如标签或书签等。</p><h3 id="chrome-扩展用处"><a href="#chrome-扩展用处" class="headerlink" title="chrome 扩展用处"></a>chrome 扩展用处</h3><p>增强浏览器的功能,可以向页面注入 js 脚本作一些操作,实现属于自己的“定制版”浏览器。<br>提供了很多 API 供我们来使用:</p><ul><li><a href="http://open.chrome.360.cn/extension_dev/tabs.html">标签</a></li><li><a href="http://open.chrome.360.cn/extension_dev/bookmarks.html">书签</a></li><li><a href="http://open.chrome.360.cn/extension_dev/cookies.html">Cookies</a></li><li><a href="http://open.chrome.360.cn/extension_dev/evnets.html">Events</a></li><li><a href="http://open.chrome.360.cn/extension_dev/devtools.html">开发者工具</a></li><li><a href="http://open.chrome.360.cn/extension_dev/history.html">历史记录</a></li><li><a href="http://open.chrome.360.cn/extension_dev/management.html">插件管理</a></li><li><a href="http://open.chrome.360.cn/extension_dev/windows.html">视窗</a><br>等等…</li></ul><hr><h2 id="开发与调试"><a href="#开发与调试" class="headerlink" title="开发与调试"></a>开发与调试</h2><p>Chrome 插件没有严格的项目结构要求,只要保证本目录有一个 manifest.json 即可,也不需要专门的 IDE,普通的 web 开发工具即可。<br>从右上角菜单->更多工具->扩展程序可以进入插件管理页面,也可以直接在地址栏输入 chrome://extensions 访问。</p><div class="note info modern"><p>勾选开发者模式即可以文件夹的形式直接加载插件,否则只能安装.crx 格式的文件。Chrome 要求插件必须从它的 Chrome 应用商店安装,其它任何网站下载的都无法直接安装,所以,其实我们可以把 crx 文件解压,然后通过开发者模式直接加载。</p><p>开发中,代码有任何改动都必须重新加载插件,只需要在插件管理页按下 Ctrl+R 即可,以防万一最好还把页面刷新一下。</p></div><h3 id="核心结构"><a href="#核心结构" class="headerlink" title="核心结构"></a>核心结构</h3><div class="tabs" id="核心结构"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#核心结构-1">manifest.json</button></li><li class="tab"><button type="button" data-href="#核心结构-2">content-scripts</button></li><li class="tab"><button type="button" data-href="#核心结构-3">backgroud</button></li><li class="tab"><button type="button" data-href="#核心结构-4">popup</button></li><li class="tab"><button type="button" data-href="#核心结构-5">inject-script</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="核心结构-1"><p>这是一个 Chrome 插件最重要也是必不可少的文件,用来配置所有和插件相关的配置,必须放在根目录。<br>字段说明:</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><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></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"manifest_version"</span>: <span class="number">2</span>, <span class="comment">// 清单文件的版本,这个必须写,而且必须是2</span></span><br><span class="line"></span><br><span class="line"> <span class="attr">"name"</span>: <span class="string">"demo"</span>, <span class="comment">// 插件的名称</span></span><br><span class="line"> <span class="attr">"version"</span>: <span class="string">"1.0.0"</span>, <span class="comment">// 插件的版本</span></span><br><span class="line"> <span class="attr">"description"</span>: <span class="string">"Chrome扩展demo"</span>, <span class="comment">// 插件描述</span></span><br><span class="line"> <span class="comment">// 图标,一般偷懒全部用一个尺寸的也没问题</span></span><br><span class="line"> <span class="attr">"icons"</span>: {</span><br><span class="line"> <span class="attr">"16"</span>: <span class="string">"img/icon.png"</span>,</span><br><span class="line"> <span class="attr">"48"</span>: <span class="string">"img/icon.png"</span>,</span><br><span class="line"> <span class="attr">"128"</span>: <span class="string">"img/icon.png"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// 会一直常驻的后台JS或后台页面</span></span><br><span class="line"> <span class="attr">"background"</span>: {</span><br><span class="line"> <span class="comment">// 2种指定方式,如果指定JS,那么会自动生成一个背景页</span></span><br><span class="line"> <span class="attr">"page"</span>: <span class="string">"background.html"</span> <span class="comment">//"scripts": ["js/background.js"]</span></span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// 浏览器右上角图标设置,browser_action、page_action、app必须三选一</span></span><br><span class="line"> <span class="attr">"browser_action"</span>: {</span><br><span class="line"> <span class="attr">"default_icon"</span>: <span class="string">"img/icon.png"</span>,</span><br><span class="line"> <span class="attr">"default_title"</span>: <span class="string">"这是一个Chrome插件"</span>, <span class="comment">// 图标悬停时的标题,可选</span></span><br><span class="line"> <span class="attr">"default_popup"</span>: <span class="string">"popup.html"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="comment">/*"page_action": </span></span><br><span class="line"><span class="comment"> {</span></span><br><span class="line"><span class="comment"> "default_icon": "img/icon.png", // 当某些特定页面打开才显示的图标</span></span><br><span class="line"><span class="comment"> "default_title": "我是pageAction",</span></span><br><span class="line"><span class="comment"> "default_popup": "popup.html"</span></span><br><span class="line"><span class="comment"> },*/</span> <span class="comment">// 需要直接注入页面的JS</span></span><br><span class="line"> <span class="attr">"content_scripts"</span>: [</span><br><span class="line"> {</span><br><span class="line"> <span class="comment">//"matches": ["http://*/*", "https://*/*"],</span></span><br><span class="line"> <span class="comment">// "<all_urls>" 表示匹配所有地址</span></span><br><span class="line"> <span class="attr">"matches"</span>: [<span class="string">"<all_urls>"</span>], <span class="comment">// 多个JS按顺序注入</span></span><br><span class="line"> <span class="attr">"js"</span>: [<span class="string">"js/jquery-1.8.3.js"</span>, <span class="string">"js/content-script.js"</span>], <span class="comment">// JS的注入可以随便一点,但是CSS的注意就要千万小心了,因为一不小心就可能影响全局样式</span></span><br><span class="line"> <span class="attr">"css"</span>: [<span class="string">"css/custom.css"</span>], <span class="comment">// 代码注入的时间,可选值: "document_start", "document_end", or "document_idle",最后一个表示页面空闲时,默认document_idle</span></span><br><span class="line"> <span class="attr">"run_at"</span>: <span class="string">"document_start"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// 这里仅仅是为了演示content-script可以配置多个规则</span></span><br><span class="line"> {</span><br><span class="line"> <span class="attr">"matches"</span>: [<span class="string">"*://*/*.png"</span>, <span class="string">"*://*/*.jpg"</span>, <span class="string">"*://*/*.gif"</span>, <span class="string">"*://*/*.bmp"</span>],</span><br><span class="line"> <span class="attr">"js"</span>: [<span class="string">"js/show-image-content-size.js"</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="attr">"permissions"</span>: [</span><br><span class="line"> <span class="string">"contextMenus"</span>, <span class="comment">// 右键菜单</span></span><br><span class="line"> <span class="string">"tabs"</span>, <span class="comment">// 标签</span></span><br><span class="line"> <span class="string">"notifications"</span>, <span class="comment">// 通知</span></span><br><span class="line"> <span class="string">"webRequest"</span>, <span class="comment">// web请求</span></span><br><span class="line"> <span class="string">"webRequestBlocking"</span>,</span><br><span class="line"> <span class="string">"storage"</span>, <span class="comment">// 插件本地存储</span></span><br><span class="line"> <span class="string">"http://*/*"</span>, <span class="comment">// 可以通过executeScript或者insertCSS访问的网站</span></span><br><span class="line"> <span class="string">"https://*/*"</span> <span class="comment">// 可以通过executeScript或者insertCSS访问的网站</span></span><br><span class="line"> ],</span><br><span class="line"> <span class="comment">// 普通页面能够直接访问的插件资源列表,如果不设置是无法直接访问的</span></span><br><span class="line"> <span class="attr">"web_accessible_resources"</span>: [<span class="string">"js/inject.js"</span>], <span class="comment">// 插件主页,这个很重要,不要浪费了这个免费广告位</span></span><br><span class="line"> <span class="attr">"homepage_url"</span>: <span class="string">"https://www.baidu.com"</span>, <span class="comment">// 覆盖浏览器默认页面</span></span><br><span class="line"> <span class="attr">"chrome_url_overrides"</span>: {</span><br><span class="line"> <span class="comment">// 覆盖浏览器默认的新标签页</span></span><br><span class="line"> <span class="attr">"newtab"</span>: <span class="string">"newtab.html"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// Chrome40以前的插件配置页写法</span></span><br><span class="line"> <span class="attr">"options_page"</span>: <span class="string">"options.html"</span>,</span><br><span class="line"> <span class="comment">// Chrome40以后的插件配置页写法,如果2个都写,新版Chrome只认后面这一个</span></span><br><span class="line"> <span class="attr">"options_ui"</span>: {</span><br><span class="line"> <span class="attr">"page"</span>: <span class="string">"options.html"</span>,</span><br><span class="line"> <span class="attr">"chrome_style"</span>: <span class="literal">true</span> <span class="comment">// 添加一些默认的样式,推荐使用</span></span><br><span class="line"> },</span><br><span class="line"> <span class="attr">"omnibox"</span>: { <span class="attr">"keyword"</span>: <span class="string">"go"</span> }, <span class="comment">// 向地址栏注册一个关键字以提供搜索建议,只能设置一个关键字</span></span><br><span class="line"> <span class="attr">"default_locale"</span>: <span class="string">"zh_CN"</span>, <span class="comment">// 默认语言</span></span><br><span class="line"> <span class="comment">// devtools页面入口,注意只能指向一个HTML文件,不能是JS文件</span></span><br><span class="line"> <span class="attr">"devtools_page"</span>: <span class="string">"devtools.html"</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="核心结构-2"><p>content-scripts,是 Chrome 插件中向页面注入脚本的一种形式(虽然名为 script,其实还可以包括 css 的),借助 content-scripts 我们可以实现通过配置的方式轻松向指定页面注入 JS 和 CSS,最常见的比如:广告屏蔽、页面 CSS 定制,等等。</p><p>配置 🌰:</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="comment">// 需要直接注入页面的JS</span></span><br><span class="line"> <span class="attr">"content_scripts"</span>: [</span><br><span class="line"> {</span><br><span class="line"> <span class="comment">//"matches": ["http://*/*", "https://*/*"],</span></span><br><span class="line"> <span class="comment">// "<all_urls>" 表示匹配所有地址</span></span><br><span class="line"> <span class="attr">"matches"</span>: [<span class="string">"<all_urls>"</span>], <span class="comment">// 多个JS按顺序注入</span></span><br><span class="line"> <span class="attr">"js"</span>: [<span class="string">"js/jquery-1.8.3.js"</span>, <span class="string">"js/content-script.js"</span>], <span class="comment">// JS的注入可以随便一点,但是CSS的注意就要千万小心了,因为一不小心就可能影响全局样式</span></span><br><span class="line"> <span class="attr">"css"</span>: [<span class="string">"css/custom.css"</span>], <span class="comment">// 代码注入的时间,可选值: "document_start", "document_end", or "document_idle",最后一个表示页面空闲时,默认document_idle</span></span><br><span class="line"> <span class="attr">"run_at"</span>: <span class="string">"document_start"</span></span><br><span class="line"> }</span><br><span class="line"> ]</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>content-scripts 和原始页面共享 DOM,但是不共享 JS,如要访问页面 JS(例如某个 JS 变量),只能通过 injected js 来实现。content-scripts 不能访问绝大部分 chrome.xxx.api,除了下面这 4 种:</p><ul><li>chrome.extension(getURL , inIncognitoContext , lastError , onRequest , sendRequest)</li><li>chrome.i18n</li><li>chrome.runtime(connect , getManifest , getURL , id , onConnect , onMessage , sendMessage)</li><li>chrome.storage</li></ul><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="核心结构-3"><p>背景页,是一个常驻的页面,它的生命周期是插件中所有类型页面中最长的,它随着浏览器的打开而打开,随着浏览器的关闭而关闭,所以通常把需要一直运行的、启动就运行的、全局的代码放在 background 里面。</p><blockquote><p>background 的权限非常高,几乎可以调用所有的 Chrome 扩展 API(除了 devtools),而且它可以无限制跨域,也就是可以跨域访问任何网站而无需要求对方设置 CORS。不止是 background,所有的直接通过 chrome-extension://id/xx.html 这种方式打开的网页都可以无限制跨域。</p></blockquote><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></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="comment">// 会一直常驻的后台JS或后台页面</span></span><br><span class="line"> <span class="attr">"background"</span>: {</span><br><span class="line"> <span class="comment">// 2种指定方式,如果指定JS,那么会自动生成一个背景页</span></span><br><span class="line"> <span class="attr">"page"</span>: <span class="string">"background.html"</span> <span class="comment">//"scripts": ["js/background.js"]</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><div class="note info modern"><p>需要特别说明的是,虽然可以通过 chrome-extension://xxx/background.html 直接打开后台页,但是打开的后台页和真正一直在后台运行的那个页面不是同一个,换句话说,可以打开无数个 background.html,但是真正在后台常驻的只有一个,而且永远看不到它的界面,只能调试它的代码。</p></div><ul><li>event-pages<br>鉴于 background 生命周期太长,长时间挂载后台可能会影响性能,所以 Google 又弄一个 event-pages,在配置文件上,它与 background 的唯一区别就是多了一个 persistent 参数。</li></ul><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></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"background"</span>: {</span><br><span class="line"> <span class="attr">"scripts"</span>: [<span class="string">"event-page.js"</span>],</span><br><span class="line"> <span class="attr">"persistent"</span>: <span class="literal">false</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>它的生命周期是:在被需要时加载,在空闲时被关闭,什么叫被需要时呢?比如第一次安装、插件更新、有 content-script 向它发送消息,等等。<br>除了配置文件的变化,代码上也有一些细微变化,这个简单了解一下就行了,一般情况下 background 也不会很消耗性能的。</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="核心结构-4"><p>popup 是点击 browser_action 或者 page_action 图标时打开的一个小窗口网页,焦点离开网页就立即关闭,一般用来做一些临时性的交互。</p><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/popup.png"></p><p>popup 可以包含任意你想要的 HTML 内容,并且会自适应大小。可以通过 default_popup 字段来指定 popup 页面,也可以调用 setPopup()方法。<br>配置 🌰:</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></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"browser_action"</span>: {</span><br><span class="line"> <span class="attr">"default_icon"</span>: <span class="string">"img/icon.png"</span>, <span class="comment">// 图标悬停时的标题,可选</span></span><br><span class="line"> <span class="attr">"default_title"</span>: <span class="string">"这是一个Chrome插件"</span>,</span><br><span class="line"> <span class="attr">"default_popup"</span>: <span class="string">"popup.html"</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><div class="note info modern"><p>需要特别注意的是,由于单击图标打开 popup,焦点离开又立即关闭,所以 popup 页面的生命周期一般很短,需要长时间运行的代码千万不要写在 popup 里面。</p><p>在权限上,它和 background 非常类似,它们之间最大的不同是生命周期的不同,popup 中可以直接通过 chrome.extension.getBackgroundPage()获取 background 的 window 对象。</p></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="核心结构-5"><p>这里的 inject-script 是我给它取的,指的是通过 DOM 操作的方式向页面注入的一种 JS。为什么要把这种 JS 单独拿出来讨论呢?又或者说为什么需要通过这种方式注入 JS 呢?<br>这是因为 content-script 有一个很大的“缺陷”,也就是无法访问页面中的 JS,虽然它可以操作 DOM,但是 DOM 却不能调用它,也就是无法在 DOM 中通过绑定事件的方式调用 content-script 中的代码(包括直接写 onclick 和 addEventListener 两种方式都不行),但是,“在页面上添加一个按钮并调用插件的扩展 API”是一个很常见的需求,那该怎么办呢?其实这就是本小节要讲的。</p><p>在 content-script 中通过 DOM 方式向页面注入 inject-script 代码示例:</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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 向页面注入JS</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">injectCustomJs</span>(<span class="params">jsPath</span>) </span>{</span><br><span class="line"> jsPath = jsPath || <span class="string">"js/inject.js"</span>;</span><br><span class="line"> <span class="keyword">var</span> temp = <span class="built_in">document</span>.createElement(<span class="string">"script"</span>);</span><br><span class="line"> temp.setAttribute(<span class="string">"type"</span>, <span class="string">"text/javascript"</span>); <span class="comment">// 获得的地址类似:chrome-extension://ihcokhadfjfchaeagdoclpnjdiokfakg/js/inject.js</span></span><br><span class="line"> temp.src = chrome.extension.getURL(jsPath);</span><br><span class="line"> temp.onload = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="comment">// 放在页面不好看,执行完后移除掉</span></span><br><span class="line"> <span class="built_in">this</span>.parentNode.removeChild(<span class="built_in">this</span>);</span><br><span class="line"> };</span><br><span class="line"> <span class="built_in">document</span>.head.appendChild(temp);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>在 web 中直接访问插件中的资源的话必须显示声明才行,配置文件中增加如下</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></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="comment">// 普通页面能够直接访问的插件资源列表,如果不设置是无法直接访问的</span></span><br><span class="line"> <span class="attr">"web_accessible_resources"</span>: [<span class="string">"js/inject.js"</span>]</span><br><span class="line">}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h3 id="展现形式"><a href="#展现形式" class="headerlink" title="展现形式"></a>展现形式</h3><div class="tabs" id="展现形式"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#展现形式-1">browserAction</button></li><li class="tab"><button type="button" data-href="#展现形式-2">pageAction</button></li><li class="tab"><button type="button" data-href="#展现形式-3">右键菜单</button></li><li class="tab"><button type="button" data-href="#展现形式-4">override</button></li><li class="tab"><button type="button" data-href="#展现形式-5">devtools</button></li><li class="tab"><button type="button" data-href="#展现形式-6">option</button></li><li class="tab"><button type="button" data-href="#展现形式-7">onmnibox</button></li><li class="tab"><button type="button" data-href="#展现形式-8">notification</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="展现形式-1"><p>通过配置 browser_action 可以在浏览器的右上角增加一个图标,一个 browser_action 可以拥有一个图标,一个 tooltip,一个 badge 和一个 popup。</p><ul><li>icon(图标)<br>browser_action 图标推荐使用宽高都为 19 像素的图片,更大的图标会被缩小,格式随意,一般推荐 png,可以通过 manifest 中 default_icon 字段配置,也可以调用 setIcon()方法。</li><li>tooltip<br>修改 browser_action 的 manifest 中 default_title 字段,或者调用 setTitle()方法。</li></ul><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/tooltip.png"></p><ul><li>badge<br>所谓 badge 就是在图标上显示一些文本,可以用来更新一些小的扩展状态提示信息。因为 badge 空间有限,所以只支持 4 个以下的字符(英文 4 个,中文 2 个)。badge 无法通过配置文件来指定,必须通过代码实现,设置 badge 文字和颜色可以分别使用 setBadgeText()和 setBadgeBackgroundColor()。</li></ul><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">chrome.browserAction.setBadgeText({ <span class="attr">text</span>: <span class="string">"new"</span> });</span><br><span class="line">chrome.browserAction.setBadgeBackgroundColor({ <span class="attr">color</span>: [<span class="number">255</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">255</span>] });</span><br></pre></td></tr></table></figure><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/badge.png"></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="展现形式-2"><p>所谓 pageAction,指的是只有当某些特定页面打开才显示的图标,它和 browserAction 最大的区别是一个始终都显示,一个只在特定情况才显示。</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="展现形式-3"><p>通过开发 Chrome 插件可以自定义浏览器的右键菜单,主要是通过 chrome.contextMenusAPI 实现,右键菜单可以出现在不同的上下文,比如普通页面、选中的文字、图片、链接,等等,如果有同一个插件里面定义了多个菜单,Chrome 会自动组合放到以插件名字命名的二级菜单里,如下:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// manifest.json</span></span><br><span class="line">{<span class="string">"permissions"</span>: [<span class="string">"contextMenus"</span>]}</span><br><span class="line"></span><br><span class="line"><span class="comment">// background.js</span></span><br><span class="line">chrome.contextMenus.create({</span><br><span class="line"> title: <span class="string">"测试右键菜单"</span>,</span><br><span class="line"> onclick: <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{alert(<span class="string">'您点击了右键菜单!'</span>);}</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/click.png"></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="展现形式-4"><p>使用 override 页可以将 Chrome 默认的一些特定页面替换掉,改为使用扩展提供的页面。<br>扩展可以替代如下页面:</p><ul><li>历史记录:从工具菜单上点击历史记录时访问的页面,或者从地址栏直接输入 chrome://history</li><li>新标签页:当创建新标签的时候访问的页面,或者从地址栏直接输入 chrome://newtab</li><li>书签:浏览器的书签,或者直接输入 chrome://bookmarks<div class="note warning modern"><p> 注意:</p><ul><li>一个扩展只能替代一个页面;</li><li>不能替代隐身窗口的新标签页;</li><li>网页必须设置 title,否则用户可能会看到网页的 URL,造成困扰;</li></ul></div></li></ul><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></pre></td><td class="code"><pre><span class="line">"chrome_url_overrides":</span><br><span class="line">{</span><br><span class="line"> <span class="attr">"newtab"</span>: <span class="string">"newtab.html"</span>,</span><br><span class="line"> <span class="attr">"history"</span>: <span class="string">"history.html"</span>,</span><br><span class="line"> <span class="attr">"bookmarks"</span>: <span class="string">"bookmarks.html"</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/override.png"></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="展现形式-5"><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/vue.png"></p><p>Chrome 允许插件在开发者工具(devtools)上动手脚,主要表现在:</p><ul><li>自定义一个和多个和 Elements、Console、Sources 等同级别的面板;</li><li>自定义侧边栏(sidebar),目前只能自定义 Elements 面板的侧边栏;</li><li>devtools 扩展介绍</li></ul><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/devtools.png"></p><ul><li>每打开一个开发者工具窗口,都会创建 devtools 页面的实例,F12 窗口关闭,页面也随着关闭,所以 devtools 页面的生命周期和 devtools 窗口是一致的。devtools 页面可以访问一组特有的 DevTools API 以及有限的扩展 API,这组特有的 DevTools API 只有 devtools 页面才可以访问,background 都无权访问,这些 API 包括:</li><li>chrome.devtools.panels:面板相关;</li><li>chrome.devtools.inspectedWindow:获取被审查窗口的有关信息;</li><li>chrome.devtools.network:获取有关网络请求的信息;<br>options 页,就是插件的设置页面,有 2 个入口,一个是右键图标有一个“选项”菜单,还有一个在插件管理页面:<blockquote><p>大部分扩展 API 都无法直接被 DevTools 页面调用,但它可以像 content-script 一样直接调用 chrome.extension 和 chrome.runtimeAPI,同时它也可以像 content-script 一样使用 Message 交互的方式与 background 页面进行通信。</p></blockquote></li></ul><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="展现形式-6"><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></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"options_ui"</span>: {</span><br><span class="line"> <span class="attr">"page"</span>: <span class="string">"options.html"</span>, <span class="comment">// 添加一些默认的样式,推荐使用</span></span><br><span class="line"> <span class="attr">"chrome_style"</span>: <span class="literal">true</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/option.png"></p><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/option1.png"></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="展现形式-7"><p>omnibox 是向用户提供搜索建议的一种方式。</p><blockquote><p>omnibox 应用程序界面允许向 Google Chrome 的地址栏注册一个关键字,地址栏也叫 omnibox。<br>当用户输入你的扩展关键字,用户开始与你的扩展交互。每个击键都会发送给你的扩展,扩展提供建议作为相应的响应。<br>建议可以被格式化多种方式。当用户接受建议,你的扩展被通知可以执行动作。</p></blockquote><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/go.gif"></p><blockquote><p>配置字段:</p></blockquote><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></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="comment">// 向地址栏注册一个关键字以提供搜索建议,只能设置一个关键字</span></span><br><span class="line"> <span class="attr">"omnibox"</span>: { <span class="attr">"keyword"</span>: <span class="string">"go"</span> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>在 background.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><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></pre></td><td class="code"><pre><span class="line">chrome.omnibox.onInputChanged.addListener(<span class="function">(<span class="params">text, suggest</span>) =></span> {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"inputChanged: "</span> + text);</span><br><span class="line"> <span class="keyword">if</span> (!text) <span class="keyword">return</span>;</span><br><span class="line"> <span class="keyword">if</span> (text == <span class="string">"微博"</span>) {</span><br><span class="line"> suggest([</span><br><span class="line"> { <span class="attr">content</span>: <span class="string">"新浪"</span> + text, <span class="attr">description</span>: <span class="string">"新浪"</span> + text },</span><br><span class="line"> { <span class="attr">content</span>: <span class="string">"腾讯"</span> + text, <span class="attr">description</span>: <span class="string">"腾讯"</span> + text },</span><br><span class="line"> { <span class="attr">content</span>: <span class="string">"搜狐"</span> + text, <span class="attr">description</span>: <span class="string">"搜索"</span> + text },</span><br><span class="line"> ]);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> suggest([</span><br><span class="line"> { <span class="attr">content</span>: <span class="string">"百度搜索 "</span> + text, <span class="attr">description</span>: <span class="string">"百度搜索 "</span> + text },</span><br><span class="line"> { <span class="attr">content</span>: <span class="string">"谷歌搜索 "</span> + text, <span class="attr">description</span>: <span class="string">"谷歌搜索 "</span> + text },</span><br><span class="line"> ]);</span><br><span class="line"> }</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="comment">// 当用户接收关键字建议时触发</span></span><br><span class="line">chrome.omnibox.onInputEntered.addListener(<span class="function">(<span class="params">text</span>) =></span> {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"inputEntered: "</span> + text);</span><br><span class="line"> <span class="keyword">if</span> (!text) <span class="keyword">return</span>;</span><br><span class="line"> <span class="keyword">var</span> href = <span class="string">""</span>;</span><br><span class="line"> <span class="keyword">if</span> (text.endsWith(<span class="string">"微博"</span>))</span><br><span class="line"> href =</span><br><span class="line"> <span class="string">"http://image.baidu.com/search/index?tn=baiduimage&ie=utf-8&word="</span> + text;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (text.startsWith(<span class="string">"百度搜索"</span>))</span><br><span class="line"> href =</span><br><span class="line"> <span class="string">"https://www.baidu.com/s?ie=UTF-8&wd="</span> + text.replace(<span class="string">"百度搜索 "</span>, <span class="string">""</span>);</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (text.startsWith(<span class="string">"谷歌搜索"</span>))</span><br><span class="line"> href =</span><br><span class="line"> <span class="string">"https://www.google.com.tw/search?q="</span> + text.replace(<span class="string">"谷歌搜索 "</span>, <span class="string">""</span>);</span><br><span class="line"> <span class="keyword">else</span> href = <span class="string">"https://www.baidu.com/s?ie=UTF-8&wd="</span> + text;</span><br><span class="line"> openUrlCurrentTab(href);</span><br><span class="line">});</span><br><span class="line"><span class="comment">// 获取当前选项卡ID</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getCurrentTabId</span>(<span class="params">callback</span>) </span>{</span><br><span class="line"> chrome.tabs.query({ <span class="attr">active</span>: <span class="literal">true</span>, <span class="attr">currentWindow</span>: <span class="literal">true</span> }, <span class="function"><span class="keyword">function</span> (<span class="params">tabs</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (callback) callback(tabs.length ? tabs[<span class="number">0</span>].id : <span class="literal">null</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="title">openUrlCurrentTab</span>(<span class="params">url</span>) </span>{</span><br><span class="line"> getCurrentTabId(<span class="function">(<span class="params">tabId</span>) =></span> {</span><br><span class="line"> chrome.tabs.update(tabId, { <span class="attr">url</span>: url });</span><br><span class="line"> });</span><br><span class="line">}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="展现形式-8"><p>通知用户发生了一些重要的事情。桌面通知会显示在浏览器窗口之外。<br>Chrome 提供了一个 chrome.notificationsAPI 以便插件推送桌面通知,暂未找到 chrome.notifications 和 HTML5 自带的 Notification 的显著区别及优势。</p><p>在后台 JS 中,无论是使用 chrome.notifications 还是 Notification 都不需要申请权限(HTML5 方式需要申请权限),直接使用即可。</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><hr><h2 id="五类-JS-文件区别"><a href="#五类-JS-文件区别" class="headerlink" title="五类 JS 文件区别"></a>五类 JS 文件区别</h2><table><thead><tr><th>js 类型</th><th>可访问的 API</th><th>DOM 访问情况</th><th>js 访问情况</th><th>跨域</th><th>调试方式</th></tr></thead><tbody><tr><td>content script</td><td>只能访问 extension、runtime 等部分 API</td><td>✔</td><td>×</td><td>×</td><td>打开 Console,如图切换<img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/tiaoshi.png" alt="tiaoshi.png"></td></tr><tr><td>popup js</td><td>可访问绝大部分 API,除了 devtools 系列</td><td>不可以直接访问</td><td>×</td><td>✔</td><td>popup 页面右键选择“审查弹出内容”</td></tr><tr><td>background js</td><td>可访问绝大部分 API,除了 devtools 系列</td><td>不可以直接访问</td><td>×</td><td>✔</td><td>插件管理页面点击背景页<img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/background.png" alt="background.png"></td></tr><tr><td>devtools js</td><td>只能访问 devtools、extension、runtime 等部分 API</td><td>✔</td><td>✔</td><td>×</td><td>暂时没有找到有效的调试方法</td></tr><tr><td>injected script</td><td>和普通 JS 无任何差别,不能访问任何扩展 API</td><td>✔</td><td>✔</td><td>×</td><td>直接普通的 F12 即可</td></tr></tbody></table><hr><h2 id="消息通信"><a href="#消息通信" class="headerlink" title="消息通信"></a>消息通信</h2><h3 id="通信方式概览"><a href="#通信方式概览" class="headerlink" title="通信方式概览"></a>通信方式概览</h3><table><thead><tr><th>-</th><th>injected-script</th><th>content-script</th><th>popup-js</th><th>background-js</th></tr></thead><tbody><tr><td>injected-script</td><td>–</td><td>window.postMessage</td><td>–</td><td>–</td></tr><tr><td>content-script</td><td>window.postMessage</td><td>–</td><td>chrome.runtime.sendMessage chrome.runtime.connect</td><td>chrome.runtime.sendMessage chrome.runtime.connect</td></tr><tr><td>popup-js</td><td>–</td><td>chrome.tabs.sendMessage chrome.tabs.connect</td><td>–</td><td>chrome.extension.getBackgroundPage()</td></tr><tr><td>background-js</td><td>–</td><td>chrome.tabs.sendMessage chrome.tabs.connect</td><td>chrome.extension.getViews</td><td>–</td></tr><tr><td>devtools-js</td><td>chrome.devtools. inspectedWindow.eval</td><td>–</td><td>chrome.runtime.sendMessage</td><td>chrome.runtime.sendMessage</td></tr></tbody></table><h3 id="popup-amp-amp-background"><a href="#popup-amp-amp-background" class="headerlink" title="popup&&background"></a>popup&&background</h3><ul><li>popup 访问 background<blockquote><p>popup 可以直接调用 background 的 JS 方法,并且可以直接访问 background 的 DOM</p></blockquote></li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// background.js</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">test</span>(<span class="params"></span>) </span>{</span><br><span class="line"> alert(<span class="string">"我是background!"</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// popup.js</span></span><br><span class="line"><span class="keyword">var</span> bg = chrome.extension.getBackgroundPage();</span><br><span class="line">bg.test(); <span class="comment">// 访问bg的函数</span></span><br><span class="line">alert(bg.document.body.innerHTML); <span class="comment">// 访问bg的DOM</span></span><br></pre></td></tr></table></figure><ul><li>background 访问 popup<div class="note info modern"><p>注意:前提是 popup 已经打开时</p></div></li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> views = chrome.extension.getViews({ <span class="attr">type</span>: <span class="string">"popup"</span> });</span><br><span class="line"><span class="keyword">if</span> (views.length > <span class="number">0</span>) {</span><br><span class="line"> <span class="built_in">console</span>.log(views[<span class="number">0</span>].location.href);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="popup-background-amp-amp-content-script"><a href="#popup-background-amp-amp-content-script" class="headerlink" title="(popup/background)&&content-script"></a>(popup/background)&&content-script</h3><ul><li>popup.js/background.js</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">sendMessageToContentScript</span>(<span class="params">message, callback</span>) </span>{</span><br><span class="line"> chrome.tabs.query({ <span class="attr">active</span>: <span class="literal">true</span>, <span class="attr">currentWindow</span>: <span class="literal">true</span> }, <span class="function"><span class="keyword">function</span> (<span class="params">tabs</span>) </span>{</span><br><span class="line"> chrome.tabs.sendMessage(tabs[<span class="number">0</span>].id, message, <span class="function"><span class="keyword">function</span> (<span class="params">response</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (callback) callback(response);</span><br><span class="line"> });</span><br><span class="line"> });</span><br><span class="line">}</span><br><span class="line">sendMessageToContentScript(</span><br><span class="line"> { <span class="attr">cmd</span>: <span class="string">"test"</span>, <span class="attr">value</span>: <span class="string">"你好,我是popup!"</span> },</span><br><span class="line"> <span class="function"><span class="keyword">function</span> (<span class="params">response</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"来自content的回复:"</span> + response);</span><br><span class="line"> }</span><br><span class="line">);</span><br></pre></td></tr></table></figure><ul><li>content-script 接收消息</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">chrome.runtime.onMessage.addListener(<span class="function"><span class="keyword">function</span> (<span class="params">request, sender, sendResponse</span>) </span>{</span><br><span class="line"> <span class="comment">// console.log(sender.tab ?"from a content script:" + sender.tab.url :"from the extension");</span></span><br><span class="line"> <span class="keyword">if</span> (request.cmd == <span class="string">"test"</span>) alert(request.value);</span><br><span class="line"> sendResponse(<span class="string">"我收到了你的消息!"</span>);</span><br><span class="line">});</span><br></pre></td></tr></table></figure><blockquote><p>双方通信直接发送的都是 JSON 对象,不是 JSON 字符串,所以无需解析,很方便(当然也可以直接发送字符串)。</p></blockquote><h3 id="content-script-amp-amp-background-popup"><a href="#content-script-amp-amp-background-popup" class="headerlink" title="content-script&&(background/popup)"></a>content-script&&(background/popup)</h3><ul><li>content-script.js</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">chrome.runtime.sendMessage(</span><br><span class="line"> { <span class="attr">greeting</span>: <span class="string">"你好,我是content-script,主动发消息给后台!"</span> },</span><br><span class="line"> <span class="function"><span class="keyword">function</span> (<span class="params">response</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"收到来自后台的回复:"</span> + response);</span><br><span class="line"> }</span><br><span class="line">);</span><br></pre></td></tr></table></figure><ul><li>background.js/popup.js 接收消息</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 监听来自content-script的消息</span></span><br><span class="line">chrome.runtime.onMessage.addListener(<span class="function"><span class="keyword">function</span> (<span class="params">request, sender, sendResponse</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"收到来自content-script的消息:"</span>);</span><br><span class="line"> <span class="built_in">console</span>.log(request, sender, sendResponse);</span><br><span class="line"> sendResponse(<span class="string">"我是后台,我已收到你的消息:"</span> + <span class="built_in">JSON</span>.stringify(request));</span><br><span class="line">});</span><br></pre></td></tr></table></figure><div class="note warning modern"><ul><li>content_script 向 popup 主动发消息的前提是 popup 必须打开!否则需要利用 background 作中转。</li><li>如果 background 和 popup 同时监听,那么它们都可以同时收到消息,但是只有一个可以 sendResponse,一个先发送了,那么另外一个再发送就无效。</li></ul></div><h3 id="inject-script-amp-amp-content-script"><a href="#inject-script-amp-amp-content-script" class="headerlink" title="inject-script&&content-script"></a>inject-script&&content-script</h3><p>content-script 和页面内的脚本(injected-script 自然也属于页面内的脚本)之间唯一共享的东西就是页面的 DOM 元素,有 2 种方法可以实现二者通讯:</p><ul><li>1.可以通过 window.postMessage 和 window.addEventListener 来实现二者消息通讯(推荐)</li><li>inject-script:</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">window</span>.postMessage({ <span class="attr">test</span>: <span class="string">"Hello,Content"</span> }, <span class="string">"*"</span>);</span><br></pre></td></tr></table></figure><ul><li>content-script:</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">window</span>.addEventListener(</span><br><span class="line"> <span class="string">"message"</span>,</span><br><span class="line"> <span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(e.data);</span><br><span class="line"> },</span><br><span class="line"> <span class="literal">false</span></span><br><span class="line">);</span><br></pre></td></tr></table></figure><ul><li>2.通过自定义 DOM 事件来实现</li><li>inject-script:</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> customEvent = <span class="built_in">document</span>.createEvent(<span class="string">"Event"</span>);</span><br><span class="line">customEvent.initEvent(<span class="string">"myCustomEvent"</span>, <span class="literal">true</span>, <span class="literal">true</span>);</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fireCustomEvent</span>(<span class="params">data</span>) </span>{</span><br><span class="line"> hiddenDiv = <span class="built_in">document</span>.getElementById(<span class="string">"myCustomEventDiv"</span>);</span><br><span class="line"> hiddenDiv.innerText = data;</span><br><span class="line"> hiddenDiv.dispatchEvent(customEvent);</span><br><span class="line">}</span><br><span class="line">fireCustomEvent(<span class="string">"Hello! I’m Injected"</span>);</span><br></pre></td></tr></table></figure><ul><li>content-script:</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> hiddenDiv = <span class="built_in">document</span>.getElementById(<span class="string">"myCustomEventDiv"</span>);</span><br><span class="line"><span class="keyword">if</span> (!hiddenDiv) {</span><br><span class="line"> hiddenDiv = <span class="built_in">document</span>.createElement(<span class="string">"div"</span>);</span><br><span class="line"> hiddenDiv.style.display = <span class="string">"none"</span>;</span><br><span class="line"> <span class="built_in">document</span>.body.appendChild(hiddenDiv);</span><br><span class="line">}</span><br><span class="line">hiddenDiv.addEventListener(<span class="string">"myCustomEvent"</span>, <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> eventData = <span class="built_in">document</span>.getElementById(<span class="string">"myCustomEventDiv"</span>).innerText;</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"收到自定义事件消息:"</span> + eventData);</span><br><span class="line">});</span><br></pre></td></tr></table></figure><hr><h2 id="补充"><a href="#补充" class="headerlink" title="补充"></a>补充</h2><h3 id="动态注入-JS、CSS"><a href="#动态注入-JS、CSS" class="headerlink" title="动态注入 JS、CSS"></a>动态注入 JS、CSS</h3><blockquote><p>虽然在 background 和 popup 中无法直接访问页面 DOM,但是可以通过 chrome.tabs.executeScript 来执行脚本,从而实现访问 web 页面的 DOM(注意,这种方式也不能直接访问页面 JS)。</p></blockquote><p>manifest.json 配置 🌰:</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"name"</span>: <span class="string">"动态注入JS/CSS"</span>,</span><br><span class="line"> ...</span><br><span class="line"> "permissions": [</span><br><span class="line"> "tabs", "http://*/*", "https://*/*"</span><br><span class="line"> ],</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><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">// 动态执行JS代码</span></span><br><span class="line">chrome.tabs.executeScript(tabId, {</span><br><span class="line"> code: <span class="string">'document.body.style.backgroundColor="red"'</span>,</span><br><span class="line">});</span><br><span class="line"><span class="comment">// 动态执行JS文件</span></span><br><span class="line">chrome.tabs.executeScript(tabId, { <span class="attr">file</span>: <span class="string">"some-script.js"</span> });</span><br><span class="line"></span><br><span class="line"><span class="comment">// 动态执行CSS代码</span></span><br><span class="line">chrome.tabs.insertCSS(tabId, { <span class="attr">code</span>: <span class="string">"xxx"</span> });</span><br><span class="line"><span class="comment">// 动态执行CSS文件</span></span><br><span class="line">chrome.tabs.insertCSS(tabId, { <span class="attr">file</span>: <span class="string">"some-style.css"</span> });</span><br></pre></td></tr></table></figure><h3 id="获取当前窗口-ID"><a href="#获取当前窗口-ID" class="headerlink" title="获取当前窗口 ID"></a>获取当前窗口 ID</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">chrome.windows.getCurrent(<span class="function"><span class="keyword">function</span> (<span class="params">currentWindow</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"当前窗口ID:"</span> + currentWindow.id);</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h3 id="获取当前标签页-ID"><a href="#获取当前标签页-ID" class="headerlink" title="获取当前标签页 ID"></a>获取当前标签页 ID</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 获取当前选项卡ID</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getCurrentTabId</span>(<span class="params">callback</span>) </span>{</span><br><span class="line"> chrome.tabs.query({ <span class="attr">active</span>: <span class="literal">true</span>, <span class="attr">currentWindow</span>: <span class="literal">true</span> }, <span class="function"><span class="keyword">function</span> (<span class="params">tabs</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (callback) callback(tabs.length ? tabs[<span class="number">0</span>].id : <span class="literal">null</span>);</span><br><span class="line"> });</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="本地存储"><a href="#本地存储" class="headerlink" title="本地存储"></a>本地存储</h3><p>本地存储建议用 chrome.storage 而不是普通的 localStorage,区别有好几点,最重要的 2 点区别是:</p><ul><li>chrome.storage 是针对插件全局的,即使你在 background 中保存的数据,在 content-script 也能获取到。</li><li>chrome.storage.sync 可以跟随当前登录用户自动同步,这台电脑修改的设置会自动同步到其它电脑,很方便,如果没有登录或者未联网则先保存到本地,等登录了再同步至网络。</li></ul><blockquote><p>需要声明 storage 权限,有 chrome.storage.sync 和 chrome.storage.local2 种方式可供选择,使用示例 🌰 如下:</p></blockquote><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 读取数据,第一个参数是指定要读取的key以及设置默认值</span></span><br><span class="line">chrome.storage.sync.get({ <span class="attr">color</span>: <span class="string">"red"</span>, <span class="attr">age</span>: <span class="number">18</span> }, <span class="function"><span class="keyword">function</span> (<span class="params">items</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(items.color, items.age);</span><br><span class="line">});</span><br><span class="line"><span class="comment">// 保存数据</span></span><br><span class="line">chrome.storage.sync.set({ <span class="attr">color</span>: <span class="string">"blue"</span> }, <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"保存成功!"</span>);</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h3 id="webRequest"><a href="#webRequest" class="headerlink" title="webRequest"></a>webRequest</h3><p>通过 webRequest 系列 API 可以对 HTTP 请求进行任性地修改、定制。<br>生命周期图:</p><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/webRequest.png"></p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//manifest.json</span></span><br><span class="line">{</span><br><span class="line"> <span class="comment">// 权限申请</span></span><br><span class="line"> <span class="string">"permissions"</span>:</span><br><span class="line"> [</span><br><span class="line"> <span class="string">"webRequest"</span>, <span class="comment">// web请求</span></span><br><span class="line"> <span class="string">"webRequestBlocking"</span>, <span class="comment">// 阻塞式web请求</span></span><br><span class="line"> <span class="string">"storage"</span>, <span class="comment">// 插件本地存储</span></span><br><span class="line"> <span class="string">"http://*/*"</span>, <span class="comment">// 可以通过executeScript或者insertCSS访问的网站</span></span><br><span class="line"> <span class="string">"https://*/*"</span> <span class="comment">// 可以通过executeScript或者insertCSS访问的网站</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="comment">// background.js</span></span><br><span class="line"><span class="comment">// 是否显示图片</span></span><br><span class="line"><span class="keyword">var</span> showImage;</span><br><span class="line">chrome.storage.sync.get({<span class="attr">showImage</span>: <span class="literal">true</span>}, <span class="function"><span class="keyword">function</span>(<span class="params">items</span>) </span>{</span><br><span class="line"> showImage = items.showImage;</span><br><span class="line">});</span><br><span class="line"><span class="comment">// web请求监听,最后一个参数表示阻塞式,需单独声明权限:webRequestBlocking</span></span><br><span class="line">chrome.webRequest.onBeforeRequest.addListener(<span class="function"><span class="params">details</span> =></span> {</span><br><span class="line"> <span class="comment">// cancel 表示取消本次请求</span></span><br><span class="line"> <span class="keyword">if</span>(!showImage && details.type == <span class="string">'image'</span>) <span class="keyword">return</span> {<span class="attr">cancel</span>: <span class="literal">true</span>};</span><br><span class="line"> <span class="comment">// 简单的音视频检测</span></span><br><span class="line"> <span class="comment">// 大部分网站视频的type并不是media,且视频做了防下载处理,所以这里仅仅是为了演示效果,无实际意义</span></span><br><span class="line"> <span class="keyword">if</span>(details.type == <span class="string">'media'</span>) {</span><br><span class="line"> chrome.notifications.create(<span class="literal">null</span>, {</span><br><span class="line"> type: <span class="string">'basic'</span>,</span><br><span class="line"> iconUrl: <span class="string">'img/icon48.png'</span>,</span><br><span class="line"> title: <span class="string">'检测到音视频'</span>,</span><br><span class="line"> message: <span class="string">'音视频地址:'</span> + details.url,</span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line">}, {<span class="attr">urls</span>: [<span class="string">"<all_urls>"</span>]}, [<span class="string">"blocking"</span>]);</span><br></pre></td></tr></table></figure><p>示例 🌰:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 每次请求前触发,可以拿到 requestBody 数据,同时可以对本次请求作出干预修改</span></span><br><span class="line">chrome.webRequest.onBeforeRequest.addListener(</span><br><span class="line"> (details) => {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"onBeforeRequest"</span>, details);</span><br><span class="line"> },</span><br><span class="line"> { <span class="attr">urls</span>: [<span class="string">"<all_urls>"</span>] },</span><br><span class="line"> [<span class="string">"blocking"</span>, <span class="string">"extraHeaders"</span>, <span class="string">"requestBody"</span>]</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 发送header之前触发,可以拿到请求headers,也可以添加、修改、删除headers</span></span><br><span class="line"><span class="comment">// 但使用有一定限制,一些特殊头部可能拿不到或者存在特殊情况,详见官网文档</span></span><br><span class="line">chrome.webRequest.onBeforeSendHeaders.addListener(</span><br><span class="line"> (details) => {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"onBeforeSendHeaders"</span>, details);</span><br><span class="line"> },</span><br><span class="line"> { <span class="attr">urls</span>: [<span class="string">"<all_urls>"</span>] },</span><br><span class="line"> [<span class="string">"blocking"</span>, <span class="string">"extraHeaders"</span>, <span class="string">"requestHeaders"</span>]</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 开始响应触发,可以拿到服务端返回的headers</span></span><br><span class="line">chrome.webRequest.onResponseStarted.addListener(</span><br><span class="line"> (details) => {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"onResponseStarted"</span>, details);</span><br><span class="line"> },</span><br><span class="line"> { <span class="attr">urls</span>: [<span class="string">"<all_urls>"</span>] },</span><br><span class="line"> [<span class="string">"extraHeaders"</span>, <span class="string">"responseHeaders"</span>]</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 请求完成触发,能拿到的数据和onResponseStarted一样,注意无法拿到responseBody</span></span><br><span class="line">chrome.webRequest.onCompleted.addListener(</span><br><span class="line"> (details) => {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"onCompleted"</span>, details);</span><br><span class="line"> },</span><br><span class="line"> { <span class="attr">urls</span>: [<span class="string">"<all_urls>"</span>] },</span><br><span class="line"> [<span class="string">"extraHeaders"</span>, <span class="string">"responseHeaders"</span>]</span><br><span class="line">);</span><br></pre></td></tr></table></figure><p>上面示例中提到,使用 webRequestAPI 是无法拿到 responseBody 的,想要拿到的话只能采取一些变通方法,例如:</p><ul><li>重写 XmlHttpRequest 和 fetch,增加自定义拦截事件,缺点是实现方式可能有点脏,重写不好的话可能影响正常页面。</li><li>devtools 的 chrome.devtools.network.onRequestFinishedAPI 可以拿到返回的 body,缺点是必须打开开发者面板。</li><li>使用 chrome.debugger.sendCommand 发送 Network.getResponseBody 命令来获取 body 内容,缺点也很明显,会有一个恼人的提示。</li></ul><blockquote><p>具体的实现方式可以查看<a href="https://stackoverflow.com/questions/18534771/chrome-extension-how-to-get-http-response-body">https://stackoverflow.com/questions/18534771/chrome-extension-how-to-get-http-response-body</a></p></blockquote><h3 id="国际化"><a href="#国际化" class="headerlink" title="国际化"></a>国际化</h3><p>插件根目录新建一个名为_locales 的文件夹,再在下面新建一些语言的文件夹,如 en、zh_CN、zh_TW,然后再在每个文件夹放入一个 messages.json,同时必须在清单文件中设置 default_locale。</p><ul><li>_locales\en\messages.json:</li></ul><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></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"pluginDesc"</span>: { <span class="attr">"message"</span>: <span class="string">"A chrome extension demo"</span> },</span><br><span class="line"> <span class="attr">"helloWorld"</span>: { <span class="attr">"message"</span>: <span class="string">"Hello World!"</span> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>_locales\zh_CN\messages.json:</li></ul><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></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"pluginDesc"</span>: { <span class="attr">"message"</span>: <span class="string">"一个Chrome插件demo"</span> },</span><br><span class="line"> <span class="attr">"helloWorld"</span>: { <span class="attr">"message"</span>: <span class="string">"你好,世界!"</span> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>在 manifest.json 和 CSS 文件中通过<strong>MSG_messagename</strong>引入,如:</li></ul><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></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"description"</span>: <span class="string">"__MSG_pluginDesc__"</span>,</span><br><span class="line"> <span class="comment">// 默认语言</span></span><br><span class="line"> <span class="attr">"default_locale"</span>: <span class="string">"zh_CN"</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>在 JS 中则直接 chrome.i18n.getMessage(“helloWorld”)。</li><li>测试时,通过给 chrome 建立一个不同的快捷方式 chrome.exe –lang=en 来切换语言</li></ul><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/i18n.png"></p><h2 id="常见的-API"><a href="#常见的-API" class="headerlink" title="常见的 API"></a>常见的 API</h2><p>所有的 Chrome API 都是以 chrome 对象开头,🌰 如:chrome.tabs</p><ul><li>bookmarks 操纵书签的 API</li><li>browserAction 获取扩展图标、标题、文字、弹出页等</li><li>browsingData 控制浏览器的浏览数据,从本地文件</li><li>commands 给扩展添加快捷键</li><li>contextMenus 添加选项到右键弹出菜单</li><li>cookies 控制 cookies</li><li>desktopCapture 捕获屏幕、个人窗口或标签内容</li><li>downloads 下载控制</li><li>events 事件相关 API</li><li>extension 获取扩展的各部分,也能与各部分交换信息</li><li>extensionTypes 扩展的类型声明</li><li>gcm 启用 google 云消息服务,收发消息</li><li>history 历史记录控制</li><li>i18n 多语言国际化支持</li><li>idle 取得机器闲置状态</li><li>management 管理扩展与应用</li><li>notifications 通知控制</li><li>pageAction 具体的页面下控制扩展图标、标题、文字、弹出页等相关内容</li><li>permissions 获取拥有的权限</li><li>power 请求系统常亮</li><li>runtime 获取运行时相关信息,包括后台页、manifest 等等</li><li>sessions 查询或恢复浏览会话</li><li>storage 存储相关</li><li>tabs 与标签页交互</li><li>vpnProvider 实现 vpn 客户端需要使用的东西</li><li>webRequest 拦截、修改、阻塞请求</li><li>windows 创建、修改、重排窗口</li></ul><hr><h2 id="踩坑"><a href="#踩坑" class="headerlink" title="踩坑"></a>踩坑</h2><h3 id="查看已安装插件路径"><a href="#查看已安装插件路径" class="headerlink" title="查看已安装插件路径"></a>查看已安装插件路径</h3><p>查看本地已安装的插件源码路径 C:\Users\用户名\AppData\Local\Google\Chrome\User Data\Default\Extensions,每一个插件被放在以插件 ID 为名的文件夹里面,想要学习某个插件的某个功能是如何实现的,看人家的源码是最好的方法了。</p><blockquote><p>Mac 系统插件本地缓存位于:/Users/用户名/Library/Application Support/Google/Chrome/Default/Extensions 文件夹</p></blockquote><p>如何查看某个插件的 ID?进入 chrome://extensions ,然后勾选开发者模式即可看到了。</p><h3 id="background-的报错"><a href="#background-的报错" class="headerlink" title="background 的报错"></a>background 的报错</h3><p>很多时候你发现你的代码会莫名其妙的失效,找来找去又找不到原因,这时打开 background 的控制台才发现原来某个地方写错了导致代码没生效,这是由于 background 报错的隐蔽性(需要主动打开对应的控制台才能看到错误)</p><h3 id="如何让-popup-页面不关闭"><a href="#如何让-popup-页面不关闭" class="headerlink" title="如何让 popup 页面不关闭"></a>如何让 popup 页面不关闭</h3><p>在对 popup 页面审查元素的时候 popup 会被强制打开无法关闭,只有控制台关闭了才可以关闭 popup,原因很简单:如果 popup 关闭了控制台就没用了。这种方法在某些情况下很实用!</p><h3 id="不支持内联-JavaScript-的执行"><a href="#不支持内联-JavaScript-的执行" class="headerlink" title="不支持内联 JavaScript 的执行"></a>不支持内联 JavaScript 的执行</h3><p>就是不支持将 js 直接写在 html 中,例如 🌰:</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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">input</span> <span class="attr">id</span>=<span class="string">"btn"</span> <span class="attr">type</span>=<span class="string">"button"</span> <span class="attr">value</span>=<span class="string">"按钮"</span> <span class="attr">onclick</span>=<span class="string">"handleBtn()"</span> /></span></span><br><span class="line"></span><br><span class="line">// 报错 // Refused to execute inline event handler because it violates the</span><br><span class="line">following Content Security Policy directive: "script-src 'self' blob:</span><br><span class="line">filesystem: chrome-extension-resource:". Either the 'unsafe-inline' keyword, a</span><br><span class="line">hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline</span><br><span class="line">execution.</span><br></pre></td></tr></table></figure><p>只能通过 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></pre></td><td class="code"><pre><span class="line">$(<span class="string">"#btn"</span>).on(<span class="string">"click"</span>, <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> alert(<span class="string">"测试"</span>);</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>另外,对于 A 标签,这样写 href=”javascript:;”然后用 JS 绑定事件虽然控制台会报错,但是不受影响,当然强迫症患者受不了的话只能写成 href=”#”了。</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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"javascript:;"</span> <span class="attr">id</span>=<span class="string">"get_res"</span>></span>请求<span class="tag"></<span class="name">a</span>></span></span><br><span class="line"></span><br><span class="line">// 报错 // Refused to execute JavaScript URL because it violates the following</span><br><span class="line">Content Security Policy directive: "script-src 'self' blob: filesystem:</span><br><span class="line">chrome-extension-resource:". Either the 'unsafe-inline' keyword, a hash</span><br><span class="line">('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.</span><br></pre></td></tr></table></figure><h3 id="注入-CSS"><a href="#注入-CSS" class="headerlink" title="注入 CSS"></a>注入 CSS</h3><p>由于通过 content_scripts 注入的 CSS 优先级非常高,几乎仅次于浏览器默认样式,稍不注意可能就会影响一些网站的展示效果,所以尽量不要写一些影响全局的样式。</p><blockquote><p>之所以强调这个,是因为这个带来的问题非常隐蔽,不太容易找到,可能你正在写某个网页,昨天样式还是好好的,怎么今天就突然不行了?然后你辛辛苦苦找来找去,找了半天才发现竟然是因为插件里面的一个样式影响的!</p></blockquote><hr><p>原文:<a href="http://blog.haoji.me/chrome-plugin-develop.html#dong-tai-zhu-ru-huo-zhi-xing-JS">http://blog.haoji.me/chrome-plugin-develop.html#dong-tai-zhu-ru-huo-zhi-xing-JS</a></p><h2 id="相关资料:"><a href="#相关资料:" class="headerlink" title="相关资料:"></a>相关资料:</h2><div class="btns rounded grid5"> <a class="button" href='http://open.se.360.cn/open/extension_dev/overview.html' title='360安全浏览器开发文档(推荐)'><i class='fas fa-book-open'></i>360安全浏览器开发文档(推荐)</a><a class="button" href='http://open.chrome.360.cn/extension_dev/overview.html' title='360极速浏览器Chrome扩展开发文档'><i class='fas fa-book-open'></i>360极速浏览器Chrome扩展开发文档</a><a class="button" href='https://www.cnblogs.com/champagne/p/' title='Chrome扩展开发极客'><i class='fas fa-book-open'></i>Chrome扩展开发极客</a><a class="button" href='https://developer.chrome.com/extensions' title='chrome扩展开发官方文档(需要翻墙)'><i class='fas fa-book-open'></i>chrome扩展开发官方文档(需要翻墙)</a><a class="button" href='https://developer.chrome.com/extensions/api_index' title='chrome API支持(需要翻墙)'><i class='fas fa-book-open'></i>chrome API支持(需要翻墙)</a> </div>]]></content>
<summary type="html"><h2 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h2><h3 id="chrome-扩展是什么?"><a href="#chrome-扩展是什么?" class="headerlink</summary>
<category term="Chrome" scheme="http://imagineblog.host/categories/Chrome/"/>
<category term="javascript" scheme="http://imagineblog.host/tags/javascript/"/>
<category term="Chrome" scheme="http://imagineblog.host/tags/Chrome/"/>
</entry>
<entry>
<title>async/await</title>
<link href="http://imagineblog.host/ilr5wg/"/>
<id>http://imagineblog.host/ilr5wg/</id>
<published>2021-05-10T07:29:03.000Z</published>
<updated>2022-08-31T08:04:19.377Z</updated>
<content type="html"><![CDATA[<p>JavaScript 中的 async/await 是 AsyncFunction 特性 中的关键字。目前为止,除了 IE 之外,常用浏览器和 Node (v7.6+) 都已经支持该特性。具体支持情况可以在<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncFunction#Browser_compatibility">这里</a>查看。</p><h2 id="async-和-await-在干什么"><a href="#async-和-await-在干什么" class="headerlink" title="async 和 await 在干什么"></a>async 和 await 在干什么</h2><p>任意一个名称都是有意义的,先从字面意思来理解。async 是“异步”的简写,而 await 可以认为是 async wait 的简写。所以应该很好理解 async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。</p><p>另外还有一个很有意思的语法规定,await 只能出现在 async 函数中。然后细心的朋友会产生一个疑问,如果 await 只能出现在 async 函数中,那这个 async 函数应该怎么调用?</p><p>如果需要通过 await 来调用一个 async 函数,那这个调用的外面必须得再包一个 async 函数,然后……进入死循环,永无出头之日……</p><p>如果 async 函数不需要 await 来调用,那 async 到底起个啥作用?</p><h3 id="async-起什么作用"><a href="#async-起什么作用" class="headerlink" title="async 起什么作用"></a>async 起什么作用</h3><p>这个问题的关键在于,async 函数是怎么处理它的返回值的!</p><p>我们当然希望它能直接通过 return 语句返回我们想要的值,但是如果真是这样,似乎就没 await 什么事了。所以,写段代码来试试,看它到底会返回什么:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">testAsync</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"hello async"</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> result = testAsync();</span><br><span class="line"><span class="built_in">console</span>.log(result);</span><br></pre></td></tr></table></figure><p>看到输出就恍然大悟了——输出的是一个 Promise 对象。</p><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/async_log.png"></p><p>所以,async 函数返回的是一个 Promise 对象。从<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/async_function">文档</a>中也可以得到这个信息。async 函数(包含函数语句、函数表达式、Lambda 表达式)会返回一个 Promise 对象,如果在函数中 return 一个直接量,async 会把这个直接量通过 Promise.resolve() 封装成 Promise 对象。</p><p>Promise.resolve(x)可以看作是 new Promise(resolve => resolve(x))的简写,可以用于快速封装字面量对象或其他对象,将其封装成 Promise 实例。</p><p>async 函数返回的是一个 Promise 对象,所以在最外层不能用 await 获取其返回值的情况下,我们当然应该用原来的方式:then()链来处理这个 Promise 对象,就像这样</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">testAsync().then(<span class="function">(<span class="params">v</span>) =></span> {</span><br><span class="line"> <span class="built_in">console</span>.log(v); <span class="comment">// 输出 hello async</span></span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>现在回过头来想下,如果 async 函数没有返回值,又该如何?很容易想到,它会返回 Promise.resolve(undefined)。</p><p>联想一下 Promise 的特点——无等待,所以在没有 await 的情况下执行 async 函数,它会立即执行,返回一个 Promise 对象,并且,绝不会阻塞后面的语句。这和普通返回 Promise 对象的函数并无二致。</p><p>那么下一个关键点就在于 await 关键字了。</p><h3 id="await-到底在等啥"><a href="#await-到底在等啥" class="headerlink" title="await 到底在等啥"></a>await 到底在等啥</h3><p>一般来说,都认为 await 是在等待一个 async 函数完成。不过按语法说明,await 等待的是一个表达式,这个表达式的计算结果是 Promise 对象或者其它值(换句话说,就是没有特殊限定)。</p><p>因为 async 函数返回一个 Promise 对象,所以 await 可以用于等待一个 async 函数的返回值——这也可以说是 await 在等 async 函数,但要清楚,它等的实际是一个返回值。注意到 await 不仅仅用于等 Promise 对象,它可以等任意表达式的结果,所以,await 后面实际是可以接普通函数调用或者直接量的。所以下面这个示例完全可以正确运行</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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getSomething</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"something"</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">testAsync</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Promise</span>.resolve(<span class="string">"hello async"</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">test</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> v1 = <span class="keyword">await</span> getSomething();</span><br><span class="line"> <span class="keyword">const</span> v2 = <span class="keyword">await</span> testAsync();</span><br><span class="line"> <span class="built_in">console</span>.log(v1, v2);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">test();</span><br></pre></td></tr></table></figure><h3 id="await-等到了要等的,然后呢"><a href="#await-等到了要等的,然后呢" class="headerlink" title="await 等到了要等的,然后呢"></a>await 等到了要等的,然后呢</h3><p>await 等到了它要等的东西,一个 Promise 对象,或者其它值,然后呢?我不得不先说,await 是个运算符,用于组成表达式,await 表达式的运算结果取决于它等的东西。</p><p>如果它等到的不是一个 Promise 对象,那 await 表达式的运算结果就是它等到的东西。</p><p>如果它等到的是一个 Promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。</p><p>看到上面的阻塞一词,心慌了吧……放心,这就是 await 必须用在 async 函数中的原因。async 函数调用不会造成阻塞,它内部所有的阻塞都被封装在一个 Promise 对象中异步执行。</p><hr><h2 id="async-await-帮我们干了啥"><a href="#async-await-帮我们干了啥" class="headerlink" title="async/await 帮我们干了啥"></a>async/await 帮我们干了啥</h2><h3 id="作个简单的比较"><a href="#作个简单的比较" class="headerlink" title="作个简单的比较"></a>作个简单的比较</h3><p>上面已经说明了 async 会将其后的函数(函数表达式或 Lambda)的返回值封装成一个 Promise 对象,而 await 会等待这个 Promise 完成,并将其 resolve 的结果返回出来。</p><p>现在举例 🌰,用 setTimeout 模拟耗时的异步操作,先来看看不用 async/await 会怎么写</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">takeLongTime</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve</span>) =></span> {</span><br><span class="line"> <span class="built_in">setTimeout</span>(<span class="function">() =></span> resolve(<span class="string">"long_time_value"</span>), <span class="number">1000</span>);</span><br><span class="line"> });</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">takeLongTime().then(<span class="function">(<span class="params">v</span>) =></span> {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"got"</span>, v);</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>如果改用 async/await 呢,会是这样</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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">takeLongTime</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve</span>) =></span> {</span><br><span class="line"> <span class="built_in">setTimeout</span>(<span class="function">() =></span> resolve(<span class="string">"long_time_value"</span>), <span class="number">1000</span>);</span><br><span class="line"> });</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">test</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> v = <span class="keyword">await</span> takeLongTime();</span><br><span class="line"> <span class="built_in">console</span>.log(v);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">test();</span><br></pre></td></tr></table></figure><p>眼尖的同学已经发现 takeLongTime() 没有申明为 async。实际上,takeLongTime() 本身就是返回的 Promise 对象,加不加 async 结果都一样,如果没明白,请回过头再去看看上面的“async 起什么作用”。</p><p>又一个疑问产生了,这两段代码,两种方式对异步调用的处理(实际就是对 Promise 对象的处理)差别并不明显,甚至使用 async/await 还需要多写一些代码,那它的优势到底在哪?</p><h3 id="async-await-的优势在于处理-then-链"><a href="#async-await-的优势在于处理-then-链" class="headerlink" title="async/await 的优势在于处理 then 链"></a>async/await 的优势在于处理 then 链</h3><p>单一的 Promise 链并不能发现 async/await 的优势,但是,如果需要处理由多个 Promise 组成的 then 链的时候,优势就能体现出来了(很有意思,Promise 通过 then 链来解决多层回调的问题,现在又用 async/await 来进一步优化它)。</p><p>假设一个业务,分多个步骤完成,每个步骤都是异步的,而且依赖于上一个步骤的结果。我们仍然用 setTimeout 来模拟异步操作:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 传入参数 n,表示这个函数执行的时间(毫秒)</span></span><br><span class="line"><span class="comment"> * 执行的结果是 n + 200,这个值将用于下一步骤</span></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">takeLongTime</span>(<span class="params">n</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve</span>) =></span> {</span><br><span class="line"> <span class="built_in">setTimeout</span>(<span class="function">() =></span> resolve(n + <span class="number">200</span>), n);</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">step1</span>(<span class="params">n</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`step1 with <span class="subst">${n}</span>`</span>);</span><br><span class="line"> <span class="keyword">return</span> takeLongTime(n);</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">step2</span>(<span class="params">n</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`step2 with <span class="subst">${n}</span>`</span>);</span><br><span class="line"> <span class="keyword">return</span> takeLongTime(n);</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">step3</span>(<span class="params">n</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`step3 with <span class="subst">${n}</span>`</span>);</span><br><span class="line"> <span class="keyword">return</span> takeLongTime(n);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>现在用 Promise 方式来实现这三个步骤的处理</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">doIt</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.time(<span class="string">"doIt"</span>);</span><br><span class="line"> <span class="keyword">const</span> time1 = <span class="number">300</span>;</span><br><span class="line"> step1(time1)</span><br><span class="line"> .then(<span class="function">(<span class="params">time2</span>) =></span> step2(time2))</span><br><span class="line"> .then(<span class="function">(<span class="params">time3</span>) =></span> step3(time3))</span><br><span class="line"> .then(<span class="function">(<span class="params">result</span>) =></span> {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`result is <span class="subst">${result}</span>`</span>);</span><br><span class="line"> <span class="built_in">console</span>.timeEnd(<span class="string">"doIt"</span>);</span><br><span class="line"> });</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">doIt();</span><br><span class="line"></span><br><span class="line"><span class="comment">// c:\var\test>node --harmony_async_await .</span></span><br><span class="line"><span class="comment">// step1 with 300</span></span><br><span class="line"><span class="comment">// step2 with 500</span></span><br><span class="line"><span class="comment">// step3 with 700</span></span><br><span class="line"><span class="comment">// result is 900</span></span><br><span class="line"><span class="comment">// doIt: 1507.251ms</span></span><br></pre></td></tr></table></figure><p>输出结果 result 是 step3()的参数 700 + 200 = 900。doIt()顺序执行了三个步骤,一共用了 300 + 500 + 700 = 1500 毫秒,和 console.time()/console.timeEnd()计算的结果一致。</p><p>如果用 async/await 来实现呢,会是这样</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">async</span> <span class="function"><span class="keyword">function</span> <span class="title">doIt</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.time(<span class="string">"doIt"</span>);</span><br><span class="line"> <span class="keyword">const</span> time1 = <span class="number">300</span>;</span><br><span class="line"> <span class="keyword">const</span> time2 = <span class="keyword">await</span> step1(time1);</span><br><span class="line"> <span class="keyword">const</span> time3 = <span class="keyword">await</span> step2(time2);</span><br><span class="line"> <span class="keyword">const</span> result = <span class="keyword">await</span> step3(time3);</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`result is <span class="subst">${result}</span>`</span>);</span><br><span class="line"> <span class="built_in">console</span>.timeEnd(<span class="string">"doIt"</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">doIt();</span><br></pre></td></tr></table></figure><p>结果和之前的 Promise 实现是一样的,但是这个代码看起来是不是清晰得多,几乎跟同步代码一样</p><h3 id="还有更酷的"><a href="#还有更酷的" class="headerlink" title="还有更酷的"></a>还有更酷的</h3><p>现在把业务要求改一下,仍然是三个步骤,但每一个步骤都需要之前每个步骤的结果。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><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="function"><span class="keyword">function</span> <span class="title">step1</span>(<span class="params">n</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`step1 with <span class="subst">${n}</span>`</span>);</span><br><span class="line"> <span class="keyword">return</span> takeLongTime(n);</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">step2</span>(<span class="params">m, n</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`step2 with <span class="subst">${m}</span> and <span class="subst">${n}</span>`</span>);</span><br><span class="line"> <span class="keyword">return</span> takeLongTime(m + n);</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">step3</span>(<span class="params">k, m, n</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`step3 with <span class="subst">${k}</span>, <span class="subst">${m}</span> and <span class="subst">${n}</span>`</span>);</span><br><span class="line"> <span class="keyword">return</span> takeLongTime(k + m + n);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>这回先用 async/await 来写:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">doIt</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.time(<span class="string">"doIt"</span>);</span><br><span class="line"> <span class="keyword">const</span> time1 = <span class="number">300</span>;</span><br><span class="line"> <span class="keyword">const</span> time2 = <span class="keyword">await</span> step1(time1);</span><br><span class="line"> <span class="keyword">const</span> time3 = <span class="keyword">await</span> step2(time1, time2);</span><br><span class="line"> <span class="keyword">const</span> result = <span class="keyword">await</span> step3(time1, time2, time3);</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`result is <span class="subst">${result}</span>`</span>);</span><br><span class="line"> <span class="built_in">console</span>.timeEnd(<span class="string">"doIt"</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">doIt();</span><br><span class="line"></span><br><span class="line"><span class="comment">// c:\var\test>node --harmony_async_await .</span></span><br><span class="line"><span class="comment">// step1 with 300</span></span><br><span class="line"><span class="comment">// step2 with 800 = 300 + 500</span></span><br><span class="line"><span class="comment">// step3 with 1800 = 300 + 500 + 1000</span></span><br><span class="line"><span class="comment">// result is 2000</span></span><br><span class="line"><span class="comment">// doIt: 2907.387ms</span></span><br></pre></td></tr></table></figure><p>除了觉得执行时间变长了之外,似乎和之前的示例没啥区别啊!别急,认真想想如果把它写成 Promise 方式实现会是什么样子?</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">doIt</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.time(<span class="string">"doIt"</span>);</span><br><span class="line"> <span class="keyword">const</span> time1 = <span class="number">300</span>;</span><br><span class="line"> step1(time1)</span><br><span class="line"> .then(<span class="function">(<span class="params">time2</span>) =></span> {</span><br><span class="line"> <span class="keyword">return</span> step2(time1, time2).then(<span class="function">(<span class="params">time3</span>) =></span> [time1, time2, time3]);</span><br><span class="line"> })</span><br><span class="line"> .then(<span class="function">(<span class="params">times</span>) =></span> {</span><br><span class="line"> <span class="keyword">const</span> [time1, time2, time3] = times;</span><br><span class="line"> <span class="keyword">return</span> step3(time1, time2, time3);</span><br><span class="line"> })</span><br><span class="line"> .then(<span class="function">(<span class="params">result</span>) =></span> {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`result is <span class="subst">${result}</span>`</span>);</span><br><span class="line"> <span class="built_in">console</span>.timeEnd(<span class="string">"doIt"</span>);</span><br><span class="line"> });</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">doIt();</span><br></pre></td></tr></table></figure><p>转载自:<a href="https://segmentfault.com/u/jamesfancy">边城</a>的<a href="https://segmentfault.com/a/1190000007535316">理解 JavaScript 的 async/await</a><br>相关文章:<br><a href="https://segmentfault.com/a/1190000021966277">在微信小程序中使用 async/await</a><br><a href="https://segmentfault.com/a/1190000022349639">代码审查,异步调用的常见问题剖析</a><br><a href="https://segmentfault.com/a/1190000022315137">Proxy 封装微信小程序的异步调用</a><br><a href="https://segmentfault.com/a/1190000022467002">改进异步封装:处理带返回值的异步调用</a><br><a href="https://segmentfault.com/a/1190000011802045">从不用 try-catch 实现的 async/await 语法说错误处理</a></p>]]></content>
<summary type="html"><p>JavaScript 中的 async/await 是 AsyncFunction 特性 中的关键字。目前为止,除了 IE 之外,常用浏览器和 Node (v7.6+) 都已经支持该特性。具体支持情况可以在<a href="https://developer.mozilla</summary>
<category term="ES6" scheme="http://imagineblog.host/categories/ES6/"/>
<category term="ES6" scheme="http://imagineblog.host/tags/ES6/"/>
</entry>
<entry>
<title>Axios 封装</title>
<link href="http://imagineblog.host/zw2gqe/"/>
<id>http://imagineblog.host/zw2gqe/</id>
<published>2021-05-09T03:18:01.000Z</published>
<updated>2022-08-31T08:04:19.377Z</updated>
<content type="html"><![CDATA[<h2 id="axios-的封装"><a href="#axios-的封装" class="headerlink" title="axios 的封装"></a>axios 的封装</h2><p>在 vue 项目中,和后台交互获取数据这块,我们通常使用的是 axios 库,它是基于 promise 的 http 库,可运行在浏览器端和 node.js 中。他有很多优秀的特性,例如拦截请求和响应、取消请求、转换 json、客户端防御 XSRF 等。所以我们的尤大大也是果断放弃了对其官方库<a href="https://www.runoob.com/vue2/vuejs-ajax.html">vue-resource</a>的维护,直接推荐我们使用 axios 库。如果还对 axios 不了解的,可以移步<a href="http://www.axios-js.com/">axios 文档</a>。</p><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install axios; <span class="comment">// 安装axios</span></span><br></pre></td></tr></table></figure><h3 id="引入"><a href="#引入" class="headerlink" title="引入"></a>引入</h3><p>在项目的 src 目录中,新建一个 request 文件夹,然后在里面新建一个 http.js 和一个 api.js 文件。http.js 文件用来封装我们的 axios,api.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><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 在http.js中引入axios</span></span><br><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">"axios"</span>; <span class="comment">// 引入axios</span></span><br><span class="line"><span class="keyword">import</span> QS <span class="keyword">from</span> <span class="string">"qs"</span>; <span class="comment">// 引入qs模块,用来序列化post类型的数据</span></span><br><span class="line"><span class="comment">// element的message提示框组件,可根据自己的ui组件更改。</span></span><br><span class="line"><span class="keyword">import</span> { Message } <span class="keyword">from</span> <span class="string">"element-ui"</span>;</span><br></pre></td></tr></table></figure><h3 id="环境的切换"><a href="#环境的切换" class="headerlink" title="环境的切换"></a>环境的切换</h3><p>项目环境可能有开发环境、测试环境和生产环境。需要通过 node 的环境变量来匹配默认的接口 url 前缀。axios.defaults.baseURL 可以设置 axios 的默认请求地址。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 环境的切换</span></span><br><span class="line"><span class="keyword">if</span> (process.env.NODE_ENV == <span class="string">"development"</span>) {</span><br><span class="line"> <span class="comment">// 生产环境</span></span><br><span class="line"> axios.defaults.baseURL = <span class="string">"https://www.baidu.com"</span>;</span><br><span class="line">} <span class="keyword">else</span> <span class="keyword">if</span> (process.env.NODE_ENV == <span class="string">"test"</span>) {</span><br><span class="line"> <span class="comment">// 测试环境</span></span><br><span class="line"> axios.defaults.baseURL = <span class="string">"https://www.ceshi.com"</span>;</span><br><span class="line">} <span class="keyword">else</span> <span class="keyword">if</span> (process.env.NODE_ENV == <span class="string">"production"</span>) {</span><br><span class="line"> <span class="comment">// 正式环境</span></span><br><span class="line"> axios.defaults.baseURL = <span class="string">"https://www.production.com"</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="设置请求超时"><a href="#设置请求超时" class="headerlink" title="设置请求超时"></a>设置请求超时</h3><p>通过 axios.defaults.timeout 设置默认的请求超时时间。例如超过了 5s,就会告知用户当前请求超时,请刷新等。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">axios.defaults.timeout = <span class="number">5000</span>;</span><br></pre></td></tr></table></figure><h3 id="post-请求头的设置"><a href="#post-请求头的设置" class="headerlink" title="post 请求头的设置"></a>post 请求头的设置</h3><p>post 请求的时候,我们需要加上一个请求头,所以可以在这里进行一个默认的设置,即设置 post 的请求头为 application/x-www-form-urlencoded;charset=UTF-8</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">axios.defaults.headers.post[<span class="string">"Content-Type"</span>] =</span><br><span class="line"> <span class="string">"application/x-www-form-urlencoded;charset=UTF-8"</span>;</span><br></pre></td></tr></table></figure><h3 id="请求拦截器"><a href="#请求拦截器" class="headerlink" title="请求拦截器"></a>请求拦截器</h3><p>我们在发送请求前可以进行一个请求的拦截,为什么要拦截呢,我们拦截请求是用来做什么的呢?比如,有些请求是需要用户登录之后才能访问的,或者 post 请求的时候,我们需要序列化我们提交的数据。这时候,我们可以在请求被发送之前进行一个拦截,从而进行我们想要的操作。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 先导入vuex,因为我们要使用到里面的状态对象</span></span><br><span class="line"><span class="comment">// vuex的路径根据自己的路径去写</span></span><br><span class="line"><span class="keyword">import</span> store <span class="keyword">from</span> <span class="string">"@/store/index"</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 请求拦截器</span></span><br><span class="line">axios.interceptors.request.use(</span><br><span class="line"> (config) => {</span><br><span class="line"> <span class="comment">// 每次发送请求之前判断vuex中是否存在token</span></span><br><span class="line"> <span class="comment">// 如果存在,则统一在http请求的header都加上token,这样后台根据token判断你的登录情况</span></span><br><span class="line"> <span class="comment">// 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断</span></span><br><span class="line"> <span class="keyword">const</span> token = store.state.token;</span><br><span class="line"> token && (config.headers.Authorization = token);</span><br><span class="line"> <span class="keyword">return</span> config;</span><br><span class="line"> },</span><br><span class="line"> (error) => {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Promise</span>.error(error);</span><br><span class="line"> }</span><br><span class="line">);</span><br></pre></td></tr></table></figure><div class="note info modern"><p>这里说一下 token,一般是在登录完成之后,将用户的 token 通过 localStorage 或者 cookie 存在本地,然后用户每次在进入页面的时候(即在 main.js 中),会首先从本地存储中读取 token,如果 token 存在说明用户已经登陆过,则更新 vuex 中的 token 状态。然后,在每次请求接口的时候,都会在请求的 header 中携带 token,后台人员就可以根据你携带的 token 来判断你的登录是否过期,如果没有携带,则说明没有登录过。</p></div><h3 id="响应拦截器"><a href="#响应拦截器" class="headerlink" title="响应拦截器"></a>响应拦截器</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 响应拦截器</span></span><br><span class="line">axios.interceptors.response.use(</span><br><span class="line"> response => {</span><br><span class="line"> <span class="comment">// 如果返回的状态码为200,说明接口请求成功,可以正常拿到数据</span></span><br><span class="line"> <span class="comment">// 否则的话抛出错误</span></span><br><span class="line"> <span class="keyword">if</span> (response.status === <span class="number">200</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Promise</span>.resolve(response);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Promise</span>.reject(response);</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// 服务器状态码不是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"> error => {</span><br><span class="line"> <span class="keyword">if</span> (error.response.status) {</span><br><span class="line"> <span class="keyword">switch</span> (error.response.status) {</span><br><span class="line"> <span class="comment">// 401: 未登录</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="keyword">case</span> <span class="number">401</span>:</span><br><span class="line"> router.replace({</span><br><span class="line"> path: <span class="string">'/login'</span>,</span><br><span class="line"> query: {</span><br><span class="line"> redirect: router.currentRoute.fullPath</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 403 token过期</span></span><br><span class="line"> <span class="comment">// 登录过期对用户进行提示</span></span><br><span class="line"> <span class="comment">// 清除本地token和清空vuex中token对象</span></span><br><span class="line"> <span class="comment">// 跳转登录页面</span></span><br><span class="line"> <span class="keyword">case</span> <span class="number">403</span>:</span><br><span class="line"> Message({</span><br><span class="line"> message: <span class="string">'登录过期,请重新登录'</span>,</span><br><span class="line"> type:<span class="string">'error'</span>,</span><br><span class="line"> duration: <span class="number">1000</span>,</span><br><span class="line"> });</span><br><span class="line"> <span class="comment">// 清除token</span></span><br><span class="line"> <span class="built_in">localStorage</span>.removeItem(<span class="string">'token'</span>);</span><br><span class="line"> store.commit(<span class="string">'loginSuccess'</span>, <span class="literal">null</span>);</span><br><span class="line"> <span class="comment">// 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面</span></span><br><span class="line"> <span class="built_in">setTimeout</span>(<span class="function">() =></span> {</span><br><span class="line"> router.replace({</span><br><span class="line"> path: <span class="string">'/login'</span>,</span><br><span class="line"> query: {</span><br><span class="line"> redirect: router.currentRoute.fullPath</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"> }, <span class="number">1000</span>);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 404请求不存在</span></span><br><span class="line"> <span class="keyword">case</span> <span class="number">404</span>:</span><br><span class="line"> Message({</span><br><span class="line"> message: <span class="string">'网络请求不存在'</span>,</span><br><span class="line"> type:<span class="string">'error'</span>,</span><br><span class="line"> duration: <span class="number">1500</span>,</span><br><span class="line"></span><br><span class="line"> });</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="comment">// 其他错误,直接抛出错误提示</span></span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> Message({</span><br><span class="line"> message: error.response.data.message,</span><br><span class="line"> type: <span class="string">'error'</span>,</span><br><span class="line"> duration: <span class="number">1500</span></span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Promise</span>.reject(error.response);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>响应拦截器很好理解,就是服务器返回给我们的数据,我们在拿到之前可以对他进行一些处理。例如上面的思想:如果后台返回的状态码是 200,则正常返回数据,否则的根据错误的状态码类型进行一些我们需要的错误,其实这里主要就是进行了错误的统一处理和没登录或登录过期后调整登录页的一个操作。</p><h3 id="封装-get-方法和-post-方法"><a href="#封装-get-方法和-post-方法" class="headerlink" title="封装 get 方法和 post 方法"></a>封装 get 方法和 post 方法</h3><p>我们常用的 ajax 请求方法有 get、post、put 等方法。axios 对应的也有很多类似的方法,不清楚的可以看下文档。但是为了简化我们的代码,我们还是要对其进行一个简单的封装。下面我们主要封装两个方法:get 和 post。</p><ul><li>get 方法:<br>我们通过定义一个 get 函数,get 函数有两个参数,第一个参数表示我们要请求的 url 地址,第二个参数是我们要携带的请求参数。get 函数返回一个 promise 对象,当 axios 其请求成功时 resolve 服务器返回 值,请求失败时 reject 错误值。最后通过 export 抛出 get 函数。</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * get方法,对应get请求</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">{String}</span> </span>url [请求的url地址]</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">{Object}</span> </span>params [请求时携带的参数]</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">export</span> <span class="function"><span class="keyword">function</span> <span class="title">get</span>(<span class="params">url, params</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</span><br><span class="line"> axios</span><br><span class="line"> .get(url, {</span><br><span class="line"> params: params,</span><br><span class="line"> })</span><br><span class="line"> .then(<span class="function">(<span class="params">res</span>) =></span> {</span><br><span class="line"> resolve(res.data);</span><br><span class="line"> })</span><br><span class="line"> .catch(<span class="function">(<span class="params">err</span>) =></span> {</span><br><span class="line"> reject(err.data);</span><br><span class="line"> });</span><br><span class="line"> });</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>post 方法:<br>原理同 get 基本一样,但是要注意的是,post 方法必须要使用对提交从参数对象进行序列化的操作,所以这里我们通过 node 的 qs 模块来序列化我们的参数。这个很重要,如果没有序列化操作,后台是拿不到你提交的数据的。这就是文章开头我们 import QS from ‘qs’的原因。</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * post方法,对应post请求</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">{String}</span> </span>url [请求的url地址]</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">{Object}</span> </span>params [请求时携带的参数]</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">export</span> <span class="function"><span class="keyword">function</span> <span class="title">post</span>(<span class="params">url, params</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</span><br><span class="line"> axios</span><br><span class="line"> .post(url, QS.stringify(params))</span><br><span class="line"> .then(<span class="function">(<span class="params">res</span>) =></span> {</span><br><span class="line"> resolve(res.data);</span><br><span class="line"> })</span><br><span class="line"> .catch(<span class="function">(<span class="params">err</span>) =></span> {</span><br><span class="line"> reject(err.data);</span><br><span class="line"> });</span><br><span class="line"> });</span><br><span class="line">}</span><br></pre></td></tr></table></figure><blockquote><p>这里有个小细节说下,axios.get()方法和 axios.post()在提交数据时参数的书写方式还是有区别的。区别就是,get 的第二个参数是一个{},然后这个对象的 params 属性值是一个参数对象的。而 post 的第二个参数就是一个参数对象。</p></blockquote><h3 id="api-接口统一管理"><a href="#api-接口统一管理" class="headerlink" title="api 接口统一管理"></a>api 接口统一管理</h3><p>在 api.js 中引入封装的 get 和 post 方法</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="comment">/**</span></span><br><span class="line"><span class="comment"> * api接口统一管理</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">import</span> { get, post } <span class="keyword">from</span> <span class="string">"./http"</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> Login = <span class="function">(<span class="params">data</span>) =></span> post(<span class="string">"api/v1/login"</span>, data);</span><br></pre></td></tr></table></figure><p>我们定义了一个 Login 方法,这个方法有一个参数 data,data 是我们请求接口时携带的参数对象。而后调用了我们封装的 post 方法,post 方法的第一个参数是我们的接口地址,第二个参数是 Login 的 data 参数,即请求接口时携带的参数对象。最后通过 export 导出 Login。</p><p>然后在我们的页面中可以这样调用我们的 api 接口:</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> { apiAddress } <span class="keyword">from</span> <span class="string">"@/request/api"</span>; <span class="comment">// 导入我们的api接口</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> {</span><br><span class="line"> name: <span class="string">"Address"</span>,</span><br><span class="line"> <span class="function"><span class="title">created</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="built_in">this</span>.onLoad();</span><br><span class="line"> },</span><br><span class="line"> methods: {</span><br><span class="line"> <span class="comment">// 获取数据</span></span><br><span class="line"> <span class="function"><span class="title">onLoad</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="comment">// 调用api接口,并且提供了两个参数</span></span><br><span class="line"> Login({</span><br><span class="line"> userName: <span class="string">"admin"</span>,</span><br><span class="line"> password: <span class="number">123456</span>,</span><br><span class="line"> }).then(<span class="function">(<span class="params">res</span>) =></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><br></pre></td></tr></table></figure><p>api 接口管理的一个好处就是,我们把 api 统一集中起来,如果后期需要修改接口,我们就直接在 api.js 中找到对应的修改就好了,而不用去每一个页面查找我们的接口然后再修改会很麻烦。还有就是如果直接在我们的业务代码修改接口,一不小心还容易动到我们的业务代码造成不必要的麻烦。</p><hr><h2 id="完整-axios-封装代码"><a href="#完整-axios-封装代码" class="headerlink" title="完整 axios 封装代码"></a>完整 axios 封装代码</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**axios封装</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="keyword">import</span> axios <span class="keyword">from</span> <span class="string">"axios"</span>;</span><br><span class="line"><span class="keyword">import</span> QS <span class="keyword">from</span> <span class="string">"qs"</span>;</span><br><span class="line"><span class="keyword">import</span> { Message } <span class="keyword">from</span> <span class="string">"element-ui"</span>;</span><br><span class="line"><span class="keyword">import</span> store <span class="keyword">from</span> <span class="string">"../store/index"</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> (process.env.NODE_ENV == <span class="string">"development"</span>) {</span><br><span class="line"> <span class="comment">// 生产环境</span></span><br><span class="line"> axios.defaults.baseURL = <span class="string">"https://www.baidu.com"</span>;</span><br><span class="line">} <span class="keyword">else</span> <span class="keyword">if</span> (process.env.NODE_ENV == <span class="string">"test"</span>) {</span><br><span class="line"> <span class="comment">// 测试环境</span></span><br><span class="line"> axios.defaults.baseURL = <span class="string">"https://www.ceshi.com"</span>;</span><br><span class="line">} <span class="keyword">else</span> <span class="keyword">if</span> (process.env.NODE_ENV == <span class="string">"production"</span>) {</span><br><span class="line"> <span class="comment">// 正式环境</span></span><br><span class="line"> axios.defaults.baseURL = <span class="string">"https://www.production.com"</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">axios.defaults.timeout = <span class="number">5000</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// post请求头</span></span><br><span class="line">axios.defaults.headers.post[<span class="string">"Content-Type"</span>] =</span><br><span class="line"> <span class="string">"application/x-www-form-urlencoded;charset=UTF-8"</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 请求拦截器</span></span><br><span class="line">axios.interceptors.request.use(</span><br><span class="line"> (config) => {</span><br><span class="line"> <span class="comment">// 每次发送请求之前判断是否存在token,如果存在,则统一在http请求的header都加上token,不用每次请求都手动添加了</span></span><br><span class="line"> <span class="comment">// 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断</span></span><br><span class="line"> <span class="keyword">const</span> token = store.state.token;</span><br><span class="line"> token && (config.headers.Authorization = token);</span><br><span class="line"> <span class="keyword">return</span> config;</span><br><span class="line"> },</span><br><span class="line"> (error) => {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Promise</span>.error(error);</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">axios.interceptors.response.use(</span><br><span class="line"> (response) => {</span><br><span class="line"> <span class="keyword">if</span> (response.status === <span class="number">200</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Promise</span>.resolve(response);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Promise</span>.reject(response);</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// 服务器状态码不是200的情况</span></span><br><span class="line"> (error) => {</span><br><span class="line"> <span class="keyword">if</span> (error.response.status) {</span><br><span class="line"> <span class="keyword">switch</span> (error.response.status) {</span><br><span class="line"> <span class="comment">// 401: 未登录</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="keyword">case</span> <span class="number">401</span>:</span><br><span class="line"> router.replace({</span><br><span class="line"> path: <span class="string">"/login"</span>,</span><br><span class="line"> query: { <span class="attr">redirect</span>: router.currentRoute.fullPath },</span><br><span class="line"> });</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="comment">// 403 token过期</span></span><br><span class="line"> <span class="comment">// 登录过期对用户进行提示</span></span><br><span class="line"> <span class="comment">// 清除本地token和清空vuex中token对象</span></span><br><span class="line"> <span class="comment">// 跳转登录页面</span></span><br><span class="line"> <span class="keyword">case</span> <span class="number">403</span>:</span><br><span class="line"> Message({</span><br><span class="line"> message: <span class="string">"登录过期,请重新登录"</span>,</span><br><span class="line"> type: <span class="string">"error"</span>,</span><br><span class="line"> duration: <span class="number">1000</span>,</span><br><span class="line"> });</span><br><span class="line"> <span class="comment">// 清除token</span></span><br><span class="line"> <span class="built_in">localStorage</span>.removeItem(<span class="string">"token"</span>);</span><br><span class="line"> store.commit(<span class="string">"loginSuccess"</span>, <span class="literal">null</span>);</span><br><span class="line"> <span class="comment">// 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面</span></span><br><span class="line"> <span class="built_in">setTimeout</span>(<span class="function">() =></span> {</span><br><span class="line"> router.replace({</span><br><span class="line"> path: <span class="string">"/login"</span>,</span><br><span class="line"> query: {</span><br><span class="line"> redirect: router.currentRoute.fullPath,</span><br><span class="line"> },</span><br><span class="line"> });</span><br><span class="line"> }, <span class="number">1000</span>);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="comment">// 404请求不存在</span></span><br><span class="line"> <span class="keyword">case</span> <span class="number">404</span>:</span><br><span class="line"> Message({</span><br><span class="line"> message: <span class="string">"网络请求不存在"</span>,</span><br><span class="line"> type: <span class="string">"error"</span>,</span><br><span class="line"> duration: <span class="number">1500</span>,</span><br><span class="line"> });</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="comment">// 其他错误,直接抛出错误提示</span></span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> Message({</span><br><span class="line"> message: error.response.data.message,</span><br><span class="line"> type: <span class="string">"error"</span>,</span><br><span class="line"> duration: <span class="number">1500</span>,</span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Promise</span>.reject(error.response);</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="comment"> * get方法,对应get请求</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">{String}</span> </span>url [请求的url地址]</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">{Object}</span> </span>params [请求时携带的参数]</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">export</span> <span class="function"><span class="keyword">function</span> <span class="title">get</span>(<span class="params">url, params</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</span><br><span class="line"> axios</span><br><span class="line"> .get(url, {</span><br><span class="line"> params: params,</span><br><span class="line"> })</span><br><span class="line"> .then(<span class="function">(<span class="params">res</span>) =></span> {</span><br><span class="line"> resolve(res.data);</span><br><span class="line"> })</span><br><span class="line"> .catch(<span class="function">(<span class="params">err</span>) =></span> {</span><br><span class="line"> reject(err.data);</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="comment"> * post方法,对应post请求</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">{String}</span> </span>url [请求的url地址]</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">{Object}</span> </span>params [请求时携带的参数]</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">export</span> <span class="function"><span class="keyword">function</span> <span class="title">post</span>(<span class="params">url, params</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</span><br><span class="line"> axios</span><br><span class="line"> .post(url, QS.stringify(params))</span><br><span class="line"> .then(<span class="function">(<span class="params">res</span>) =></span> {</span><br><span class="line"> resolve(res.data);</span><br><span class="line"> })</span><br><span class="line"> .catch(<span class="function">(<span class="params">err</span>) =></span> {</span><br><span class="line"> reject(err.data);</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><ol><li> 优化 axios 封装,去掉之前的 get 和 post</li><li> 断网情况处理</li><li> 更加模块化的 api 管理</li><li> 接口域名有多个的情况</li><li> api 挂载到 vue.prototype 上省去引入的步骤</li></ol><p>http.js 中 axios 封装的优化,先直接贴代码:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><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="comment">/**</span></span><br><span class="line"><span class="comment"> * axios封装</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="keyword">import</span> axios <span class="keyword">from</span> <span class="string">"axios"</span>;</span><br><span class="line"><span class="keyword">import</span> router <span class="keyword">from</span> <span class="string">"../router"</span>;</span><br><span class="line"><span class="keyword">import</span> store <span class="keyword">from</span> <span class="string">"../store/index"</span>;</span><br><span class="line"><span class="keyword">import</span> { Message } <span class="keyword">from</span> <span class="string">"element-ui"</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"> * 禁止点击蒙层、显示一秒后关闭</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">const</span> tip = <span class="function">(<span class="params">msg</span>) =></span> {</span><br><span class="line"> Message({</span><br><span class="line"> message: msg,</span><br><span class="line"> type: <span class="string">"error"</span>,</span><br><span class="line"> duration: <span class="number">1000</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="comment"> * 跳转登录页</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="keyword">const</span> toLogin = <span class="function">() =></span> {</span><br><span class="line"> router.replace({</span><br><span class="line"> path: <span class="string">"/login"</span>,</span><br><span class="line"> query: {</span><br><span class="line"> redirect: router.currentRoute.fullPath,</span><br><span class="line"> },</span><br><span class="line"> });</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 请求失败后的错误统一处理</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">{Number}</span> </span>status 请求失败的状态码</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">const</span> errorHandle = <span class="function">(<span class="params">status, other</span>) =></span> {</span><br><span class="line"> <span class="comment">// 状态码判断</span></span><br><span class="line"> <span class="keyword">switch</span> (status) {</span><br><span class="line"> <span class="comment">// 401: 未登录状态,跳转登录页</span></span><br><span class="line"> <span class="keyword">case</span> <span class="number">401</span>:</span><br><span class="line"> toLogin();</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="comment">// 403 token过期</span></span><br><span class="line"> <span class="comment">// 清除token并跳转登录页</span></span><br><span class="line"> <span class="keyword">case</span> <span class="number">403</span>:</span><br><span class="line"> tip(<span class="string">"登录过期,请重新登录"</span>);</span><br><span class="line"> <span class="built_in">localStorage</span>.removeItem(<span class="string">"token"</span>);</span><br><span class="line"> store.commit(<span class="string">"loginSuccess"</span>, <span class="literal">null</span>);</span><br><span class="line"> <span class="built_in">setTimeout</span>(<span class="function">() =></span> {</span><br><span class="line"> toLogin();</span><br><span class="line"> }, <span class="number">1000</span>);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="comment">// 404请求不存在</span></span><br><span class="line"> <span class="keyword">case</span> <span class="number">404</span>:</span><br><span class="line"> tip(<span class="string">"请求的资源不存在"</span>);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> <span class="built_in">console</span>.log(other);</span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="comment">// 创建axios实例</span></span><br><span class="line"><span class="keyword">var</span> instance = axios.create({ <span class="attr">timeout</span>: <span class="number">5000</span> });</span><br><span class="line"><span class="comment">// 设置post请求头</span></span><br><span class="line">instance.defaults.headers.post[<span class="string">"Content-Type"</span>] =</span><br><span class="line"> <span class="string">"application/x-www-form-urlencoded"</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"> * 每次请求前,如果存在token则在请求头中携带token</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">instance.interceptors.request.use(</span><br><span class="line"> (config) => {</span><br><span class="line"> <span class="comment">// 登录流程控制中,根据本地是否存在token判断用户的登录情况</span></span><br><span class="line"> <span class="comment">// 但是即使token存在,也有可能token是过期的,所以在每次的请求头中携带token</span></span><br><span class="line"> <span class="comment">// 后台根据携带的token判断用户的登录情况,并返回给我们对应的状态码</span></span><br><span class="line"> <span class="comment">// 而后我们可以在响应拦截器中,根据状态码进行一些统一的操作。</span></span><br><span class="line"> <span class="keyword">const</span> token = store.state.token;</span><br><span class="line"> token && (config.headers.Authorization = token);</span><br><span class="line"> <span class="keyword">return</span> config;</span><br><span class="line"> },</span><br><span class="line"> (error) => <span class="built_in">Promise</span>.error(error)</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 响应拦截器</span></span><br><span class="line">instance.interceptors.response.use(</span><br><span class="line"> <span class="comment">// 请求成功</span></span><br><span class="line"> (res) => (res.status === <span class="number">200</span> ? <span class="built_in">Promise</span>.resolve(res) : <span class="built_in">Promise</span>.reject(res)),</span><br><span class="line"> <span class="comment">// 请求失败</span></span><br><span class="line"> (error) => {</span><br><span class="line"> <span class="keyword">const</span> { response } = error;</span><br><span class="line"> <span class="keyword">if</span> (response) {</span><br><span class="line"> <span class="comment">// 请求已发出,但是不在2xx的范围</span></span><br><span class="line"> errorHandle(response.status, response.data.message);</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Promise</span>.reject(response);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">// 处理断网的情况</span></span><br><span class="line"> <span class="comment">// eg:请求超时或断网时,更新state的network状态</span></span><br><span class="line"> <span class="comment">// network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏</span></span><br><span class="line"> <span class="comment">// 关于断网组件中的刷新重新获取数据,会在断网组件中说明</span></span><br><span class="line"> <span class="keyword">if</span> (!<span class="built_in">window</span>.navigator.onLine) {</span><br><span class="line"> store.commit(<span class="string">"changeNetwork"</span>, <span class="literal">false</span>);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Promise</span>.reject(error);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> instance;</span><br></pre></td></tr></table></figure><div class="note primary modern"><p>如下几点改变:</p><ol><li>去掉了之前 get 和 post 方法的封装,通过创建一个 axios 实例然后 export default 方法导出,这样使用起来更灵活一些。</li><li>去掉了通过环境变量控制 baseUrl 的值。考虑到接口会有多个不同域名的情况,所以准备通过 js 变量来控制接口域名。这点具体在 api 里会介绍。</li><li>增加了请求超时,即断网状态的处理。<br>当断网时,通过更新 vuex 中 network 的状态来控制断网提示组件的显示隐藏。断网提示一般会有重新加载数据的操作。</li><li>公用函数进行抽出,简化代码,尽量保证单一职责原则。</li></ol></div><p> 下面说下 api 这块,考虑到以下需求:<br>5. 更加模块化<br>6. 更方便多人开发,有效减少解决命名冲突<br>7. 处理接口域名有多个情况</p><p>这里新建了一个 api 文件夹,里面有一个 index.js 和一个 base.js,以及多个根据模块划分的接口 js 文件。index.js 是一个 api 的出口,base.js 管理接口域名,其他 js 则用来管理各个模块的接口。</p><p>先放 index.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><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="comment">/**</span></span><br><span class="line"><span class="comment"> * api接口的统一出口</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="keyword">import</span> article <span class="keyword">from</span> <span class="string">"@/api/article"</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 class="keyword">export</span> <span class="keyword">default</span> {</span><br><span class="line"> article,</span><br><span class="line"> <span class="comment">// ……</span></span><br><span class="line">};</span><br></pre></td></tr></table></figure><p>index.js 是一个 api 接口的出口,这样就可以把 api 接口根据功能划分为多个模块,利于多人协作开发,比如一个人只负责一个模块的开发等,还能方便每个模块中接口的命名。</p><p>base.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><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 class="comment"> * 接口域名的管理</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">const</span> base = {</span><br><span class="line"> sq: <span class="string">"https://xxxx111111.com/api/v1"</span>,</span><br><span class="line"> bd: <span class="string">"http://xxxxx22222.com/api"</span>,</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> base;</span><br></pre></td></tr></table></figure><p>通过 base.js 来管理我们的接口域名,不管有多少个都可以通过这里进行接口的定义。即使修改起来,也是很方便的。<br>最后就是接口模块的说明,例如上面的 article.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><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">/**</span></span><br><span class="line"><span class="comment"> * article模块接口列表</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> base <span class="keyword">from</span> <span class="string">"./base"</span>; <span class="comment">// 导入接口域名列表</span></span><br><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">"@/utils/http"</span>; <span class="comment">// 导入http中创建的axios实例</span></span><br><span class="line"><span class="keyword">import</span> qs <span class="keyword">from</span> <span class="string">"qs"</span>; <span class="comment">// 根据需求是否导入qs模块</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> article = {</span><br><span class="line"> <span class="comment">// 新闻列表</span></span><br><span class="line"> <span class="function"><span class="title">articleList</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="keyword">return</span> axios.get(<span class="string">`<span class="subst">${base.sq}</span>/topics`</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="title">articleDetail</span>(<span class="params">id, params</span>)</span> {</span><br><span class="line"> <span class="keyword">return</span> axios.get(<span class="string">`<span class="subst">${base.sq}</span>/topic/<span class="subst">${id}</span>`</span>, {</span><br><span class="line"> params: params,</span><br><span class="line"> });</span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// post提交</span></span><br><span class="line"> <span class="function"><span class="title">login</span>(<span class="params">params</span>)</span> {</span><br><span class="line"> <span class="keyword">return</span> axios.post(<span class="string">`<span class="subst">${base.sq}</span>/accesstoken`</span>, qs.stringify(params));</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><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> article;</span><br></pre></td></tr></table></figure><div class="note success modern"><ol><li>通过直接引入我们封装好的 axios 实例,然后定义接口、调用 axios 实例并返回,可以更灵活的使用 axios,比如你可以对 post 请求时提交的数据进行一个 qs 序列化的处理等。</li><li>请求的配置更灵活,你可以针对某个需求进行一个不同的配置。关于配置的优先级,axios 文档说的很清楚,这个顺序是:在 lib/defaults.js 找到的库的默认值,然后是实例的 defaults 属性,最后是请求的 config 参数。后者将优先于前者。</li><li>restful 风格的接口,也可以通过这种方式灵活的设置 api 接口地址。</li></ol></div><p>最后,为了方便 api 的调用,我们需要将其挂载到 vue 的原型上。在 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><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Vue <span class="keyword">from</span> <span class="string">"vue"</span>;</span><br><span class="line"><span class="keyword">import</span> App <span class="keyword">from</span> <span class="string">"./App"</span>;</span><br><span class="line"><span class="keyword">import</span> router <span class="keyword">from</span> <span class="string">"./router"</span>; <span class="comment">// 导入路由文件</span></span><br><span class="line"><span class="keyword">import</span> store <span class="keyword">from</span> <span class="string">"./store"</span>; <span class="comment">// 导入vuex文件</span></span><br><span class="line"><span class="keyword">import</span> api <span class="keyword">from</span> <span class="string">"./api"</span>; <span class="comment">// 导入api接口</span></span><br><span class="line"></span><br><span class="line">Vue.prototype.$api = api; <span class="comment">// 将api挂载到vue的原型上</span></span><br></pre></td></tr></table></figure><p>在页面中这样调用接口,例子 🌰:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><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">methods: {</span><br><span class="line"> <span class="function"><span class="title">onLoad</span>(<span class="params">id</span>)</span> {</span><br><span class="line"> <span class="built_in">this</span>.$api.article.articleDetail(id, {</span><br><span class="line"> api: <span class="number">123</span></span><br><span class="line"> }).then(<span class="function"><span class="params">res</span>=></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></pre></td></tr></table></figure><p>关于断网的处理,这里做一个简单的示例 🌰:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">template</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">v-if</span>=<span class="string">"!network"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">h3</span>></span>我没网了<span class="tag"></<span class="name">h3</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> @<span class="attr">click</span>=<span class="string">"onRefresh"</span>></span>刷新<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">router-view</span> /></span></span><br><span class="line"> <span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"></<span class="name">template</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"><<span class="name">script</span>></span></span><br><span class="line"><span class="javascript"> <span class="keyword">import</span> { mapState } <span class="keyword">from</span> <span class="string">"vuex"</span>;</span></span><br><span class="line"><span class="javascript"> <span class="keyword">export</span> <span class="keyword">default</span> {</span></span><br><span class="line"><span class="javascript"> name: <span class="string">"App"</span>,</span></span><br><span class="line"> computed: {</span><br><span class="line"><span class="javascript"> ...mapState([<span class="string">"network"</span>]),</span></span><br><span class="line"> },</span><br><span class="line"> methods: {</span><br><span class="line"><span class="javascript"> <span class="comment">// 通过跳转一个空页面再返回的方式来实现刷新当前页面数据的目的</span></span></span><br><span class="line"><span class="javascript"> <span class="function"><span class="title">onRefresh</span>(<span class="params"></span>)</span> {</span></span><br><span class="line"><span class="javascript"> <span class="built_in">this</span>.$router.replace(<span class="string">"/refresh"</span>);</span></span><br><span class="line"> },</span><br><span class="line"> },</span><br><span class="line"> };</span><br><span class="line"><span class="tag"></<span class="name">script</span>></span></span><br></pre></td></tr></table></figure><p>这是 app.vue,这里简单演示一下断网。在 http.js 中介绍了,我们会在断网的时候,来更新 vue 中 network 的状态,那么这里我们根据 network 的状态来判断是否需要加载这个断网组件。断网情况下,加载断网组件,不加载对应页面的组件。当点击刷新的时候,我们通过跳转 refesh 页面然后立即返回的方式来实现重新获取数据的操作。因此我们需要新建一个 refresh.vue 页面,并在其 beforeRouteEnter 钩子中再返回当前页面。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// refresh.vue</span></span><br><span class="line">beforeRouteEnter (to, <span class="keyword">from</span>, next) {</span><br><span class="line"> next(<span class="function"><span class="params">vm</span> =></span> {</span><br><span class="line"> vm.$router.replace(<span class="keyword">from</span>.fullPath)</span><br><span class="line"> })</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><h2 id="axios-的封装"><a href="#axios-的封装" class="headerlink" title="axios 的封装"></a>axios 的封装</h2><p>在 vue 项目中,和后台交互获取数据这块,我们通常使用的是 axios 库,它是基</summary>
<category term="javascript" scheme="http://imagineblog.host/categories/javascript/"/>
<category term="Axios" scheme="http://imagineblog.host/tags/Axios/"/>
</entry>
<entry>
<title>浏览器渲染过程简介</title>
<link href="http://imagineblog.host/gc6agg/"/>
<id>http://imagineblog.host/gc6agg/</id>
<published>2021-04-29T02:37:05.000Z</published>
<updated>2022-08-31T08:04:19.377Z</updated>
<content type="html"><![CDATA[<h2 id="浏览器工作流程"><a href="#浏览器工作流程" class="headerlink" title="浏览器工作流程"></a>浏览器工作流程</h2><p>话不多说,先来看个图:</p><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/Render-Process.jpg"></p><p>从上面这个图中,我们可以看到那么几个事:</p><ul><li>浏览器会解析三个东西:</li></ul><ol><li>一个是 HTML/SVG/XHTML,事实上,Webkit 有三个 C++的类对应这三类文档。解析这三种文件会产生一个 DOM Tree。</li><li>CSS,解析 CSS 会产生 CSS 规则树。</li><li>Javascript 脚本,主要是通过 DOM API 和 CSSOM API 来操作 DOM Tree 和 CSS Rule Tree(CSS 规则树)。</li></ol><ul><li>解析完成后,浏览器引擎会通过 DOM Tree 和 CSS Rule Tree 来构造 Rendering Tree(渲染树)。</li></ul><blockquote><p>注意:<br>Rendering Tree 渲染树并不等同于 DOM 树,因为一些像 Header 或 display:none 的东西就没必要放在渲染树中了。<br>CSS 的 Rule Tree 主要是为了完成匹配并把 CSS Rule 附加上 Rendering Tree 上的每个 Element(元素)。也就是 DOM 节点。也就是所谓的 Frame(框架)。<br>然后,计算每个 Frame(也就是每个 Element)的位置,这又叫 layout 和 reflow(重排/回流)过程。</p></blockquote><ul><li>最后通过调用操作系统 Native GUI 的 API 绘制。</li></ul><hr><h2 id="DOM-解析"><a href="#DOM-解析" class="headerlink" title="DOM 解析"></a>DOM 解析</h2><p>HTML 的 DOM Tree 解析如下:</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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">html</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>Web page parsing<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">body</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">h1</span>></span>Web page parsing<span class="tag"></<span class="name">h1</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">p</span>></span>This is an example Web page.<span class="tag"></<span class="name">p</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">body</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">html</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>上面这段 HTML 会解析成这样:</p><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/DOM-Tree-01.jpg"></p><p>有 SVG 标签的情况:</p><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/DOM-Tree-02.jpg"></p><hr><h2 id="CSS-解析"><a href="#CSS-解析" class="headerlink" title="CSS 解析"></a>CSS 解析</h2><p>CSS 的解析大概是下面这个样子(下面主要说的是 Gecko 也就是 Firefox 的玩法),假设我们有下面的 HTML 文档:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">doc</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>A few quotes<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">para</span>></span></span><br><span class="line"> Franklin said that <span class="tag"><<span class="name">quote</span>></span>"A penny saved is a penny earned."<span class="tag"></<span class="name">quote</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">para</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">para</span>></span></span><br><span class="line"> FDR said</span><br><span class="line"> <span class="tag"><<span class="name">quote</span>></span>"We have nothing to fear but <span class="tag"><<span class="name">span</span>></span>fear itself.<span class="tag"></<span class="name">span</span>></span>"<span class="tag"></<span class="name">quote</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">para</span>></span></span><br><span class="line"><span class="tag"></<span class="name">doc</span>></span></span><br></pre></td></tr></table></figure><p>DOM Tree 是这个样子:</p><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/DOM-Tree-Example.jpg"></p><p>css 文档:</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><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">/* rule 1 */</span></span><br><span class="line">doc {</span><br><span class="line"> <span class="attribute">display</span>: block;</span><br><span class="line"> <span class="attribute">text-indent</span>: <span class="number">1em</span>;</span><br><span class="line">}</span><br><span class="line"><span class="comment">/* rule 2 */</span></span><br><span class="line">title {</span><br><span class="line"> <span class="attribute">display</span>: block;</span><br><span class="line"> <span class="attribute">font-size</span>: <span class="number">3em</span>;</span><br><span class="line">}</span><br><span class="line"><span class="comment">/* rule 3 */</span></span><br><span class="line">para {</span><br><span class="line"> <span class="attribute">display</span>: block;</span><br><span class="line">}</span><br><span class="line"><span class="comment">/* rule 4 */</span></span><br><span class="line"><span class="selector-attr">[class=<span class="string">"emph"</span>]</span> {</span><br><span class="line"> <span class="attribute">font-style</span>: italic;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>于是我们的 CSS Rule Tree 会是这个样子:</p><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/CSS-Rule-Tree-Example.jpg"></p><p>注意,图中的第 4 条规则出现了两次,一次是独立的,一次是在规则 3 的子节点。所以,我们可以知道,建立 CSS Rule Tree(CSS 规则树)是需要比照着 DOM Tree 来的。CSS 匹配 DOM Tree 主要是从右到左解析 CSS 的 Selector(选择器),好多人以为这个事会比较快,其实并不一定。关键还看我们的 CSS 的 Selector(选择器)怎么写了。</p><div class="note warning modern"><p>注意:<br>CSS 匹配 HTML 元素是一个相当复杂和有性能问题的事情。所以,你就会在 N 多地方看到很多人都告诉你,DOM 树要小,CSS 尽量用 id 和 class,千万不要过渡层叠下去……</p></div><p>通过这两个树,我们可以得到一个叫 Style Context Tree(样式上下文树),也就是下面这样(把 CSS Rule 节点附加到 DOM Tree 上):</p><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/CSS-Content-Tree-Example.jpg"></p><p>所以,Firefox 基本上来说是通过 CSS 解析 生成 CSS Rule Tree,然后,通过比对 DOM 生成 Style Context Tree,然后 Firefox 通过把 Style Context Tree 和其 Render Tree(Frame Tree)关联上,就完成了。</p><div class="note warning modern"><p>注意:Render Tree 会把一些不可见的节点去除掉。而 Firefox 中所谓的 Frame 就是一个 DOM 节点,不要被其名字所迷惑了。</p></div><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/Firefox-style-context-tree.png"></p><blockquote><p>注:Webkit 不像 Firefox 要用两个树来干这个,Webkit 也有 Style 对象,它直接把这个 Style 对象存在了相应的 DOM 节点上了。</p></blockquote><hr><h2 id="渲染"><a href="#渲染" class="headerlink" title="渲染"></a>渲染</h2><p>渲染的流程基本上如下(黄色的四个步骤):</p><ol><li>计算 CSS 样式</li><li>构建 Render Tree</li><li>Layout – 定位坐标和大小,是否换行,各种 position, overflow, z-index 属性 ……</li><li>正式开画</li></ol><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/Render-Process-Skipping-1024x282.jpg"></p><div class="note warning modern"><p>注意:上图流程中有很多连接线,这表示了 Javascript 动态修改了 DOM 属性或是 CSS 属会导致重新 Layout,有些改变不会,就是那些指到天上的箭头,比如,修改后的 CSS rule 没有被匹配到,等。</p></div><p>这里重要要说两个概念,一个是 Reflow(重排/回流),另一个是 Repaint(重绘)。这两个不是一回事。</p><div class="note info modern"><ul><li>Repaint(重排/回流)——屏幕的一部分要重画,比如某个 CSS 的背景色变了。但是元素的几何尺寸没有变。</li><li>Reflow(重绘)——意味着元件的几何尺寸变了,我们需要重新验证并计算 Render Tree。是 Render Tree 的一部分或全部发生了变化。这就是 Reflow,或是 Layout。(HTML 使用的是 flow based layout,也就是流式布局,所以,如果某元件的几何尺寸发生了变化,需要重新布局,也就叫 reflow)reflow 会从这个 root frame 开始递归往下,依次计算所有的节点几何尺寸和位置,在 reflow 过程中,可能会增加一些 frame,比如一个文本字符串必需被包装起来。</li></ul></div><p>Reflow 的成本比 Repaint 的成本高得多的多。DOM Tree 里的每个节点都会有 reflow 方法,一个节点的 reflow 很有可能导致子节点,甚至父节点以及同级节点的 reflow。在一些高性能的电脑上也许还没什么,但是如果 reflow 发生在手机上,那么这个过程是非常痛苦和耗电的。</p><p>所以,下面这些动作有很大可能会是成本比较高的。</p><ul><li>当你增加、删除、修改 DOM 节点时,会导致 Reflow 或 Repaint</li><li>当你移动 DOM 的位置,或是搞个动画的时候。</li><li>当你修改 CSS 样式的时候。</li><li>当你 Resize 窗口的时候(移动端没有这个问题),或是滚动的时候。</li><li>当你修改网页的默认字体时。</li></ul><blockquote><p>注:display:none 会触发 reflow,而 visibility:hidden 只会触发 repaint,因为没有发现位置变化。</p></blockquote><p>通常来说,如果在滚屏的时候,我们的页面上的所有的像素都会跟着滚动,那么性能上没什么问题,因为我们的显卡对于这种把全屏像素往上往下移的算法是很快。但是如果你有一个 fixed 的背景图,或是有些 Element 不跟着滚动,有些 Elment 是动画,那么这个滚动的动作对于浏览器来说会是相当相当痛苦的一个过程。你可以看到很多这样的网页在滚动的时候性能有多差。因为滚屏也有可能会造成 reflow。</p><p>基本上来说,reflow 有如下的几个原因:</p><ol><li>Initial。网页初始化的时候。</li><li>Incremental。一些 Javascript 在操作 DOM Tree 时。</li><li>Resize。其些元件的尺寸变了。</li><li>StyleChange。如果 CSS 的属性发生变化了。</li><li>Dirty。几个 Incremental 的 reflow 发生在同一个 frame 的子树上。</li></ol><p>看个例子:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> bstyle = <span class="built_in">document</span>.body.style; <span class="comment">// cache</span></span><br><span class="line"></span><br><span class="line">bstyle.padding = <span class="string">"20px"</span>; <span class="comment">// reflow, repaint</span></span><br><span class="line">bstyle.border = <span class="string">"10px solid red"</span>; <span class="comment">// 再一次的 reflow 和 repaint</span></span><br><span class="line"></span><br><span class="line">bstyle.color = <span class="string">"blue"</span>; <span class="comment">// repaint</span></span><br><span class="line">bstyle.backgroundColor = <span class="string">"#fad"</span>; <span class="comment">// repaint</span></span><br><span class="line"></span><br><span class="line">bstyle.fontSize = <span class="string">"2em"</span>; <span class="comment">// reflow, repaint</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// new DOM element – reflow, repaint</span></span><br><span class="line"><span class="built_in">document</span>.body.appendChild(<span class="built_in">document</span>.createTextNode(<span class="string">"dude"</span>));</span><br></pre></td></tr></table></figure><p>当然,我们的浏览器是聪明的,它不会像上面那样,你每改一次样式,它就 reflow 或 repaint 一次。<strong>一般来说,浏览器会把这样的操作积攒一批,然后做一次 reflow,这又叫异步 reflow 或增量异步 reflow</strong>。但是有些情况浏览器是不会这么做的,比如:resize 窗口,改变了页面默认的字体,等。对于这些操作,浏览器会马上进行 reflow。</p><p>但是有些时候,我们的脚本会阻止浏览器这么干,比如:如果我们请求下面的一些 DOM 值:</p><ul><li>offsetTop, offsetLeft, offsetWidth, offsetHeight</li><li>scrollTop/Left/Width/Height</li><li>clientTop/Left/Width/Height</li><li>IE 中的 getComputedStyle(), 或 currentStyle</li></ul><p>因为,如果我们的程序需要这些值,那么浏览器需要返回最新的值,而这样一样会有一些样式的改变,从而造成频繁的 reflow/repaint。</p><hr><h2 id="减少重排-重绘"><a href="#减少重排-重绘" class="headerlink" title="减少重排/重绘"></a>减少重排/重绘</h2><ol><li>不要一条一条地修改 DOM 的样式。与其这样,还不如预先定义好 css 的 class,然后修改 DOM 的 className。</li></ol><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// bad</span></span><br><span class="line"><span class="keyword">var</span> left = <span class="number">10</span>,</span><br><span class="line"> top = <span class="number">10</span>;</span><br><span class="line">el.style.left = left + <span class="string">"px"</span>;</span><br><span class="line">el.style.top = top + <span class="string">"px"</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Good</span></span><br><span class="line">el.className += <span class="string">"theclassname"</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Good</span></span><br><span class="line">el.style.cssText += <span class="string">"; left: "</span> + left + <span class="string">"px; top: "</span> + top + <span class="string">"px;"</span>;</span><br></pre></td></tr></table></figure><ol start="2"><li>把 DOM 离线后修改。<br> 如:<br> 使用 documentFragment 对象在内存里操作 DOM<br> 先把 DOM 给 display:none(有一次 reflow),然后你想怎么改就怎么改。比如修改 100 次,然后再把他显示出来。<br> clone 一个 DOM 节点到内存里,然后想怎么改就怎么改,改完后,和在线的那个的交换一下。</li><li> 不要把 DOM 节点的属性值放在一个循环里当成循环里的变量。不然这会导致大量地读写这个节点的属性。</li><li> 尽可能的修改层级比较低的 DOM。当然,改变层级比较底的 DOM 有可能会造成大面积的 reflow,但是也可能影响范围很小。</li><li> 为动画的 HTML 元件使用 fixed 或 absoult 的 position,那么修改他们的 CSS 是不会 reflow 的。</li><li> 千万不要使用 table 布局。因为可能很小的一个小改动会造成整个 table 的重新布局。</li></ol><hr><p>转载自:<a href="https://coolshell.cn/articles/9666.html">https://coolshell.cn/articles/9666.html</a><br>推荐文章:<a href="http://taligarsiel.com/Projects/howbrowserswork1.htm">《How Browsers Work》</a></p>]]></content>
<summary type="html"><h2 id="浏览器工作流程"><a href="#浏览器工作流程" class="headerlink" title="浏览器工作流程"></a>浏览器工作流程</h2><p>话不多说,先来看个图:</p>
<p><img src= "data:image/gif;base6</summary>
<category term="浏览器" scheme="http://imagineblog.host/categories/%E6%B5%8F%E8%A7%88%E5%99%A8/"/>
<category term="Browser" scheme="http://imagineblog.host/tags/Browser/"/>
</entry>
<entry>
<title>React(一):核心概念</title>
<link href="http://imagineblog.host/xu4nht/"/>
<id>http://imagineblog.host/xu4nht/</id>
<published>2021-04-22T07:18:19.000Z</published>
<updated>2022-08-31T08:04:19.377Z</updated>
<content type="html"><![CDATA[<h2 id="React-简介"><a href="#React-简介" class="headerlink" title="React 简介"></a>React 简介</h2><h3 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h3><p>React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站。做出来以后,发现这套东西很好用,就在 2013 年 5 月开源了。</p><h3 id="react-是什么?"><a href="#react-是什么?" class="headerlink" title="react 是什么?"></a>react 是什么?</h3><p>React 是一个用于构建用户界面的 JavaScript 库。用于构建快速、高效的用户界面;它是一个轻量级库,遵循组件化设计模式、声明式编程范式以及函数式编程概念。它使用虚拟 DOM 来有效地操作 DOM;遵循从高阶组件到低阶组件的单向数据流。</p><blockquote><p>在整个 Web 应用的 MVC 架构中,你可以将 React 看作为视图层,并且是一个高效的视图。React 提供了和以往不一样的方式来看待视图,它以组件开发为基础。对 React 应用而言,你需要分割你的页面,使其成为一个个的组件。也就是说,你的应用是由这些组件组合而成的。你可以通过分割组件的方式去开发复杂的页面或某个功能区块,并且组件是可以被复用的。这个过程大概类似于用乐高积木去拼装不同的物体。</p></blockquote><hr><h2 id="特点"><a href="#特点" class="headerlink" title="特点"></a>特点</h2><ul><li>采用组件化模式、声明式编码;提高开发效率和组件复用率</li><li>使用虚拟 DOM 和 diffing 算法,减少与真实 DOM 的交互</li><li>与已知的库或框架完好配合,相对灵活</li><li>使用 JSX 语法糖</li><li>单向数据流</li></ul><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/vdom.jpg"></p><hr><h2 id="Virtual-DOM"><a href="#Virtual-DOM" class="headerlink" title="Virtual DOM"></a>Virtual DOM</h2><p>为了跟踪模型层的变化,并且将其应用到 DOM 中(也就是渲染),我们需要注意两个重要的事情:</p><ul><li>数据是什么时候改变的<br>React 提供了一个观察者模型用于替代传统的脏检查(dirty checking),也就是持续的检查模型的变化。这也就是解释了为什么 React 不需要计算哪些发生了改变的原因,因为它会立即知道。这个过程减少了计算量,使应用程序变得更平滑。</li><li>哪一个(些)DOM 元素需要被更新<br>React 在内存中构建了 DOM 的树形表示,并且计算出哪个 DOM 元素应该被改变。对浏览器而言,DOM 操纵是比较耗费性能的,因此我们更倾向于让其变得最小化。幸运的是,React 视图尽可能少的触及到 DOM 元素。给予对象表示而言, 更少的 DOM 操纵意味着计算会更快,因此 DOM 改变也被尽可能的减少。<br>React 在底层实现了一个 diffing 算法,该算法使用 DOM 的树形表示法,当某个节点发生变化(标记为 dirty)时它会重新计算整个子树,你会注意到你的模型发生了改变,因为整个子树在之后会被重新渲染。</li></ul><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/vdom03.png"></p><h3 id="什么是虚拟-DOM?"><a href="#什么是虚拟-DOM?" class="headerlink" title="什么是虚拟 DOM?"></a>什么是虚拟 DOM?</h3><p>在 react 中,简单来说虚拟 DOM 其实就是 JS 对象,将真实 DOM 抽象成一个 javascript 对象。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">el</span>(<span class="params">name, props, child</span>) </span>{</span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">this</span>.name = name;</span><br><span class="line"> <span class="built_in">this</span>.props = props;</span><br><span class="line"> <span class="built_in">this</span>.child = child;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> dom = <span class="keyword">new</span> el(<span class="string">"div"</span>, { <span class="attr">id</span>: <span class="string">"list"</span> }, [</span><br><span class="line"> <span class="keyword">new</span> el(<span class="string">"span"</span>, { <span class="attr">id</span>: <span class="string">"span_one"</span> }, [<span class="string">"第一个元素"</span>]),</span><br><span class="line"> <span class="keyword">new</span> el(<span class="string">"span"</span>, { <span class="attr">id</span>: <span class="string">"span_two"</span> }, [<span class="string">"第二个元素"</span>]),</span><br><span class="line"> <span class="keyword">new</span> el(<span class="string">"span"</span>, { <span class="attr">id</span>: <span class="string">"span_three"</span> }, [<span class="string">"第三个元素"</span>]),</span><br><span class="line"> <span class="keyword">new</span> el(<span class="string">"span"</span>, { <span class="attr">id</span>: <span class="string">"span_four"</span> }, [<span class="string">"第四个元素"</span>]),</span><br><span class="line">]);</span><br></pre></td></tr></table></figure><p>这里的 dom 就是一个对象,里面包含了 name,props,child。<br>将对象转换成真实的 DOM:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><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">el.prototype.render = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> d = <span class="built_in">document</span>.createElement(<span class="built_in">this</span>.name);</span><br><span class="line"> <span class="keyword">for</span> (key <span class="keyword">in</span> <span class="built_in">this</span>.props) {</span><br><span class="line"> d.setAttribute(key, <span class="built_in">this</span>.props[key]);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">this</span>.child.forEach(<span class="function"><span class="keyword">function</span> (<span class="params">child</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (child <span class="keyword">instanceof</span> el) {</span><br><span class="line"> tnode = child.render();</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> tnode = <span class="built_in">document</span>.createTextNode(child);</span><br><span class="line"> }</span><br><span class="line"> d.appendChild(tnode);</span><br><span class="line"> });</span><br><span class="line"> <span class="keyword">return</span> d;</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> ele = dom.render();</span><br><span class="line"><span class="built_in">document</span>.body.appendChild(ele);</span><br></pre></td></tr></table></figure><h3 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h3><p>在 React 中,也有一个 render 函数来将虚拟 DOM 树转换成真实 DOM,并且,React 中有 state 转移的过程,所以每次 state 有变化之后,就会触发 render 函数,重新构造一个虚拟 DOM 树。对比新旧虚拟 DOM 树的差别,记录下差异,然后只针对差异部分对应的真实 DOM 进行操作。</p><ul><li>如何进行新旧虚拟 DOM 树的对比?<br>这里采用的是 Diff 算法。Diff 算法比较复杂,主要的思路是这样的。<br>首先,每一次生成的虚拟 DOM 树上的各个节点都对应唯一的一个 id,当第二次生成了新的 DOM 树时,对原来树上的每一个节点对比新树上对应节点,如果不同,就记录下来这个差异。同时,差异也分为很多种:</li></ul><ol><li>替换节点</li><li>删除、移动、增加节点</li><li>修改属性</li><li>对文本内容做修改</li></ol><p>对每一类记录下差异后,针对不同的差异做不同的操作。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">比如:替换节点就需要调原生JS的repaceChild()接口;对于修改属性,则要调setAttribute()接口等等。</span><br></pre></td></tr></table></figure><hr><h2 id="JSX-语法"><a href="#JSX-语法" class="headerlink" title="JSX 语法"></a>JSX 语法</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> element = <span class="xml"><span class="tag"><<span class="name">h1</span>></span>Hello, Word!<span class="tag"></<span class="name">h1</span>></span></span>;</span><br></pre></td></tr></table></figure><blockquote><p>像这样的形式,被称为 JSX;是 javascript 的语法扩展。JSX 的基本语法和 XML 基本相同,都是使用成对标签的形式构成树状结构的数据。</p></blockquote><h3 id="为什么使用-JSX?"><a href="#为什么使用-JSX?" class="headerlink" title="为什么使用 JSX?"></a>为什么使用 JSX?</h3><p>我们来看看 React 官方的回答:</p><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/jsx.png"></p><p>简单来说,react 认为组件才是王道;而组件是和模板紧密关联的。组件模板和组件逻辑分离让问题复杂化了。<br>所以就有了 JSX 这种语法,就是为了把 HTML 模板直接嵌入到 JS 代码里面,这样就做到了模板和组件关联,但是 JS 不支持这种包含 HTML 的语法,所以需要通过工具将 JSX 编译输出成 JS 代码才能使用。</p><h3 id="JSX-是可选的"><a href="#JSX-是可选的" class="headerlink" title="JSX 是可选的"></a>JSX 是可选的</h3><p>因为 JSX 最终是输出成 JS 代码来表达的,所以我们可以直接用 React 提供的这些 DOM 构建方法来写模板,比如一个 JSX 写的一个链接:<br><code><a href="https://react.docschina.org/">Hello!</a></code><br>用 js 来写的的话就是:<br><code>React.createElement('a', {href: 'https://react.docschina.org/'}, 'Hello!')</code></p><p>JSX 语法糖允许前端开发者使用我们最熟悉的类 HTML 标签语法来创建虚拟 DOM 在降低学习成本的同时,也提升了研发效率与研发体验。</p><h3 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h3><h4 id="标签类型"><a href="#标签类型" class="headerlink" title="标签类型"></a>标签类型</h4><ul><li>DOM 类型的标签(div,span 等), 使用时,标签首字母必须小写</li><li>React 组件类型的标签,使用时,组件名称的首字母必须大写</li></ul><p>React 通过首字母的大小写来判断渲染的是 DOM 类型标签还是 React 组件类型标签。</p><h4 id="JS-表达式"><a href="#JS-表达式" class="headerlink" title="JS 表达式"></a>JS 表达式</h4><p>JSX 的本质是 javascript,在 JSX 中使用 JS 表达式需要用{}包裹起来。</p><ul><li>使用场景</li></ul><ol><li>通过表达式给标签属性赋值<br><code>const dom = <Child data={ 1 + 1 } /></code></li><li>通过表达式定义子组件</li></ol><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="string">'li01'</span>,<span class="string">'li02'</span>,<span class="string">'li03'</span>]</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> dom = {</span><br><span class="line"> <ul></span><br><span class="line"> arr.map(<span class="function"><span class="params">item</span>=></span>{<span class="xml"><span class="tag"><<span class="name">Item</span> <span class="attr">msg</span>=<span class="string">{item}</span> <span class="attr">key</span>=<span class="string">{item}</span> /></span></span>})</span><br><span class="line"> </ul></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="标签属性"><a href="#标签属性" class="headerlink" title="标签属性"></a>标签属性</h4><ol><li>当 JSX 标签是 DOM 类型的标签时,对应的 DOM 标签支持的属性 JSX 也支持,部分属性名称有所变化,例如 class 写成 className,之所以改变是因为 React 对 DOM 标签支持的事件重新做了封装。事件属性名称采用驼峰格式。</li><li>当 JSX 标签是 React 组件类型时,可以自定义标签的属性名。</li></ol><h4 id="注释"><a href="#注释" class="headerlink" title="注释"></a>注释</h4><p>JSX 的注释需要大括号”{}”将/**/包裹起来。</p><hr><h2 id="元素渲染"><a href="#元素渲染" class="headerlink" title="元素渲染"></a>元素渲染</h2><blockquote><p>元素是构成 React 应用的最小砖块。</p></blockquote><h3 id="将一个元素渲染为-DOM"><a href="#将一个元素渲染为-DOM" class="headerlink" title="将一个元素渲染为 DOM"></a>将一个元素渲染为 DOM</h3><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">div</span> <span class="attr">id</span>=<span class="string">"root"</span>></span><span class="tag"></<span class="name">div</span>></span></span><br></pre></td></tr></table></figure><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> dom = <span class="xml"><span class="tag"><<span class="name">h1</span>></span>Hello, Word!<span class="tag"></<span class="name">h1</span>></span></span>;</span><br><span class="line">ReactDOM.render(dom, <span class="built_in">document</span>.getElementById(<span class="string">"root"</span>));</span><br></pre></td></tr></table></figure><h3 id="更新已渲染元素"><a href="#更新已渲染元素" class="headerlink" title="更新已渲染元素"></a>更新已渲染元素</h3><p>React 元素是不可变对象。一旦被创建,你就无法更改它的子元素或者属性。一个元素就像电影的单帧:它代表了某个特定时刻的 UI。更新 UI 唯一的方式是创建一个全新的元素,并将其传入 ReactDOM.render()。</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="function"><span class="keyword">function</span> <span class="title">tick</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> element = (</span><br><span class="line"> <div></span><br><span class="line"> <h1>Hello, world!</h1></span><br><span class="line"> <h2>It is {<span class="keyword">new</span> <span class="built_in">Date</span>().toLocaleTimeString()}.</h2></span><br><span class="line"> </div></span><br><span class="line"> );</span><br><span class="line"> ReactDOM.render(element, <span class="built_in">document</span>.getElementById(<span class="string">"root"</span>));</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">setInterval</span>(tick, <span class="number">1000</span>);</span><br></pre></td></tr></table></figure><h3 id="React-只更新它需要更新的部分"><a href="#React-只更新它需要更新的部分" class="headerlink" title="React 只更新它需要更新的部分"></a>React 只更新它需要更新的部分</h3><p>ReactDOM 会将元素和它的子元素与它们之前的状态进行比较,并只会进行必要的更新来使 DOM 达到预期的状态。</p><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/timeout.gif"></p><p>尽管每一秒都会新建一个描述整个 UI 树的元素,ReactDOM 只会更新实际改变了的内容。</p><hr><h2 id="组件"><a href="#组件" class="headerlink" title="组件"></a>组件</h2><h3 id="组件的定义"><a href="#组件的定义" class="headerlink" title="组件的定义"></a>组件的定义</h3><p>定义组件的两种方式:</p><ul><li>使用函数(函数组件)</li><li>使用 ES6 class(类组件)</li></ul><h4 id="函数组件"><a href="#函数组件" class="headerlink" title="函数组件"></a>函数组件</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Funcomponent</span>(<span class="params">props</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="xml"><span class="tag"><<span class="name">h1</span>></span>我是函数组件,{props.name}<span class="tag"></<span class="name">h1</span>></span></span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><blockquote><p>该函数是一个有效的 React 组件,因为它接收唯一带有数据的 “props”(代表属性)对象并返回一个 React 元素。这类组件被称为“函数组件”,因为它本质上就是 JavaScript 函数。</p></blockquote><h4 id="class-类组件"><a href="#class-类组件" class="headerlink" title="class 类组件"></a>class 类组件</h4><p>使用 class 定义组件满足的两个条件:</p><ol><li>class 继承自 React.Component。</li><li>class 内部必须自定义 render 方法,render 方法返回代表该组件 UI 的 React 元素。</li></ol><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Classcomponent</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span> </span>{</span><br><span class="line"> <span class="function"><span class="title">render</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="xml"><span class="tag"><<span class="name">h1</span>></span>我是类组件,{this.props.name}<span class="tag"></<span class="name">h1</span>></span></span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="组件渲染"><a href="#组件渲染" class="headerlink" title="组件渲染"></a>组件渲染</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> element = <span class="xml"><span class="tag"><<span class="name">Child</span> <span class="attr">name</span>=<span class="string">"child"</span> /></span></span>;</span><br></pre></td></tr></table></figure><blockquote><p>当 React 元素为用户自定义组件时,它会将 JSX 所接收的属性(attributes)以及子组件(children)转换为单个对象传递给组件,这个对象被称之为 “props”。</p></blockquote><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Child</span>(<span class="params">props</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="xml"><span class="tag"><<span class="name">h1</span>></span>Hello!{props.name}<span class="tag"></<span class="name">h1</span>></span></span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> element = <span class="xml"><span class="tag"><<span class="name">Child</span> <span class="attr">name</span>=<span class="string">"函数式组件"</span> /></span></span>;</span><br><span class="line">ReactDOM.render(element, <span class="built_in">document</span>.getElementById(<span class="string">"root"</span>));</span><br></pre></td></tr></table></figure><p>来看看上述例子都做了什么?</p><ul><li>调用 ReactDOM.render()函数,并传入< Child name=”函数式组件” />作为参数。</li><li>React 调用 Child 组件,并将{name: ‘函数式组件’}作为 props 传入。</li><li>Child 组件将< h1 >Hello!函数式组件</ h1 >元素作为返回值。</li><li>React DOM 将 DOM 高效地更新为< h1 >Hello!函数式组件</ h1 >。</li></ul><h3 id="组合、嵌套组件"><a href="#组合、嵌套组件" class="headerlink" title="组合、嵌套组件"></a>组合、嵌套组件</h3><blockquote><p>将一个组件渲染到某一个节点里的时候,会将这个节点里原有内容覆盖。组件嵌套的方式就是将子组件写入到父组件的模板中去,且 React 没有 Vue 中的内容分发机制(slot),所以我们在一个组件的模板中只能看到父子关系</p></blockquote><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 从 react 的包当中引入了 React 和 React.js 的组件父类 Component</span></span><br><span class="line"><span class="comment">// 还引入了一个React.js里的一种特殊的组件 Fragment</span></span><br><span class="line"><span class="keyword">import</span> React, { Component, Fragment } <span class="keyword">from</span> <span class="string">'react'</span></span><br><span class="line"><span class="keyword">import</span> ReactDOM <span class="keyword">from</span> <span class="string">'react-dom'</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Title</span> <span class="keyword">extends</span> <span class="title">Component</span> </span>{</span><br><span class="line">render () {</span><br><span class="line"><span class="keyword">return</span> (</span><br><span class="line"><h1>Hello,React</h1></span><br><span class="line"> )</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Content</span> <span class="keyword">extends</span> <span class="title">Component</span> </span>{</span><br><span class="line">render () {</span><br><span class="line"><span class="keyword">return</span> (</span><br><span class="line"><p>React.js是一个用于构建用户界面的JavaScript库</p></span><br><span class="line"> )</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"><span class="comment">/** 由于每个React组件只能有一个根节点,所以要渲染多个组件的时候,需要在最外层包一个容器,如果使用div, 会生成多余的一层dom</span></span><br><span class="line"><span class="comment">class App extends Component {</span></span><br><span class="line"><span class="comment"> render () {</span></span><br><span class="line"><span class="comment"> return (</span></span><br><span class="line"><span class="comment"> <div></span></span><br><span class="line"><span class="comment"> <Title /></span></span><br><span class="line"><span class="comment"> <Content /></span></span><br><span class="line"><span class="comment"> </div></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">}</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="comment">// 如果不想生成多余的一层dom可以使用React提供的Fragment组件在最外层进行包裹</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">App</span> <span class="keyword">extends</span> <span class="title">Component</span> </span>{</span><br><span class="line"> render () {</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <Fragment></span><br><span class="line"> <Title /></span><br><span class="line"> <Content /></span><br><span class="line"> </Fragment></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">ReactDOM.render(</span><br><span class="line"><App/>,</span><br><span class="line"><span class="built_in">document</span>.getElementById(<span class="string">'root'</span>)</span><br></pre></td></tr></table></figure><h3 id="Props(组件的数据挂载方式)"><a href="#Props(组件的数据挂载方式)" class="headerlink" title="Props(组件的数据挂载方式)"></a>Props(组件的数据挂载方式)</h3><h4 id="属性-props(只读性)"><a href="#属性-props(只读性)" class="headerlink" title="属性 props(只读性)"></a>属性 props(只读性)</h4><p>props 是由外部传进来的,也可以由组件内部设置初始化的 props;组件无论是使用函数式组件还是 class 组件,都不能修改自身的 props。可以通过父组件主动重新渲染的方式来传入新的 props。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React, { Component, Fragment } <span class="keyword">from</span> <span class="string">'react'</span></span><br><span class="line"><span class="keyword">import</span> ReactDOM <span class="keyword">from</span> <span class="string">'react-dom'</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Title</span> <span class="keyword">extends</span> <span class="title">Component</span></span>{</span><br><span class="line"> <span class="function"><span class="title">render</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <h1>Hello,{<span class="built_in">this</span>.props.name}</h1></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">const</span> Conent = <span class="function">(<span class="params">props</span>)=></span> {</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <p>{props.name}是一个用于构建用户界面的JavaScript库</p></span><br><span class="line"> )</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">App</span> <span class="keyword">extends</span> <span class="title">Component</span></span>{</span><br><span class="line"> <span class="function"><span class="title">render</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">return</span>(</span><br><span class="line"> <Fragment></span><br><span class="line"> <Title name=<span class="string">"React"</span> /></span><br><span class="line"> <Conent name=<span class="string">"React.js"</span> /></span><br><span class="line"> </Fragment></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">ReactDOM.render(</span><br><span class="line"><App/>,</span><br><span class="line"><span class="built_in">document</span>.getElementById(<span class="string">'root'</span>)</span><br></pre></td></tr></table></figure><h4 id="设置组件的默认-props"><a href="#设置组件的默认-props" class="headerlink" title="设置组件的默认 props"></a>设置组件的默认 props</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React, { Component, Fragment } <span class="keyword">from</span> <span class="string">'react'</span></span><br><span class="line"><span class="keyword">import</span> ReactDOM <span class="keyword">from</span> <span class="string">'react-dom'</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Title</span> <span class="keyword">extends</span> <span class="title">Component</span></span>{</span><br><span class="line"> <span class="comment">// 使用类创建的组件,直接在这里写static方法,创建defaultProps</span></span><br><span class="line"> <span class="keyword">static</span> defaultProps = {</span><br><span class="line"> name: <span class="string">'React'</span></span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="title">render</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <h1>Hello,{<span class="built_in">this</span>.props.name}</h1></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">const</span> Conent = <span class="function">(<span class="params">props</span>)=></span> {</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <p>{props.name}是一个用于构建用户界面的JavaScript库</p></span><br><span class="line"> )</span><br><span class="line">}</span><br><span class="line"><span class="comment">// 使用箭头函数创建的组件,需要在这个组件上直接写defaultProps属性</span></span><br><span class="line">Content.defaultProps = {</span><br><span class="line">name: <span class="string">'React.js'</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">App</span> <span class="keyword">extends</span> <span class="title">Component</span></span>{</span><br><span class="line"> <span class="function"><span class="title">render</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">return</span>(</span><br><span class="line"> <Fragment></span><br><span class="line"> {<span class="comment">/* 由于设置了defaultProps, 不传props也能正常运行,如果传递了就会覆盖defaultProps的值 */</span>}</span><br><span class="line"> <Title /></span><br><span class="line"> <Conent /></span><br><span class="line"> </Fragment></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">ReactDOM.render(</span><br><span class="line"><App/>,</span><br><span class="line"><span class="built_in">document</span>.getElementById(<span class="string">'root'</span>)</span><br></pre></td></tr></table></figure><h4 id="props-children"><a href="#props-children" class="headerlink" title="props.children"></a>props.children</h4><p>我们知道使用组件的时候,可以嵌套。要在自定义组件的使用嵌套结构,就需要使用 props.children。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React, { Component, Fragment } <span class="keyword">from</span> <span class="string">'react'</span></span><br><span class="line"><span class="keyword">import</span> ReactDOM <span class="keyword">from</span> <span class="string">'react-dom'</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Title</span> <span class="keyword">extends</span> <span class="title">Component</span></span>{</span><br><span class="line"> <span class="function"><span class="title">render</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <h1>Hello,{<span class="built_in">this</span>.props.children}</h1></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">const</span> Conent = <span class="function">(<span class="params">props</span>)=></span> {</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <p>{props.children}</p></span><br><span class="line"> )</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">App</span> <span class="keyword">extends</span> <span class="title">Component</span></span>{</span><br><span class="line"> <span class="function"><span class="title">render</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">return</span>(</span><br><span class="line"> <Fragment></span><br><span class="line"> <Title>React</Title></span><br><span class="line"> <Conent><span class="xml"><span class="tag"><<span class="name">strong</span>></span>React.js<span class="tag"></<span class="name">strong</span>></span></span>是一个用于构建用户界面的JavaScript库</Conent></span><br><span class="line"> </Fragment></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">ReactDOM.render(</span><br><span class="line"><App/>,</span><br><span class="line"><span class="built_in">document</span>.getElementById(<span class="string">'root'</span>)</span><br></pre></td></tr></table></figure><h4 id="prop-types"><a href="#prop-types" class="headerlink" title="prop-types"></a>prop-types</h4><blockquote><p>React 其实是为了构建大型应用程序而生, 在一个大型应用中,根本不知道别人使用你写的组件的时候会传入什么样的参数,有可能会造成应用程序运行不了,但是不报错。为了解决这个问题,React 提供了一种机制,让写组件的人可以给组件的 props 设定参数检查,需要安装和使用 prop-types:</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">npm i prop-types -S</span><br></pre></td></tr></table></figure><hr><h2 id="State(状态)"><a href="#State(状态)" class="headerlink" title="State(状态)"></a>State(状态)</h2><div class="note primary modern"><p>组件的 state 是组件内部的状态,state 的变化最终将反映在组件 UI 的变化上。在构造方法 constructor 中通过 this.state 定义组件的初始状态,并调用 this.setState 方法改变组件的状态。</p></div><h3 id="定义-state"><a href="#定义-state" class="headerlink" title="定义 state"></a>定义 state</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React, { Component, Fragment } <span class="keyword">from</span> <span class="string">'react'</span></span><br><span class="line"><span class="keyword">import</span> ReactDOM <span class="keyword">from</span> <span class="string">'react-dom'</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">App</span> <span class="keyword">extends</span> <span class="title">Component</span></span>{</span><br><span class="line"> <span class="function"><span class="title">constructor</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="built_in">super</span>()</span><br><span class="line"> <span class="built_in">this</span>.state = {</span><br><span class="line"> name: <span class="string">'React'</span>,</span><br><span class="line"> bool: <span class="literal">true</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="title">render</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">return</span>(</span><br><span class="line"> <div></span><br><span class="line"> <h1>Welcome to {<span class="built_in">this</span>.state.name} Word!</h1></span><br><span class="line"> <button>{<span class="built_in">this</span>.state.bool ? <span class="string">'YES'</span> : <span class="string">'NO'</span>}</button></span><br><span class="line"> </div></span><br><span class="line"> )</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">ReactDOM.render(</span><br><span class="line"><App/>,</span><br><span class="line"><span class="built_in">document</span>.getElementById(<span class="string">'root'</span>)</span><br></pre></td></tr></table></figure><div class="note info modern"><p>this.props 和 this.state 是纯 js 对象,在 vue 中,data 属性是利用 Object.defineProperty 处理过的,更改 data 的数据的时候会触发数据的 getter 和 setter,但是 React 中没有做这样的处理,如果直接更改的话,react 是无法得知的,所以,需要使用特殊的更改状态的方法 setState。</p></div><h3 id="setState"><a href="#setState" class="headerlink" title="setState"></a>setState</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React, { Component, Fragment } <span class="keyword">from</span> <span class="string">'react'</span></span><br><span class="line"><span class="keyword">import</span> ReactDOM <span class="keyword">from</span> <span class="string">'react-dom'</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">App</span> <span class="keyword">extends</span> <span class="title">Component</span></span>{</span><br><span class="line"> <span class="function"><span class="title">constructor</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="built_in">super</span>()</span><br><span class="line"> <span class="built_in">this</span>.state = {</span><br><span class="line"> name: <span class="string">'React'</span>,</span><br><span class="line"> bool: <span class="literal">true</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"> handleBtn = <span class="function">()=></span>{</span><br><span class="line"> <span class="built_in">this</span>.setState = ({</span><br><span class="line"> bool: !<span class="built_in">this</span>.state.bool</span><br><span class="line"> })</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="title">render</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">return</span>(</span><br><span class="line"> <div></span><br><span class="line"> <h1>Welcome to {<span class="built_in">this</span>.state.name} Word!</h1></span><br><span class="line"> <button onClick={<span class="built_in">this</span>.handleBtn}>{<span class="built_in">this</span>.state.bool ? <span class="string">'YES'</span> : <span class="string">'NO'</span>}</button></span><br><span class="line"> </div></span><br><span class="line"> )</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">ReactDOM.render(</span><br><span class="line"><App/>,</span><br><span class="line"><span class="built_in">document</span>.getElementById(<span class="string">'root'</span>)</span><br></pre></td></tr></table></figure><p>setState 有两个参数:</p><div class="tabs" id="参数"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#参数-1">参数是对象</button></li><li class="tab"><button type="button" data-href="#参数-2">参数是方法</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="参数-1"><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">this</span>.setState = {</span><br><span class="line"> bool: !<span class="built_in">this</span>.state.bool,</span><br><span class="line">};</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="参数-2"><div class="note warning modern"><p>注意的是这个方法接收两个参数,第一个是上一次的 state, 第二个是 props<br>setState 是异步的,所以想要获取到最新的 state,没有办法获取,就有了第二个参数,这是一个可选的回调函数</p></div><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></pre></td><td class="code"><pre><span class="line"><span class="built_in">this</span>.setState =</span><br><span class="line"> (<span class="function">(<span class="params">preState, props</span>) =></span> {</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> bool: !preState.bool,</span><br><span class="line"> };</span><br><span class="line"> },</span><br><span class="line"> () => {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"callback"</span>, <span class="built_in">this</span>.state.bool);</span><br><span class="line"> });</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">"setState"</span>, <span class="built_in">this</span>.state.bool);</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="Props-和-State-对比"><a href="#Props-和-State-对比" class="headerlink" title="Props 和 State 对比"></a>Props 和 State 对比</h2><div class="tabs" id="props和state对比"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#props和state对比-1">相似点</button></li><li class="tab"><button type="button" data-href="#props和state对比-2">不同点</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="props和state对比-1"><p><strong>都是纯 js 对象,都会触发 render 更新,都具有确定性(状态/属性相同,结果相同)</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="props和state对比-2"><table><thead><tr><th>Props</th><th>State</th></tr></thead><tbody><tr><td>能从父组件获取</td><td>不能</td></tr><tr><td>可以由父组件修改</td><td>不可以</td></tr><tr><td>能在内部设置默认值</td><td>不能</td></tr><tr><td>不在组件内部修改</td><td>要改</td></tr><tr><td>能设置子组件初始值</td><td>不可以</td></tr><tr><td>可以修改子组件的值</td><td>不可以</td></tr><tr><td>主要作用是让使用该组件的父组件可以传入参数来配置该组件。它是外部传进来的配置参数,组件内部无法控制也无法修改。除非外部组件主动传入新的 props,否则组件的 props 永远保持不变。</td><td>主要作用是用于组件保存、控制、修改自己的可变状态。state 在组件内部初始化,可以被组件自身修改,而外部不能访问也不能修改。你可以认为 state 是一个局部的、只能被组件自身控制的数据源。state 中状态可以通过 this.setState 方法进行更新,setState 会导致组件的重新渲染。</td></tr></tbody></table><div class="note success modern"><p>React 组件是通过 props 和 state 两种数据驱动渲染出组件 UI。Props 是组件对外的接口,它是只读的,组件通过 props 接受外部传入的数据;state 是组件对内的接口,它是可变的,组件内部状态通过 state 来反映。</p></div><p>如果搞不清 state 和 props 的使用场景,记住一个简单的规则:尽量少地用 state,多用 props。<br>没有 state 的组件叫无状态组件(stateless component),设置了 state 的叫做有状态组件(stateful component)。因为状态会带来管理的复杂性,我们尽量多地写无状态组件,尽量少地写有状态的组件。这样会降低代码维护的难度,也会在一定程度上增强组件的可复用性。</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><p><strong><em>状态提升</em></strong></p><ul><li>如果有多个组件共享一个数据,把这个数据放到共同的父级组件中来管理<br>具体操作可以查看 React 文档:<a href="https://react.docschina.org/docs/lifting-state-up.html">状态提升</a></li></ul><hr><h2 id="生命周期"><a href="#生命周期" class="headerlink" title="生命周期"></a>生命周期</h2><div class="tabs" id="生命周期"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#生命周期-1">React旧版生命周期</button></li><li class="tab"><button type="button" data-href="#生命周期-2">React新版生命周期</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="生命周期-1"><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/oldComponent.png"></p><ul><li>第一次渲染<br>constructor → componentWillMount → render → componentDidMount</li><li>props 更新<br>componentWillReceiveProps → shouldComponentUpdate(如果返回 true) → componentWillUpdate → render → componentDidUpdate</li><li>state 更新<br>shouldComponentUpdate (如果返回 true)→ componentWillUpdate → render → componentDidUpdate</li><li>组件卸载<br>componentWillUnmount</li></ul><p><strong>React 旧版生命周期包含三个过程:</strong></p><ol><li>挂载过程<br> constructor()<br> componentWillMount()<br> componentDidMount()</li><li>更新过程<br> componentWillReceiveProps(nextProps)<br> shouldComponentUpdate(nextProps,nextState)<br> componentWillUpdate (nextProps,nextState)<br> render()<br> componentDidUpdate(prevProps,prevState)</li><li>卸载过程<br> componentWillUnmount()</li></ol><p><strong>其具体作用分别为:</strong></p><ul><li><strong>constructor()</strong><br>完成了 React 数据的初始化。</li><li><strong>componentWillMount()</strong><br>组件已经完成初始化数据,但是还未渲染 DOM 时执行的逻辑,主要用于服务端渲染。</li><li><strong>componentDidMount()</strong><br>组件第一次渲染完成时执行的逻辑,此时 DOM 节点已经生成了。</li><li><strong>componentWillReceiveProps(nextProps)</strong><br>接收父组件新的 props 时,重新渲染组件执行的逻辑。</li><li><strong>shouldComponentUpdate(nextProps, nextState)</strong><br>在 setState 以后,state 发生变化,组件会进入重新渲染的流程时执行的逻辑。在这个生命周期中 return false 可以阻止组件的更新,主要用于性能优化。</li><li><strong>componentWillUpdate(nextProps, nextState)</strong><br>shouldComponentUpdate 返回 true 以后,组件进入重新渲染的流程时执行的逻辑。</li><li><strong>render()</strong><br>页面渲染执行的逻辑,render 函数把 jsx 编译为函数并生成虚拟 dom,然后通过其 diff 算法比较更新前后的新旧 DOM 树,并渲染更改后的节点。</li><li><strong>componentDidUpdate(prevProps, prevState)</strong><br>重新渲染后执行的逻辑。</li><li><strong>componentWillUnmount()</strong><br>组件的卸载前执行的逻辑,比如进行“清除组件中所有的 setTimeout、setInterval 等计时器”或“移除所有组件中的监听器 removeEventListener”等操作。</li></ul><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="生命周期-2"><p><em></em></p><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/newComponent.png"></p><p>所不同的是少了 componentWillMount, componentWillReceiveProps, componentWillUpdate 这三个鸡肋,其实这三个生命周期回调要直到 v17 才会被完全删除,不过现在都被冠以 UNSAFE_的前缀了。</p><p>多了两个是 getDerivedStateFromProps 和 getSnapshotBeforeUpdate,其中 getDerivedStateFromProps 在第一次渲染和更新的时候都会被调用,而 getSnapshotBeforeUpdate 只会在更新的时候被调用。</p><ul><li><p><strong>使用 getDerivedStateFromProps(nextProps, prevState)的原因:</strong></p><div class="note primary modern"><p> 旧的 React 中 componentWillReceiveProps 方法是用来判断前后两个 props 是否相同,如果不同,则将新的 props 更新到相应的 state 上去。在这个过程中我们实际上是可以访问到当前 props 的,这样我们可能会对 this.props 做一些奇奇怪怪的操作,很可能会破坏 state 数据的单一数据源,导致组件状态变得不可预测。</p><p>而在 getDerivedStateFromProps 中禁止了组件去访问 this.props,强制让开发者去比较 nextProps 与 prevState 中的值,以确保当开发者用到 getDerivedStateFromProps 这个生命周期函数时,就是在根据当前的 props 来更新组件的 state,而不是去访问 this.props 并做其他一些让组件自身状态变得更加不可预测的事情。</p></div></li><li><p><strong>使用 getSnapshotBeforeUpdate(prevProps, prevState)的原因:</strong></p><div class="note primary modern"><p> 在 React 开启异步渲染模式后,在执行函数时读到的 DOM 元素状态并不总是渲染时相同,这就导致在 componentDidUpdate 中使用 componentWillUpdate 中读取到的 DOM 元素状态是不安全的,因为这时的值很有可能已经失效了。</p><p>而 getSnapshotBeforeUpdate 会在最终的 render 之前被调用,也就是说在 getSnapshotBeforeUpdate 中读取到的 DOM 元素状态是可以保证与 componentDidUpdate 中一致的。</p></div></li></ul><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><hr><h2 id="事件处理"><a href="#事件处理" class="headerlink" title="事件处理"></a>事件处理</h2><h3 id="绑定事件"><a href="#绑定事件" class="headerlink" title="绑定事件"></a>绑定事件</h3><p>React 元素的事件处理和 DOM 元素很相似,都是采用 on+事件名称的方式绑定事件。但不同的是原生事件采用的是纯小写形式,如:onclick;而 React 的事件使用小驼峰的形式,如:onClick;使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。</p><div class="note info modern"><p>React 的事件不是原生事件,而是合成事件。</p></div><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">button</span> <span class="attr">onclick</span>=<span class="string">"clickActive()"</span>></span>BUTTON<span class="tag"></<span class="name">button</span>></span></span><br></pre></td></tr></table></figure><p>React:</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">button</span> <span class="attr">onClick</span>=<span class="string">"{clickActive}"</span>></span>BUTTON<span class="tag"></<span class="name">button</span>></span></span><br></pre></td></tr></table></figure><h3 id="事件-handler-的写法"><a href="#事件-handler-的写法" class="headerlink" title="事件 handler 的写法"></a>事件 handler 的写法</h3><ul><li>直接在 render 里写行内的箭头函数(不推荐)</li><li>在组件内使用箭头函数定义一个方法(推荐)</li><li>直接在组件内定义一个非箭头函数的方法,然后在 render 里直接使用 onClick={this.handleClick.bind(this)}(不推荐)</li><li>直接在组件内定义一个非箭头函数的方法,然后在 constructor 里 bind(this)(推荐)</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Toggle</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span> </span>{</span><br><span class="line"> <span class="function"><span class="title">constructor</span>(<span class="params">props</span>)</span> {</span><br><span class="line"> <span class="built_in">super</span>(props);</span><br><span class="line"> <span class="built_in">this</span>.state = { <span class="attr">isToggleOn</span>: <span class="literal">true</span> };</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 为了在回调中使用 `this`,这个绑定是必不可少的</span></span><br><span class="line"> <span class="built_in">this</span>.handleClick = <span class="built_in">this</span>.handleClick.bind(<span class="built_in">this</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="title">handleClick</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="built_in">this</span>.setState(<span class="function">(<span class="params">state</span>) =></span> ({</span><br><span class="line"> isToggleOn: !state.isToggleOn,</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="title">render</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <button onClick={<span class="built_in">this</span>.handleClick}></span><br><span class="line"> {<span class="built_in">this</span>.state.isToggleOn ? <span class="string">"ON"</span> : <span class="string">"OFF"</span>}</span><br><span class="line"> </button></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">ReactDOM.render(<span class="xml"><span class="tag"><<span class="name">Toggle</span> /></span></span>, <span class="built_in">document</span>.getElementById(<span class="string">"root"</span>));</span><br></pre></td></tr></table></figure><h3 id="Event-对象"><a href="#Event-对象" class="headerlink" title="Event 对象"></a>Event 对象</h3><p>和普通浏览器一样,事件 handler 会被自动传入一个 event 对象,这个对象和普通的浏览器 event 对象所包含的方法和属性都基本一致。不同的是 React 中的 event 对象并不是浏览器提供的,而是它自己内部所构建的。它同样具有 event.stopPropagation、event.preventDefault 这种常用的方法</p><blockquote><p>因此,在 React 中你不能通过返回 false 的方式阻止默认行为。你必须显式的使用 preventDefault。</p></blockquote><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><a href=<span class="string">"#"</span> onclick=<span class="string">"console.log('click'); return false"</span>></a></span><br></pre></td></tr></table></figure><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Active</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">clickLink</span>(<span class="params">e</span>) </span>{</span><br><span class="line"> e.preventDefault();</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"click"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="xml"><span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#"</span> <span class="attr">onClick</span>=<span class="string">{clickLink}</span>></span><span class="tag"></<span class="name">a</span>></span></span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="向事件处理程序传递参数"><a href="#向事件处理程序传递参数" class="headerlink" title="向事件处理程序传递参数"></a>向事件处理程序传递参数</h3><ol><li>在 render 里调用方法的地方包一层箭头函数</li><li>在 render 里通过 this.handleEvent.bind(this, 参数)这样的方式来传递</li><li>通过 event 传递</li></ol><figure class="highlight html"><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="tag"><<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">{(e)</span> =></span> this.deleteRow(id, e)}>Delete Row<span class="tag"></<span class="name">button</span>></span></span><br><span class="line"><span class="tag"><<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">{this.deleteRow.bind(this,</span> <span class="attr">id</span>)}></span>Delete Row<span class="tag"></<span class="name">button</span>></span></span><br></pre></td></tr></table></figure><hr><h2 id="条件渲染"><a href="#条件渲染" class="headerlink" title="条件渲染"></a>条件渲染</h2><p>在 React 中,你可以创建不同的组件来封装各种你需要的行为。然后,依据应用的不同状态,你可以只渲染对应状态下的部分内容。</p><div class="note primary modern"><p>React 中的条件渲染和 JavaScript 中的一样,使用 JavaScript 运算符 if 或者条件运算符去创建元素来表现当前的状态,然后让 React 根据它们来更新 UI。</p></div><h3 id="条件表达式渲染(适用于两个组件二选一的渲染)"><a href="#条件表达式渲染(适用于两个组件二选一的渲染)" class="headerlink" title="条件表达式渲染(适用于两个组件二选一的渲染)"></a>条件表达式渲染(适用于两个组件二选一的渲染)</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="title">render</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="keyword">const</span> isLoggedIn = <span class="built_in">this</span>.state.isLoggedIn;</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> {isLoggedIn ? (</span><br><span class="line"> <LogoutButton onClick={<span class="built_in">this</span>.handleLogoutClick} /></span><br><span class="line"> ) : (</span><br><span class="line"> <LoginButton onClick={<span class="built_in">this</span>.handleLoginClick} /></span><br><span class="line"> )}</span><br><span class="line"> </div></span><br><span class="line"> );</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="amp-amp-操作符渲染-适用于一个组件有无的渲染"><a href="#amp-amp-操作符渲染-适用于一个组件有无的渲染" class="headerlink" title="&& 操作符渲染 (适用于一个组件有无的渲染)"></a>&& 操作符渲染 (适用于一个组件有无的渲染)</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Mailbox</span>(<span class="params">props</span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> messages = props.messages;</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> <h1>Hello!</h1></span><br><span class="line"> {messages.length > <span class="number">0</span> && <span class="xml"><span class="tag"><<span class="name">h2</span>></span>You have {messages.length} messages.<span class="tag"></<span class="name">h2</span>></span></span>}</span><br><span class="line"> </div></span><br><span class="line"> );</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="利用变量输出组件渲染-(适用于有多个组件多种条件下的渲染)"><a href="#利用变量输出组件渲染-(适用于有多个组件多种条件下的渲染)" class="headerlink" title="利用变量输出组件渲染 (适用于有多个组件多种条件下的渲染)"></a>利用变量输出组件渲染 (适用于有多个组件多种条件下的渲染)</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><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="function"><span class="title">render</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="keyword">const</span> isLoggedIn = <span class="built_in">this</span>.state.isLoggedIn;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> button = isLoggedIn ? (</span><br><span class="line"> <LogoutButton onClick={<span class="built_in">this</span>.handleLogoutClick} /></span><br><span class="line"> ) : (</span><br><span class="line"> <LoginButton onClick={<span class="built_in">this</span>.handleLoginClick} /></span><br><span class="line"> );</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> <Greeting isLoggedIn={isLoggedIn} /></span><br><span class="line"> {button}</span><br><span class="line"> </div></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="函数方式"><a href="#函数方式" class="headerlink" title="函数方式"></a>函数方式</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><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="title">renderButton</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">const</span> isLoggedIn = <span class="built_in">this</span>.state.isLoggedIn;</span><br><span class="line"> <span class="keyword">if</span>(isLoggedIn)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> (<span class="xml"><span class="tag"><<span class="name">LogoutButton</span> <span class="attr">onClick</span>=<span class="string">{this.handleLogoutClick}</span> /></span></span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> (<span class="xml"><span class="tag"><<span class="name">LoginButton</span> <span class="attr">onClick</span>=<span class="string">{this.handleLoginClick}</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="function"><span class="title">render</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> <Greeting /></span><br><span class="line"> {<span class="built_in">this</span>.renderButton()}</span><br><span class="line"> </div></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 javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Greeting</span>(<span class="params">props</span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> isLoggedIn = props.isLoggedIn;</span><br><span class="line"> <span class="keyword">if</span> (isLoggedIn) {</span><br><span class="line"> <span class="keyword">return</span> <span class="xml"><span class="tag"><<span class="name">UserGreeting</span> /></span></span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="xml"><span class="tag"><<span class="name">GuestGreeting</span> /></span></span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">ReactDOM.render(</span><br><span class="line"> <Greeting isLoggedIn={<span class="literal">false</span>} />,</span><br><span class="line"> <span class="built_in">document</span>.getElementById(<span class="string">"root"</span>)</span><br><span class="line">);</span><br></pre></td></tr></table></figure><hr><h2 id="列表和-key"><a href="#列表和-key" class="headerlink" title="列表和 key"></a>列表和 key</h2><p>当列表数据为多组时,调用数据运行时为提示警告:“Each child in an array or iterator should have a unique ‘ key ’ prop ”说明如果没有给每条数据添加一个“key” 的话,当数据组数过多时,不同组数有相同的数据,调用就可能会出现错误。因此这里的“key”就相当于数据库里的主键,给每组数据调取都有一个参照。</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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">ListItem</span>(<span class="params">props</span>) </span>{</span><br><span class="line"> <span class="comment">// 正确!这里不需要指定 key:</span></span><br><span class="line"> <span class="keyword">return</span> <span class="xml"><span class="tag"><<span class="name">li</span>></span>{props.value}<span class="tag"></<span class="name">li</span>></span></span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">NumberList</span>(<span class="params">props</span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> numbers = props.numbers;</span><br><span class="line"> <span class="keyword">const</span> listItems = numbers.map(<span class="function">(<span class="params">number</span>) =></span> (</span><br><span class="line"> <span class="comment">// 正确!key 应该在数组的上下文中被指定</span></span><br><span class="line"> <ListItem key={number.toString()} value={number} /></span><br><span class="line"> ));</span><br><span class="line"> <span class="keyword">return</span> <span class="xml"><span class="tag"><<span class="name">ul</span>></span>{listItems}<span class="tag"></<span class="name">ul</span>></span></span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> numbers = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>];</span><br><span class="line">ReactDOM.render(</span><br><span class="line"> <NumberList numbers={numbers} />,</span><br><span class="line"> <span class="built_in">document</span>.getElementById(<span class="string">"root"</span>)</span><br><span class="line">);</span><br></pre></td></tr></table></figure><div class="note success modern"><ul><li>key 帮助 React 识别哪些元素改变了,比如被添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识。</li><li>虽然列表元素的 key 不能重复,但这个唯一性仅限至于在当前列表中,而不是全局唯一。</li><li>不推荐使用索引作为 key,因为一旦列表中的数据发生重排,数据的索引也会发生变化,不利于 React 的渲染优化。</li></ul></div><hr><h2 id="表单"><a href="#表单" class="headerlink" title="表单"></a>表单</h2><h3 id="受控组件"><a href="#受控组件" class="headerlink" title="受控组件"></a>受控组件</h3><blockquote><p>什么受控组件?简单来说就是如果一个表单元素的值是由 React 来管理的,那它就是一个受控组件。</p></blockquote><p>贴一段 React 官网的解释:</p><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/input.png"></p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React, { Component } <span class="keyword">from</span> <span class="string">"react"</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Inputs</span> <span class="keyword">extends</span> <span class="title">Component</span> </span>{</span><br><span class="line"> <span class="function"><span class="title">constructor</span>(<span class="params">props</span>)</span> {</span><br><span class="line"> <span class="built_in">super</span>(props);</span><br><span class="line"> <span class="built_in">this</span>.state = {</span><br><span class="line"> name: <span class="string">""</span>,</span><br><span class="line"> password: <span class="string">""</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="title">handleChange</span>(<span class="params">event</span>)</span> {</span><br><span class="line"> <span class="keyword">const</span> e = event.target;</span><br><span class="line"> <span class="built_in">this</span>.setState({</span><br><span class="line"> [e.name]: e.value,</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="title">handleSubmit</span>(<span class="params">event</span>)</span> {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"Login Success!"</span>);</span><br><span class="line"> event.preventDefault();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="title">render</span>(<span class="params"></span>)</span> {</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <form onSubmit={<span class="built_in">this</span>.handleSubmit}></span><br><span class="line"> </span><br><span class="line"> <label></span><br><span class="line"> 用户名:</span><br><span class="line"> <input</span><br><span class="line"> type=<span class="string">"text"</span></span><br><span class="line"> name=<span class="string">"name"</span></span><br><span class="line"> value={<span class="built_in">this</span>.state.name}</span><br><span class="line"> onChange={<span class="built_in">this</span>.handleChange}</span><br><span class="line"> /></span><br><span class="line"> </span><br><span class="line"> </label></span><br><span class="line"> <label></span><br><span class="line"> 密码:</span><br><span class="line"> <input</span><br><span class="line"> type=<span class="string">"password"</span></span><br><span class="line"> name=<span class="string">"password"</span></span><br><span class="line"> value={<span class="built_in">this</span>.state.password}</span><br><span class="line"> onChange={<span class="built_in">this</span>.handleChange}</span><br><span class="line"> /></span><br><span class="line"> </span><br><span class="line"> </label></span><br><span class="line"> </span><br><span class="line"> <input type=<span class="string">"submit"</span> value=<span class="string">"登录"</span> /></span><br><span class="line"> </form></span><br><span class="line"> );</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><div class="note success modern"><p>用户名和密码两个表单元素的值是从组件的 state 中获取的,当用户更改表单元素的值时,onChange 事件会被触发,对应的 handleChange 处理函数会把变化同步到组件的 state,新的 state 又会触发表单元素重新渲染,从而实现表单元素状态的控制。</p></div><hr><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><blockquote><p>本章主要介绍了 React 的主要特性及其用法。React 通过 JSX 语法声明界面 UI,将界面 UI 和它的逻辑封装在同一个 JS 文件中。通过虚拟 DOM 和 diffing 算法来减少与真实 DOM 的交互。组件是 React 的核心,根据组件的外部接口 props 和内部接口 state 完成自身的渲染。使用组件需要理解它的生命周期,借助不同的生命周期方法,组件可以实现复杂逻辑。渲染时,注意 key 的使用,事件处理时,注意事件名称和事件处理函数的写法。最后介绍表单元素的用法,使用方式分受控组价和非受控组件。</p></blockquote>]]></content>
<summary type="html"><h2 id="React-简介"><a href="#React-简介" class="headerlink" title="React 简介"></a>React 简介</h2><h3 id="背景"><a href="#背景" class="headerlink" titl</summary>
<category term="React" scheme="http://imagineblog.host/categories/React/"/>
<category term="javascript" scheme="http://imagineblog.host/tags/javascript/"/>
<category term="React" scheme="http://imagineblog.host/tags/React/"/>
</entry>
<entry>
<title>JS forEach 踩坑</title>
<link href="http://imagineblog.host/ehgc3o/"/>
<id>http://imagineblog.host/ehgc3o/</id>
<published>2021-04-21T07:51:55.000Z</published>
<updated>2022-08-31T08:04:19.377Z</updated>
<content type="html"><![CDATA[<p>在 js 做遍历数组的时候会用到很多数组的遍历方法,例如 for 循环、forEach 之类的方法,今天主要来说说 forEach 方法的一些坑。<br>来看一下这段代码:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></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><br><span class="line">arr.forEach(<span class="function">(<span class="params">item, indec</span>) =></span> {</span><br><span class="line"> arr.splice(index, <span class="number">1</span>);</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"执行"</span>); <span class="comment">// 输出了几次???</span></span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(arr); <span class="comment">// arr ????</span></span><br></pre></td></tr></table></figure><h2 id="上述代码中,循环体内“执行”打印了几次?arr-的输出是多少?"><a href="#上述代码中,循环体内“执行”打印了几次?arr-的输出是多少?" class="headerlink" title="上述代码中,循环体内“执行”打印了几次?arr 的输出是多少?"></a>上述代码中,循环体内“执行”打印了几次?arr 的输出是多少?</h2><p>👌 好,我们带着这些疑问继续往下看。</p><h2 id="forEach-参数"><a href="#forEach-参数" class="headerlink" title="forEach 参数"></a>forEach 参数</h2><p>与 for 循环一样,forEach 也属于完整遍历数组的方法,并会对数组每项元素执行提供的回调函数,一个完整的 forEach 应该是这样,我们一一解释回调函数的参数,与后方的 this 有何作用。<br><code>arr.forEach(function(self,index,arr){},this)</code></p><ul><li>**<em>self</em>**:数组当前遍历的元素,默认从左往右依次获取数组元素</li><li>**<em>index</em>**:数组当前元素的索引</li><li>**<em>arr</em>**:当前遍历的数组</li><li>**<em>this</em>**:回调函数中的 this 指向</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>];</span><br><span class="line"><span class="keyword">let</span> obj = {</span><br><span class="line"> a: <span class="number">1</span>,</span><br><span class="line">};</span><br><span class="line">arr.forEach(<span class="function"><span class="keyword">function</span> (<span class="params">self, index, arr</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`当前元素为<span class="subst">${self}</span>索引为<span class="subst">${index}</span>,属于数组<span class="subst">${arr}</span>`</span>);</span><br><span class="line"> <span class="comment">//做个简单计算</span></span><br><span class="line"> <span class="built_in">console</span>.log(self + <span class="built_in">this</span>.a);</span><br><span class="line">}, obj);</span><br></pre></td></tr></table></figure><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/each01.png"></p><p>可以看到,arr 参数其实就是我们正在遍历的数组,而回调函数中的 this 指向我们提供的 obj。</p><p>至于第三个参数 arr,遍历自己还提供自己作为参数,其实这个参数还挺好用,比如我们可以利用它做数组去重,像这样:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> arr1 = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">2</span>, <span class="number">1</span>, <span class="number">4</span>];</span><br><span class="line"><span class="keyword">let</span> arr2 = [];</span><br><span class="line">arr1.forEach(<span class="function">(<span class="params">self, index, arr</span>) =></span> {</span><br><span class="line"> arr.indexOf(self) === index ? arr2.push(self) : <span class="literal">null</span>;</span><br><span class="line">});</span><br><span class="line"><span class="built_in">console</span>.log(arr2); <span class="comment">// [1,2,3,4]</span></span><br></pre></td></tr></table></figure><hr><h2 id="坑点"><a href="#坑点" class="headerlink" title="坑点"></a>坑点</h2><h3 id="1、不支持-break"><a href="#1、不支持-break" class="headerlink" title="1、不支持 break"></a>1、不支持 break</h3><p>大家都知道,在使用 for 循环时可以使用 break 跳出循环,比如我希望找到数组中符合条件的第一个元素就跳出循环,这对于优化数组遍历是非常棒的。很遗憾,forEach 并不支持 break 操作,使用 break 会导致报错。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>], i = <span class="number">0</span>, length = arr.length;</span><br><span class="line"><span class="keyword">for</span> (; i < length; i++) {</span><br><span class="line"> <span class="built_in">console</span>.log(arr[i]); <span class="comment">//1,2</span></span><br><span class="line"> <span class="keyword">if</span> (arr[i] === <span class="number">2</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><br><span class="line">arr.forEach(<span class="function">(<span class="params">self,index</span>) =></span> {</span><br><span class="line"> <span class="built_in">console</span>.log(self);</span><br><span class="line"> <span class="keyword">if</span> (self === <span class="number">2</span>) {</span><br><span class="line"> <span class="keyword">break</span>; <span class="comment">//报错</span></span><br><span class="line"> };</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>要想跳过循环,需要通过 try catch 来操作;具体可以查看文章<a href="https://www.cnblogs.com/echolun/p/10651039.html">js forEach 跳出循环</a></p><h3 id="2、使用-return-无效"><a href="#2、使用-return-无效" class="headerlink" title="2、使用 return 无效"></a>2、使用 return 无效</h3><p>forEach 中使用 return 不会报错,但 rerutn 并不会生效,我们来看个例子:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>];</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">find</span>(<span class="params">arr, num</span>) </span>{</span><br><span class="line"> arr.forEach(<span class="function">(<span class="params">self, index</span>) =></span> {</span><br><span class="line"> <span class="keyword">if</span> (self === num) {</span><br><span class="line"> <span class="keyword">return</span> index;</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> index = find(arr, <span class="number">2</span>); <span class="comment">// undefined</span></span><br></pre></td></tr></table></figure><p>上述代码想要找到数字 2 在数组中的索引,但 return 并不会起到终止代码运行并返回值的作用。<br>如果我们真的要用 return 返回某个值,那就只能将 return 操作放在函数中,而不是 forEach 循环中,像这样:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">find</span>(<span class="params">arr, num</span>) </span>{</span><br><span class="line"> <span class="keyword">let</span> _index;</span><br><span class="line"> arr.forEach(<span class="function">(<span class="params">self, index</span>) =></span> {</span><br><span class="line"> <span class="keyword">if</span> (self === num) {</span><br><span class="line"> _index = index;</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"> <span class="keyword">return</span> _index;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="3、删除自身元素-index-不会被重置"><a href="#3、删除自身元素-index-不会被重置" class="headerlink" title="3、删除自身元素 index 不会被重置"></a>3、删除自身元素 index 不会被重置</h3><p>让我们回头看看文章开头的那段代码,那段代码其实只会执行一次,数组也不会被删除干净,这是因为 forEach 在遍历跑完回调函数后,会隐性让 index 自增,像这样:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">arr.forEach(<span class="function">(<span class="params">item, index</span>) =></span> {</span><br><span class="line"> arr.splice(index, <span class="number">1</span>);</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"执行"</span>);</span><br><span class="line"> <span class="comment">//这里隐性让index自增加1</span></span><br><span class="line"> index++;</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>当第一次遍历结束,此时数组为[2]而 index 变成了 1,此时数组最大索引只是 0,不满足条件,所以跳出了循环。<br>那有没有什么办法让此时的 forEach 不跳出循环呢,当然有,使用 ES6 的拓展运算符。</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">[...arr].forEach(<span class="function">(<span class="params">item, index</span>) =></span> {</span><br><span class="line"> arr.splice(index, <span class="number">1</span>);</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"执行"</span>);</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>通过拓展运算符重置数组 arr,达到不跳出循环的目的,会发现内部确实执行了两次,很遗憾的是 index 依旧没被重置,所以数组 arr 还是无法在遍历的同时删空自己。</p><hr><h2 id="for、forEach-比较"><a href="#for、forEach-比较" class="headerlink" title="for、forEach 比较"></a>for、forEach 比较</h2><ol><li>for 循环可以使用 break 跳出循环,但 forEach 不能。</li><li>for 循环可以控制循环起点(i 初始化的数字决定循环的起点),forEach 只能默认从索引 0 开始。</li><li>for 循环过程中支持修改索引(修改 i),但 forEach 做不到(底层控制 index 自增,我们无法左右它)。</li></ol><hr><h2 id="数组遍历并删除自身"><a href="#数组遍历并删除自身" class="headerlink" title="数组遍历并删除自身"></a>数组遍历并删除自身</h2><p>怎么在遍历一个数组的同时,并删除符合条件的所有项呢?</p><h3 id="for-循环实现"><a href="#for-循环实现" class="headerlink" title="for 循环实现"></a>for 循环实现</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</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">1</span>],</span><br><span class="line"> i = <span class="number">0</span>,</span><br><span class="line"> length = arr.length;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (; i < length; i++) {</span><br><span class="line"> <span class="comment">// 删除数组中所有的1</span></span><br><span class="line"> <span class="keyword">if</span> (arr[i] === <span class="number">1</span>) {</span><br><span class="line"> arr.splice(i, <span class="number">1</span>);</span><br><span class="line"> <span class="comment">//重置i,否则i会跳一位</span></span><br><span class="line"> i--;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="built_in">console</span>.log(arr); <span class="comment">// [2]</span></span><br></pre></td></tr></table></figure><h3 id="filter-实现"><a href="#filter-实现" class="headerlink" title="filter 实现"></a>filter 实现</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> arr1 = arr.filter(<span class="function">(<span class="params">index</span>) =></span> {</span><br><span class="line"> <span class="keyword">return</span> index !== <span class="number">1</span>;</span><br><span class="line">});</span><br><span class="line"><span class="built_in">console</span>.log(arr1); <span class="comment">//[2]</span></span><br></pre></td></tr></table></figure><h3 id="forEach-实现(不建议)"><a href="#forEach-实现(不建议)" class="headerlink" title="forEach 实现(不建议)"></a>forEach 实现(不建议)</h3><p>forEach 因为 index 索引无法重置,对于删除数组项真的很困难,我们得让数组反过来遍历:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">arr</span><br><span class="line"> .slice()</span><br><span class="line"> .reverse()</span><br><span class="line"> .forEach(<span class="function"><span class="keyword">function</span> (<span class="params">item, index, arr1</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (item === <span class="number">1</span>) {</span><br><span class="line"> arr.splice(arr1.length - <span class="number">1</span> - index, <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"><span class="built_in">console</span>.log(arr); <span class="comment">//[2]</span></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><p>在 js 做遍历数组的时候会用到很多数组的遍历方法,例如 for 循环、forEach 之类的方法,今天主要来说说 forEach 方法的一些坑。<br>来看一下这段代码:</p>
<figure class="highlight javascript"><table><t</summary>
<category term="javascript" scheme="http://imagineblog.host/categories/javascript/"/>
<category term="javascript" scheme="http://imagineblog.host/tags/javascript/"/>
</entry>
<entry>
<title>Promise(三):拓展方法实现</title>
<link href="http://imagineblog.host/ddv8fu/"/>
<id>http://imagineblog.host/ddv8fu/</id>
<published>2021-04-14T06:34:21.000Z</published>
<updated>2022-08-31T08:04:19.373Z</updated>
<content type="html"><![CDATA[<p>上次把 Promise 简单的实现了基本功能,趁热打铁,我们来实现一下它里面的拓展方法。</p><h2 id="myPromise-prototype-catch"><a href="#myPromise-prototype-catch" class="headerlink" title="myPromise.prototype.catch"></a>myPromise.prototype.catch</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">myPromise.prototype.catch = <span class="function"><span class="keyword">function</span> (<span class="params">rejectFun</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>.then(<span class="literal">null</span>, rejectFun);</span><br><span class="line">};</span><br></pre></td></tr></table></figure><blockquote><p>catch 方法实现起来还是简单的,通过调用 Promise 的 then 方法,只传入失败的回调;then 方法会把值传递下去。</p></blockquote><hr><h2 id="myPromise-prototype-finally"><a href="#myPromise-prototype-finally" class="headerlink" title="myPromise.prototype.finally"></a>myPromise.prototype.finally</h2><p>不管成功还是失败,都会执行</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">myPromise.prototype.finally = <span class="function"><span class="keyword">function</span> (<span class="params">finallyFun</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>.then(<span class="function">(<span class="params">res</span>) =></span> {</span><br><span class="line"> finallyFun();</span><br><span class="line"> <span class="keyword">return</span> res;</span><br><span class="line"> }).catch(<span class="function">(<span class="params">err</span>) =></span> {</span><br><span class="line"> fiinallyFun();</span><br><span class="line"> <span class="keyword">return</span> err;</span><br><span class="line"> });</span><br><span class="line">};</span><br></pre></td></tr></table></figure><hr><h2 id="myPromise-resolve"><a href="#myPromise-resolve" class="headerlink" title="myPromise.resolve"></a>myPromise.resolve</h2><p>返回一个成功的 Promise</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">myPromise.resolve = <span class="function"><span class="keyword">function</span> (<span class="params">res</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> myPromise(<span class="function">(<span class="params">resolve</span>) =></span> {</span><br><span class="line"> resolve(res);</span><br><span class="line"> });</span><br><span class="line">};</span><br></pre></td></tr></table></figure><hr><h2 id="myPromise-reject"><a href="#myPromise-reject" class="headerlink" title="myPromise.reject"></a>myPromise.reject</h2><p>返回一个失败的 Promise</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">myPromise.reject = <span class="function"><span class="keyword">function</span> (<span class="params">res</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> myPromise(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</span><br><span class="line"> reject(res);</span><br><span class="line"> });</span><br><span class="line">};</span><br></pre></td></tr></table></figure><hr><h2 id="myPromise-all"><a href="#myPromise-all" class="headerlink" title="myPromise.all"></a>myPromise.all</h2><ul><li>返回一个 Promsie 实例,接收一个可迭代的对象,返回值是一个数组</li><li>等参数内的值都执行成功才返回成功,只要有一个值返回失败,则返回失败</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><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">myPromise.all = <span class="function"><span class="keyword">function</span> (<span class="params">arr</span>) </span>{</span><br><span class="line"> <span class="comment">/*判断参数类型*/</span></span><br><span class="line"> <span class="keyword">if</span> (!<span class="built_in">Array</span>.isArray(arr)) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">TypeError</span>(<span class="string">"参数类型错误,必须是数组"</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">let</span> resolve;</span><br><span class="line"> <span class="keyword">let</span> reject;</span><br><span class="line"> <span class="keyword">const</span> promise = <span class="keyword">new</span> myPromise(<span class="function">(<span class="params">r, j</span>) =></span> {</span><br><span class="line"> resolve = r;</span><br><span class="line"> reject = j;</span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> fufilledCount = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">let</span> index = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">const</span> result = [];</span><br><span class="line"> <span class="comment">/*记录当前遍历的index*/</span></span><br><span class="line"> <span class="keyword">const</span> wrapFufilled = <span class="function">(<span class="params">i</span>) =></span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="function">(<span class="params">val</span>) =></span> {</span><br><span class="line"> fufilledCount += <span class="number">1</span>;</span><br><span class="line"> result[i] = val;</span><br><span class="line"> <span class="keyword">if</span> (fufilledCount >= index) {</span><br><span class="line"> resolve(result);</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> };</span><br><span class="line"> <span class="keyword">const</span> wrapRejected = <span class="function">(<span class="params">i</span>) =></span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="function">(<span class="params">err</span>) =></span> {</span><br><span class="line"> reject(err);</span><br><span class="line"> };</span><br><span class="line"> };</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> item <span class="keyword">of</span> arr) {</span><br><span class="line"> myPromise.resolve(item).then(wrapFufilled(index), wrapRejected(index));</span><br><span class="line"> index += <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> promise;</span><br><span class="line">};</span><br></pre></td></tr></table></figure><p>调用一下 myPromise.all</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 测试</span></span><br><span class="line"><span class="keyword">const</span> pro1 = <span class="keyword">new</span> myPromise(<span class="function">(<span class="params">res, rej</span>) =></span> {</span><br><span class="line"> <span class="built_in">setTimeout</span>(<span class="function">() =></span> {</span><br><span class="line"> res(<span class="string">"1"</span>);</span><br><span class="line"> }, <span class="number">1000</span>);</span><br><span class="line">});</span><br><span class="line"><span class="keyword">const</span> pro2 = <span class="keyword">new</span> myPromise(<span class="function">(<span class="params">res, rej</span>) =></span> {</span><br><span class="line"> <span class="built_in">setTimeout</span>(<span class="function">() =></span> {</span><br><span class="line"> <span class="comment">// res('2')</span></span><br><span class="line"> rej(<span class="string">"错误"</span>);</span><br><span class="line"> }, <span class="number">2000</span>);</span><br><span class="line">});</span><br><span class="line"><span class="keyword">const</span> pro3 = <span class="keyword">new</span> myPromise(<span class="function">(<span class="params">res, rej</span>) =></span> {</span><br><span class="line"> <span class="built_in">setTimeout</span>(<span class="function">() =></span> {</span><br><span class="line"> res(<span class="string">"3"</span>);</span><br><span class="line"> }, <span class="number">3000</span>);</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> proAll = myPromise</span><br><span class="line"> .all([pro1, pro2, pro3])</span><br><span class="line"> .then(</span><br><span class="line"> (res) => <span class="built_in">console</span>.log(res) <span class="comment">// 3秒之后打印 ["1", "2", "3"]</span></span><br><span class="line"> )</span><br><span class="line"> .catch(<span class="function">(<span class="params">e</span>) =></span> {</span><br><span class="line"> <span class="built_in">console</span>.log(e); <span class="comment">// “错误”</span></span><br><span class="line"> });</span><br></pre></td></tr></table></figure><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/cs.png"></p><p>其中一个失败时</p><p><img src= "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="https://cdn.jsdelivr.net/gh/lp-Imagine/lp-Imagine@main/images/cs2.png"></p><blockquote><p><strong>总结:</strong><br>1、Promise.all()接受一个 Array 类型的参数<br>2、只有数组中全部的 Promise 都变为 resolve 的时候<br>3、返回一个新的 Promise 实例<br>4、只要有一个失败,状态就变成 rejected</p></blockquote><hr><h2 id="myPromise-race"><a href="#myPromise-race" class="headerlink" title="myPromise.race"></a>myPromise.race</h2><p>返回一个 Promsie,接收一个数组作为参数,一旦数组其中一项执行,就返回执行结果。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">myPromise.race = <span class="function"><span class="keyword">function</span> (<span class="params">arr</span>) </span>{</span><br><span class="line"> <span class="keyword">let</span> resolve;</span><br><span class="line"> <span class="keyword">let</span> reject;</span><br><span class="line"> <span class="keyword">const</span> promise = <span class="keyword">new</span> myPromsie(<span class="function">(<span class="params">r, j</span>) =></span> {</span><br><span class="line"> resolve = r;</span><br><span class="line"> reject = j;</span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> item <span class="keyword">of</span> arr) {</span><br><span class="line"> myPromise.resolve(item).then(</span><br><span class="line"> (val) => resolve(val),</span><br><span class="line"> (err) => reject(err)</span><br><span class="line"> );</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> promise;</span><br><span class="line">};</span><br></pre></td></tr></table></figure><hr><h2 id="myPromise-any"><a href="#myPromise-any" class="headerlink" title="myPromise.any"></a>myPromise.any</h2><p>只要其中一个 Promsie 成功,就返回成功的那个;如果没有一个成功,就返回失败,把失败的错误集中在一起。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">myPromise.any = <span class="function"><span class="keyword">function</span> (<span class="params">arr</span>) </span>{</span><br><span class="line"> <span class="keyword">let</span> resolve;</span><br><span class="line"> <span class="keyword">let</span> reject;</span><br><span class="line"> <span class="keyword">const</span> promise = <span class="keyword">new</span> myPromise(<span class="function">(<span class="params">r, j</span>) =></span> {</span><br><span class="line"> resolve = r;</span><br><span class="line"> reject = j;</span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> errCount = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">let</span> arrCount = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> item <span class="keyword">of</span> arr) {</span><br><span class="line"> arrCount += <span class="number">1</span>;</span><br><span class="line"> myPromise.resolve(item).then(</span><br><span class="line"> (val) => resolve(val),</span><br><span class="line"> (err) => {</span><br><span class="line"> errCount += <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> (errCount >= arrCount) {</span><br><span class="line"> reject(<span class="keyword">new</span> AggregateError(<span class="string">"所有Promsie都失败"</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">return</span> promise;</span><br><span class="line">};</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><p>上次把 Promise 简单的实现了基本功能,趁热打铁,我们来实现一下它里面的拓展方法。</p>
<h2 id="myPromise-prototype-catch"><a href="#myPromise-prototype-catch" class="headerlin</summary>
<category term="javascript" scheme="http://imagineblog.host/categories/javascript/"/>
<category term="javascript" scheme="http://imagineblog.host/tags/javascript/"/>
<category term="Promise" scheme="http://imagineblog.host/tags/Promise/"/>
</entry>
</feed>