-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
1515 lines (1098 loc) · 77.5 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">
<link rel="apple-touch-icon" sizes="180x180" href="/images/favicon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon.png">
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon.png">
<link rel="mask-icon" href="/images/favicon.png" color="#222">
<link rel="stylesheet" href="/css/main.css">
<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">
<script id="hexo-configurations">
var NexT = window.NexT || {};
var CONFIG = {"hostname":"xianzhiding.github.io","root":"/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":true,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.json"};
</script>
<meta name="description" content="w3cbest是一个专注前端开发、用户体验设计,提供大量最新前端前沿技术文章及资源。">
<meta property="og:type" content="website">
<meta property="og:title" content="前端开发 大前端 W3Cbest">
<meta property="og:url" content="https://xianzhiding.github.io/index.html">
<meta property="og:site_name" content="前端开发 大前端 W3Cbest">
<meta property="og:description" content="w3cbest是一个专注前端开发、用户体验设计,提供大量最新前端前沿技术文章及资源。">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="Tom">
<meta property="article:tag" content="前端开发,es5,es6,es10,css,javascript,html,flexbox,grid,echarts">
<meta name="twitter:card" content="summary">
<link rel="canonical" href="https://xianzhiding.github.io/">
<script id="page-configurations">
// https://hexo.io/docs/variables.html
CONFIG.page = {
sidebar: "",
isHome : true,
isPost : false,
lang : 'zh-CN'
};
</script>
<title>前端开发 大前端 W3Cbest</title>
<noscript>
<style>
.use-motion .brand,
.use-motion .menu-item,
.sidebar-inner,
.use-motion .post-block,
.use-motion .pagination,
.use-motion .comments,
.use-motion .post-header,
.use-motion .post-body,
.use-motion .collection-header { opacity: initial; }
.use-motion .site-title,
.use-motion .site-subtitle {
opacity: initial;
top: initial;
}
.use-motion .logo-line-before i { left: initial; }
.use-motion .logo-line-after i { right: initial; }
</style>
</noscript>
</head>
<body itemscope itemtype="http://schema.org/WebPage">
<div class="container use-motion">
<div class="headband"></div>
<header class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"><div class="site-brand-container">
<div class="site-nav-toggle">
<div class="toggle" aria-label="切换导航栏">
<span class="toggle-line toggle-line-first"></span>
<span class="toggle-line toggle-line-middle"></span>
<span class="toggle-line toggle-line-last"></span>
</div>
</div>
<div class="site-meta">
<a href="/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<h1 class="site-title">前端开发 大前端 W3Cbest</h1>
<span class="logo-line-after"><i></i></span>
</a>
<p class="site-subtitle" itemprop="description">一个专注 WEB 开发的技术博客</p>
</div>
<div class="site-nav-right">
<div class="toggle popup-trigger">
<i class="fa fa-search fa-fw fa-lg"></i>
</div>
</div>
</div>
<nav class="site-nav">
<ul id="menu" class="main-menu menu">
<li class="menu-item menu-item-home">
<a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>
</li>
<li class="menu-item menu-item-archives">
<a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>
</li>
<li class="menu-item menu-item-search">
<a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
</a>
</li>
</ul>
</nav>
<div class="search-pop-overlay">
<div class="popup search-popup">
<div class="search-header">
<span class="search-icon">
<i class="fa fa-search"></i>
</span>
<div class="search-input-container">
<input autocomplete="off" autocapitalize="off"
placeholder="搜索..." spellcheck="false"
type="search" class="search-input">
</div>
<span class="popup-btn-close">
<i class="fa fa-times-circle"></i>
</span>
</div>
<div id="search-result">
<div id="no-result">
<i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
</div>
</div>
</div>
</div>
</div>
</header>
<div class="back-to-top">
<i class="fa fa-arrow-up"></i>
<span>0%</span>
</div>
<div class="reading-progress-bar"></div>
<main class="main">
<div class="main-inner">
<div class="content-wrap">
<div class="content index posts-expand">
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="https://xianzhiding.github.io/2023/06/21/vue%E7%BB%84%E4%BB%B6%E4%B9%8B%E9%97%B4%E4%BC%A0%E5%80%BC/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="Tom">
<meta itemprop="description" content="w3cbest是一个专注前端开发、用户体验设计,提供大量最新前端前沿技术文章及资源。">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="前端开发 大前端 W3Cbest">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2023/06/21/vue%E7%BB%84%E4%BB%B6%E4%B9%8B%E9%97%B4%E4%BC%A0%E5%80%BC/" class="post-title-link" itemprop="url">关于Vue组件之间的传值</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2023-06-21 00:00:00" itemprop="dateCreated datePublished" datetime="2023-06-21T00:00:00+08:00">2023-06-21</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h2 id="组件传值-通信-式"><a href="#组件传值-通信-式" class="headerlink" title="组件传值(通信)式"></a>组件传值(通信)式</h2><p><strong>父传后代(后代拿到了父的数据)</strong></p>
<ul>
<li>父组件引入子组件,绑定数据,<br> 优点:子组件通过props来接收父组件绑定的数据。这种方式父传子很方便,但是父传给孙子辈分的组件就很麻烦 (父->子->孙)<br> 缺点:子组件无法直接修改父组件数据,属单向绑定</li>
<li>子组件直接使用父组件的数据,<br> 优点:子组件通过this.$parent.xxx使用父组件的数据<br> 缺点:子组件可直接修改父组件数据</li>
<li>依赖注入 provide / inject<br> 优点:这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。<br> 缺点:不容易定位祖先组件注入位置</li>
</ul>
<p><strong>后代向父组件传值</strong></p>
<ul>
<li>子组件通过触发事件向父组件传值 $.emit()</li>
<li>使用ref属性</li>
<li>使用slot插槽方式</li>
</ul>
<p><strong>兄弟之间组件传值</strong></p>
<ul>
<li>eventBus</li>
</ul>
<h2 id="父组件直接修改子组件的值,子组件直接修改父组件的值"><a href="#父组件直接修改子组件的值,子组件直接修改父组件的值" class="headerlink" title="父组件直接修改子组件的值,子组件直接修改父组件的值"></a>父组件直接修改子组件的值,子组件直接修改父组件的值</h2><ul>
<li>父组件修改子组值 <pre class="language-none"><code class="language-none"><Child ref="setChild"></Child>
this.$refs.setChild.xxx = '修改值'</code></pre></li>
<li>子组件直接修改父组件的值<pre class="language-none"><code class="language-none">this.$parent.xxx = '修改值'</code></pre></li>
</ul>
<h2 id="eventBus示例"><a href="#eventBus示例" class="headerlink" title="eventBus示例"></a>eventBus示例</h2><p><strong>初始化时全局定义</strong></p>
<pre><code>// eventBus.js 中
import Vue from 'vue'
// 第一种定义方式
Vue.prototype.$eventBus = new Vue()
// 第二种定义方式
window.eventBus = new Vue();
// 第三种定义方式
export const eventBus = new Vue()
</code></pre>
<p><strong>触发事件</strong></p>
<pre><code>//使用方式一定义时
// params 多个参数
this.$eventBus.$emit('eventName', param1,param2,...)
//使用方式二定义时
eventBus.$emit('eventName', param1,param2,...)
</code></pre>
<p><strong>监听事件</strong></p>
<pre><code>//使用方式一定义时
this.$eventBus.$on('eventName', (param1,param2,...)=>{
//需要执行 逻辑代码
// params 多个参数
})
//使用方式二定义时
eventBus.$on('eventName', (param1,param2,...)=>{
//需要执行 逻辑代码
})
</code></pre>
<p><strong>移除事件</strong></p>
<p>在开发的过程中,我们要及时移除不使用的 eventBus ,原因:</p>
<ul>
<li>为了避免在监听时,事件被反复触发</li>
<li>由于热更新,事件可能会被多次绑定监听,这时也需要移除事件监听</li>
<li> 未及时移除的 eventBus 会导致内存泄漏</li>
</ul>
<pre class="language-//使用方式一定义时" data-language="//使用方式一定义时"><code class="language-//使用方式一定义时">this.$eventBus.$off('eventName');
//使用方式二定义时
eventBus.$off('eventName');
//使用方式三定义时
eventBus.$off.$on('eventName');</code></pre>
<h2 id="vue踩坑之eventBus-on多次触发的问题"><a href="#vue踩坑之eventBus-on多次触发的问题" class="headerlink" title="vue踩坑之eventBus.$on多次触发的问题"></a>vue踩坑之eventBus.$on多次触发的问题</h2><p><code>this.root.Bus.on</code>实际是向Bus容器中添加一个事件监听器,当页面跳转时,原来的vue组件被注销,但是原来vue组件向Bus容器中添加的事件监听器并不会被移除。因此,当下次进入这个vue组件对应的页面时,执行到<code>this.root.Bus.on</code>时,又会向Bus容器中添加一个重复的事件监听器,以此类推,导致Bus容器中有很多个一模一样的事件监听器,从而导致事件只被触发一次,但是回调函数被执行多次的现象。</p>
<p>解决方法:</p>
<p>方法1:在每次on之前调用off卸载掉事件</p>
<pre><code>created(){
eventBus.$off.$on("fetchList",()=>{
this.getListData()
})
}
</code></pre>
<p>方法2:在生命周期<code>beforeDestroy</code> <code>destroyed</code>里面调用$off卸载掉事件</p>
<pre><code>beforeDestroy(){
eventBus.$off("fetchList")
}
</code></pre>
<p>如果这变得重复,你可以写一个mixin来自动化。</p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="https://xianzhiding.github.io/2023/06/19/vue%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="Tom">
<meta itemprop="description" content="w3cbest是一个专注前端开发、用户体验设计,提供大量最新前端前沿技术文章及资源。">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="前端开发 大前端 W3Cbest">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2023/06/19/vue%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/" class="post-title-link" itemprop="url">关于Vue的生命周期</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2023-06-19 00:00:00" itemprop="dateCreated datePublished" datetime="2023-06-19T00:00:00+08:00">2023-06-19</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<blockquote>
<p>所有生命周期钩子的 <code>this</code> 上下文将自动绑定至实例中,因此你可以访问 data、computed 和 methods。这意味着你不应该使用箭头函数来定义一个生命周期方法 (例如 <code>created: () => this.fetchTodos()</code>)。因为箭头函数绑定了父级上下文,所以 <code>this</code> 不会指向预期的组件实例,并且<code>this.fetchTodos</code> 将会是 undefined。</p>
</blockquote>
<h2 id="vue的生命周期有哪些?"><a href="#vue的生命周期有哪些?" class="headerlink" title="vue的生命周期有哪些?"></a>vue的生命周期有哪些?</h2><h3 id="beforCreated"><a href="#beforCreated" class="headerlink" title="beforCreated"></a>beforCreated</h3><p><strong>类型:</strong><code>Function</code></p>
<p><strong>详细:</strong><br>在实例初始化之后,进行数据侦听和事件/侦听器的配置之前同步调用。</p>
<p><strong>参考:</strong><a target="_blank" rel="noopener" href="https://v2.cn.vuejs.org/v2/guide/instance.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%BE%E7%A4%BA">生命周期图示</a></p>
<h3 id="created"><a href="#created" class="headerlink" title="created"></a>created</h3><p><strong>类型:</strong><code>Function</code></p>
<p><strong>详细:</strong><br>在实例创建完成后被立即同步调用。在这一步中,实例已完成对选项的处理,意味着以下内容已被配置完毕:数据侦听、计算属性、方法、事件/侦听器的回调函数。然而,挂载阶段还没开始,且 $el property 目前尚不可用。</p>
<p><strong>参考:</strong><a target="_blank" rel="noopener" href="https://v2.cn.vuejs.org/v2/guide/instance.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%BE%E7%A4%BA">生命周期图示</a></p>
<h3 id="beforMounted"><a href="#beforMounted" class="headerlink" title="beforMounted"></a>beforMounted</h3><p><strong>类型:</strong><code>Function</code></p>
<p><strong>详细:</strong><br>在挂载开始之前被调用:相关的 <code>render</code> 函数首次被调用。</p>
<p>该钩子在服务器端渲染期间不被调用。<br><strong>参考:</strong><a target="_blank" rel="noopener" href="https://v2.cn.vuejs.org/v2/guide/instance.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%BE%E7%A4%BA">生命周期图示</a></p>
<h3 id="mounted"><a href="#mounted" class="headerlink" title="mounted"></a>mounted</h3><p><strong>类型:</strong><code>Function</code></p>
<p><strong>详细:</strong><br>实例被挂载后调用,这时 <code>el</code> 被新创建的 <code>vm.$el</code> 替换了。如果根实例挂载到了一个文档内的元素上,当 <code>mounted</code> 被调用时 <code>vm.$el</code> 也在文档内。</p>
<p>注意 <code>mounted</code> 不会保证所有的子组件也都被挂载完成。如果你希望等到整个视图都渲染完毕再执行某些操作,可以在 <code>mounted</code> 内部使用 <a target="_blank" rel="noopener" href="https://v2.cn.vuejs.org/v2/api/#vm-nextTick">vm.$nextTick:</a></p>
<pre><code>mounted: function () {
this.$nextTick(function () {
// 仅在整个视图都被渲染之后才会运行的代码
})
}
</code></pre>
<p>该钩子在服务器端渲染期间不被调用。</p>
<p><strong>参考:</strong><a target="_blank" rel="noopener" href="https://v2.cn.vuejs.org/v2/guide/instance.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%BE%E7%A4%BA">生命周期图示</a></p>
<h3 id="beforUpdated"><a href="#beforUpdated" class="headerlink" title="beforUpdated"></a>beforUpdated</h3><p><strong>类型:</strong><code>Function</code></p>
<p><strong>详细:</strong><br>在数据发生改变后,DOM 被更新之前被调用。这里适合在现有 DOM 将要被更新之前访问它,比如移除手动添加的事件监听器。</p>
<p>该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务器端进行。</p>
<p><strong>参考:</strong><a target="_blank" rel="noopener" href="https://v2.cn.vuejs.org/v2/guide/instance.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%BE%E7%A4%BA">生命周期图示</a></p>
<h3 id="updated"><a href="#updated" class="headerlink" title="updated"></a>updated</h3><p><strong>类型:</strong><code>Function</code></p>
<p><strong>详细:</strong><br>在数据更改导致的虚拟 <code>DOM</code> 重新渲染和更新完毕之后被调用。</p>
<p>当这个钩子被调用时,组件 <code>DOM</code> 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 <code>watcher</code> 取而代之。</p>
<p>注意,<code>updated</code> 不会保证所有的子组件也都被重新渲染完毕。如果你希望等到整个视图都渲染完毕,可以在 <code>updated</code> 里使用 <a target="_blank" rel="noopener" href="https://v2.cn.vuejs.org/v2/api/#vm-nextTick">vm.$nextTick:</a></p>
<pre><code>updated: function () {
this.$nextTick(function () {
// 仅在整个视图都被重新渲染之后才会运行的代码
})
}
</code></pre>
<p>该钩子在服务器端渲染期间不被调用。</p>
<p><strong>参考:</strong><a target="_blank" rel="noopener" href="https://v2.cn.vuejs.org/v2/guide/instance.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%BE%E7%A4%BA">生命周期图示</a></p>
<h3 id="beforDestroy"><a href="#beforDestroy" class="headerlink" title="beforDestroy"></a>beforDestroy</h3><p><strong>类型:</strong><code>Function</code></p>
<p><strong>详细:</strong></p>
<p>实例销毁之前调用。在这一步,实例仍然完全可用。</p>
<p>该钩子在服务器端渲染期间不被调用。</p>
<p><strong>参考:</strong><a target="_blank" rel="noopener" href="https://v2.cn.vuejs.org/v2/guide/instance.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%BE%E7%A4%BA">生命周期图示</a></p>
<h3 id="destroyed"><a href="#destroyed" class="headerlink" title="destroyed"></a>destroyed</h3><p><strong>类型:</strong><code>Function</code></p>
<p><strong>详细:</strong></p>
<p>实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。</p>
<p>该钩子在服务器端渲染期间不被调用。</p>
<p><strong>参考:</strong><a target="_blank" rel="noopener" href="https://v2.cn.vuejs.org/v2/guide/instance.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%BE%E7%A4%BA">生命周期图示</a></p>
<h3 id="activated"><a href="#activated" class="headerlink" title="activated"></a>activated</h3><p><strong>类型:</strong><code>Function</code></p>
<p><strong>详细:</strong><br>被 keep-alive 缓存的组件激活时调用。</p>
<p>该钩子在服务器端渲染期间不被调用。</p>
<p><strong>参考:</strong><br><a target="_blank" rel="noopener" href="https://v2.cn.vuejs.org/v2/api/#keep-alive">构建组件 - keep-alive</a></li><br><a target="_blank" rel="noopener" href="https://v2.cn.vuejs.org/v2/guide/components-dynamic-async.html#%E5%9C%A8%E5%8A%A8%E6%80%81%E7%BB%84%E4%BB%B6%E4%B8%8A%E4%BD%BF%E7%94%A8-keep-alive">动态组件 - keep-alive</a></p>
<h3 id="deactivated"><a href="#deactivated" class="headerlink" title="deactivated"></a>deactivated</h3><p><strong>类型:</strong><code>Function</code></p>
<p><strong>详细:</strong>被 keep-alive 缓存的组件失活时调用。</p>
<p>该钩子在服务器端渲染期间不被调用。</p>
<p><strong>参考:</strong><br><a target="_blank" rel="noopener" href="https://v2.cn.vuejs.org/v2/api/#keep-alive">构建组件 - keep-alive</a></li><br><a target="_blank" rel="noopener" href="https://v2.cn.vuejs.org/v2/guide/components-dynamic-async.html#%E5%9C%A8%E5%8A%A8%E6%80%81%E7%BB%84%E4%BB%B6%E4%B8%8A%E4%BD%BF%E7%94%A8-keep-alive">动态组件 - keep-alive</a></p>
<h3 id="errorCaptured"><a href="#errorCaptured" class="headerlink" title="errorCaptured"></a>errorCaptured</h3><p><strong>类型:</strong><code>(err: Error, vm: Component, info: string) => ?boolean</code></p>
<p><strong>详细:</strong></p>
<p>在捕获一个来自后代组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。</p>
<p><strong>参考:</strong><a target="_blank" rel="noopener" href="https://v2.cn.vuejs.org/v2/guide/render-function.html">渲染函数</a></p>
<h2 id="进入组件会执行那些生命周期"><a href="#进入组件会执行那些生命周期" class="headerlink" title="进入组件会执行那些生命周期"></a>进入组件会执行那些生命周期</h2><p>进入到页面或进入到组件,会执行 <code>beforeCreated</code> <code>created</code> <code>beforMounted</code> <code>mounted</code>这四个生命周期。<code>beforeCreated</code>在实例初始化后进行数据监听和事件监听之前同步调用。<code>created</code>在实例创建完成后被立即同步调用。<code>beforeCreated</code> 和 <code>created</code> 无法获取到 <code>DOM</code>,<code>mounted</code>时<code>DOM</code>被创建,此时可以获取到<code>DOM</code></p>
<h2 id="父组件引入子组件,执行生命周期的顺序是什么"><a href="#父组件引入子组件,执行生命周期的顺序是什么" class="headerlink" title="父组件引入子组件,执行生命周期的顺序是什么"></a>父组件引入子组件,执行生命周期的顺序是什么</h2><ul>
<li>父组件引入子组件会先执行父组件的<code>beforeCreated</code> <code>created</code> <code>beforMounted</code> 前三个生命周期。</li>
<li>再执行子组件的<code>beforeCreated</code> <code>created</code> <code>beforMounted</code> <code>mounted</code>前四个生命周期。</li>
<li>然后再执行父组件的 <code>mounted</code>生命周期</li>
</ul>
<h2 id="在created中获取DOM"><a href="#在created中获取DOM" class="headerlink" title="在created中获取DOM"></a>在created中获取DOM</h2><p><code>created</code>在实例创建完成后被立即同步调用。但此时DOM还未被创建,只有通过异步调用后,在异步中可以获取到DOM<br>例如:setTimeout、请求接口、$nextTick, $refs等</p>
<h2 id="发送请求在created还是mounted"><a href="#发送请求在created还是mounted" class="headerlink" title="发送请求在created还是mounted?"></a>发送请求在created还是mounted?</h2><p>发送请求在created还是mounted这个问题具体要看项目和业务的情况</p>
<ul>
<li>如果组件的加载顺序是父组件引入了子组件,那么会先执行父组件的<code>beforeCreated</code> <code>created</code>和<code>beforMounted</code>的前三个生命周期,再执行子组件的再执行子组件的<code>beforeCreated</code> <code>created</code> <code>beforMounted</code> <code>mounted</code>前四个生命周期,然后再执行父组件的 <code>mounted</code>生命周期。</li>
<li>如果业务是父组件引入子组件,并且优先加载子组件的数据,那么在父组件中当前的请求应放在<code>mounted</code>中。</li>
<li>如果当前组件没有依赖关系那么放在哪个生命周期中请求都可以的。</li>
</ul>
<h2 id="beforCreated-中发请求的优劣势,beforeCreate和created有什么区别"><a href="#beforCreated-中发请求的优劣势,beforeCreate和created有什么区别" class="headerlink" title="beforCreated 中发请求的优劣势,beforeCreate和created有什么区别?"></a>beforCreated 中发请求的优劣势,beforeCreate和created有什么区别?</h2><p>优势:可以提前加载好数据,整理数据<br>劣势:如果请求是在methods封装好了,在beforeCreate调用的时候,beforeCreate阶段是拿不到methods里面的方法的(会报错了) 。</p>
<p><strong>区别:</strong></p>
<table>
<thead>
<tr>
<th align="left"></th>
<th align="right">$data</th>
<th align="center">methods</th>
</tr>
</thead>
<tbody><tr>
<td align="left">beforeCreate</td>
<td align="right">无</td>
<td align="center">无法获取</td>
</tr>
<tr>
<td align="left">created</td>
<td align="right">有</td>
<td align="center">可以获取</td>
</tr>
</tbody></table>
<h2 id="created和mounted的区别"><a href="#created和mounted的区别" class="headerlink" title="created和mounted的区别"></a>created和mounted的区别</h2><p><code>created()</code> 和 <code>mounted()</code> 之间的根本区别在于访问DOM,在 <code>created()</code> 中返回 null,在 <code>mounted()</code> 中返回 DOM 元素。因此,任何 DOM 操作,甚至使用诸如 querySelector 之类的方法获取 DOM 元素结构将无法在 <code>created()</code> 中使用。因此根据这点区别 <code>created()</code> 非常适合调用 API,而 <code>mounted()</code> 非常适合在 DOM 元素完全加载后执行任何操作。</p>
<h2 id="加入keep-alive会执行哪些生命周期?"><a href="#加入keep-alive会执行哪些生命周期?" class="headerlink" title="加入keep-alive会执行哪些生命周期?"></a>加入keep-alive会执行哪些生命周期?</h2><p>如果使用了keep-alive组件会额外增加2个生命周期<code>activated</code> <code>deactivated</code><br>如果当前组件加入了keep-alive第一次进入这个组件会执行5个生命周期 <code>beforeCreated</code> <code>created</code> <code>beforMounted</code> <code>mounted</code> <code>activated</code></p>
<h2 id="第二次或者第N次进去组件会执行哪些生命周期?"><a href="#第二次或者第N次进去组件会执行哪些生命周期?" class="headerlink" title="第二次或者第N次进去组件会执行哪些生命周期?"></a>第二次或者第N次进去组件会执行哪些生命周期?</h2><p>如果当前组件加入了keep-alive,只会执行一个<code>activated</code>生命周期</p>
<p>如果没有加入keep-alive就会执行<code>beforeCreated</code> <code>created</code> <code>beforMounted</code> <code>mounted</code>前四个生命周期</p>
<h2 id="你在什么情况下用过哪些生命周期?说一说生命周期使用场景"><a href="#你在什么情况下用过哪些生命周期?说一说生命周期使用场景" class="headerlink" title="你在什么情况下用过哪些生命周期?说一说生命周期使用场景"></a>你在什么情况下用过哪些生命周期?说一说生命周期使用场景</h2><p>created ===> 单组件请求<br>mounted ===> 同步可以获取dom,如果先子组件请求后父组件请求<br>activated ===> 用于缓存同页面使用,判断id是否相等,如果不相同发起请求<br>destroyed ===> 关闭页面记录浏览位置,初始化的时候从上一次的历史开始浏览</p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="https://xianzhiding.github.io/2023/06/10/vue%E5%9F%BA%E7%A1%80/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="Tom">
<meta itemprop="description" content="w3cbest是一个专注前端开发、用户体验设计,提供大量最新前端前沿技术文章及资源。">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="前端开发 大前端 W3Cbest">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2023/06/10/vue%E5%9F%BA%E7%A1%80/" class="post-title-link" itemprop="url">Vue的基础原理</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2023-06-10 00:00:00" itemprop="dateCreated datePublished" datetime="2023-06-10T00:00:00+08:00">2023-06-10</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h2 id="vue的设计原理"><a href="#vue的设计原理" class="headerlink" title="vue的设计原理"></a>vue的设计原理</h2><ul>
<li>渐进式的JavaScript框架:vue的核心只关注视图层,容易上手,还便于与第三方库或既有项目整合</li>
<li>易用性:vue提供数据响应式、声明式模板语法和基于配置的组件系统等核心特性。这些使我们只需关注应用的核心业务即可。</li>
<li>灵活性:渐进式框架最大优点就是灵活性,如果应用足够小,我们可能仅需要vue核心特性即可完成功能;随着应用规模的不断扩大,我们才可能逐渐引入路由、状态管理、vue-cli等库和工具,不管是应用体积还是学习难度都是一个逐渐增加的平和曲线。</li>
<li>高效性:超快的虚拟DOM和diff算法使我们的应用拥有最佳的性能表现。追求高效的过程还在继续,vue3中引入Proxy对数据响应式改进以及编译器中对于静态内容编译的改进都会让vue更加高效。</li>
</ul>
<h2 id="vue的常见性能优化"><a href="#vue的常见性能优化" class="headerlink" title="vue的常见性能优化"></a>vue的常见性能优化</h2><ul>
<li>路由懒加载</li>
<li>keep-alive缓存页面</li>
<li>使用v-show复用DOM</li>
<li>v-for遍历时避免同时使用v-if</li>
<li>长列表性能优化,<br> 如果列表是纯粹的数据展示,不作任何改变,就不需要做响应化,<br> 如果是大数据列表,可采用虚拟滚动,只渲染可见区域内容</li>
<li>事件的销毁,解绑全部指令及事件监听器</li>
<li>图片懒加载</li>
<li>第三方插件按需引入</li>
</ul>
<h2 id="v-model的实现原理"><a href="#v-model的实现原理" class="headerlink" title="v-model的实现原理"></a>v-model的实现原理</h2><p>绑定响应数据,触发input事件并传递数据</p>
<h2 id="修改computed计算属性的结果值"><a href="#修改computed计算属性的结果值" class="headerlink" title="修改computed计算属性的结果值"></a>修改computed计算属性的结果值</h2><ul>
<li>需要通过get/set写法</li>
<li>当前组件v-model绑定的值是computed来的,需要通过get/set写法</li>
</ul>
<h2 id="computed和watch的区别"><a href="#computed和watch的区别" class="headerlink" title="computed和watch的区别"></a>computed和watch的区别</h2><p><strong>对于computed</strong></p>
<ul>
<li>计算属性的结果会被缓存,只有依赖的数据发生变化才会重新计算</li>
<li>不支持异步,computed中有异步操作时,无法监听数据的变化</li>
<li>computed的值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data声明过,或者父组件传递过来的props中的数据进行计算的。</li>
<li>如果一个属性是由其他属性计算而来的,这个属性依赖其他的属性,一般会使用computed</li>
<li>如果computed属性的属性值是函数,那么默认使用get方法,函数的返回值就是属性的属性值;在computed中,属性有一个get方法和一个set方法,当数据发生变化时,会调用set方法。</li>
</ul>
<p><strong>对于watch</strong></p>
<ul>
<li>它支持缓存,只要数据变化时,就会触发响应的操作</li>
<li>支持异步监听</li>
<li>监听的函数接收两个参数,第一个参数是最新的值,第二个是变化之前的值</li>
<li>当一个属性发生变化时,就需要执行相应的操作</li>
<li>监听数据必须是data中声明的或者父组件传递过来的props中的数据,当发生变化时,会触发其他操作,函数有两个的参数:<ul>
<li>immediate:组件加载立即触发回调函数</li>
<li>deep:深度监听,发现数据内部的变化,在复杂数据类型中使用,例如数组中的对象发生变化。需要注意的是,deep无法监听到数组和对象内部的变化。</li>
</ul>
</li>
</ul>
<p><strong>总结</strong></p>
<ul>
<li>computed计算属性:computed的值有缓存,依赖其他属性值,只有它依赖的属性值发生变化,下一次获取computed的值时才会重新计算computed的值。</li>
<li>watch监听器:更多的是观察作用,无缓存,类似于某些数据的监听回调,每当监听的数据发生变化时,都会执行回调进行后续操作。</li>
</ul>
<p><strong>运用场景</strong></p>
<ul>
<li>当需要进行数据计算,并且依赖于其他数据时,应使用computed,因为可以利用computed的缓存特性,避免每次获取值时都要重新计算。</li>
<li>当需要在数据变化时执行异步或开销较大的操作时,应该使用watch,使用watch选项允许执行异步操作,限制执行该操作的频率,并在得到最终结果前,设置中间状态。这些都是计算属性无法做到的。</li>
</ul>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="https://xianzhiding.github.io/2023/04/02/javascript%E9%97%AD%E5%8C%85/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="Tom">
<meta itemprop="description" content="w3cbest是一个专注前端开发、用户体验设计,提供大量最新前端前沿技术文章及资源。">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="前端开发 大前端 W3Cbest">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2023/04/02/javascript%E9%97%AD%E5%8C%85/" class="post-title-link" itemprop="url">闭包,什么是JavaScript闭包</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2023-04-02 14:07:06" itemprop="dateCreated datePublished" datetime="2023-04-02T14:07:06+08:00">2023-04-02</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p>闭包是 JavaScript 中最强大的特性之一。JavaScript 允许函数嵌套,并且内部函数具有定义在外部函数中的所有变量和函数(以及外部函数能访问的所有变量和函数)的完全访问权限。</p>
<p>但是,外部函数却不能访问定义在内部函数中的变量和函数。这给内部函数的变量提供了一种封装。</p>
<p>此外,由于内部函数可以访问外部函数的作用域,因此当内部函数生存周期大于外部函数时,外部函数中定义的变量和函数的生存周期将比内部函数执行的持续时间要长。当内部函数以某一种方式被任何一个外部函数之外的任何作用域访问时,就会创建闭包。</p>
<pre class="language-none"><code class="language-none">// 外部函数定义了一个名为“name”的变量
const pet = function (name) {
const getName = function () {
// 内部函数可以访问外部函数的“name”变量
return name;
};
return getName; // 返回内部函数,从而将其暴露给外部作用域
};
const myPet = pet("Vivie");
console.log(myPet()); // "Vivie"</code></pre>
<p>实际上可能会比上面的代码复杂的多。它可以返回一个包含用于操作外部函数的内部变量的方法的对象。</p>
<pre class="language-none"><code class="language-none">const createPet = function (name) {
let sex;
const pet = {
// 在这个上下文中:setName(newName) 等价于 setName: function (newName)
setName(newName) {
name = newName;
},
getName() {
return name;
},
getSex() {
return sex;
},
setSex(newSex) {
if (
typeof newSex === "string" &&
(newSex.toLowerCase() === "male" || newSex.toLowerCase() === "female")
) {
sex = newSex;
}
},
};
return pet;
};
const pet = createPet("Vivie");
console.log(pet.getName()); // Vivie
pet.setName("Oliver");
pet.setSex("male");
console.log(pet.getSex()); // male
console.log(pet.getName()); // Oliver</code></pre>
<p>在上面的代码中,外部函数的 name 变量对内部函数来说是可访问的,而除了通过内部函数本身,没有其他任何方法可以取得内部的变量。内部函数的内部变量就像对外部参数和变量的保险柜。它们会为内部函数保留“稳定”而又“被封装”的数据参与运行。而这些内部函数甚至不会被分配给一个变量,或者有个名称。</p>
<pre class="language-none"><code class="language-none">const getCode = (function () {
const apiCode = "0]Eal(eh&2"; // 我们不希望外部能够修改的代码......
return function () {
return apiCode;
};
})();
console.log(getCode()); // "0]Eal(eh&2"</code></pre>
<p>备注: 使用闭包时需要注意许多陷阱!</p>
<p>如果一个闭包的函数定义了一个和外部外部的某个变量名称相同的变量,那么这个闭包将无法引用外部作用域中的这个变量。(内部作用域的变量“覆盖”外部作用域,直至程序退出内部作用域。可以将其视作命名冲突。)</p>
<pre class="language-none"><code class="language-none">const createPet = function (name) {
// 外部函数定义了一个名为“name”的变量。
return {
setName(name) {
// 闭包函数还定义了一个名为“name”的变量。
name = name; // 我们如何访问外部函数定义的“name”?
},
};
};</code></pre>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="https://xianzhiding.github.io/2021/08/25/%E5%89%8D%E7%AB%AF%E7%BC%93%E5%AD%98%E6%8A%80%E6%9C%AF/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="Tom">
<meta itemprop="description" content="w3cbest是一个专注前端开发、用户体验设计,提供大量最新前端前沿技术文章及资源。">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="前端开发 大前端 W3Cbest">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2021/08/25/%E5%89%8D%E7%AB%AF%E7%BC%93%E5%AD%98%E6%8A%80%E6%9C%AF/" class="post-title-link" itemprop="url">前端缓存技术</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2021-08-25 00:00:00" itemprop="dateCreated datePublished" datetime="2021-08-25T00:00:00+08:00">2021-08-25</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h2 id="思路:加载列表数据切数据不进行额外操作,做数据优化"><a href="#思路:加载列表数据切数据不进行额外操作,做数据优化" class="headerlink" title="思路:加载列表数据切数据不进行额外操作,做数据优化"></a>思路:加载列表数据切数据不进行额外操作,做数据优化</h2><ul>
<li>当页面第一次加载先判断本地储存中有没有旧数据 //储存数据格式{time:Date.now(), data}</li>
<li>没有旧数据直接发送请求,并将数据储存本地</li>
<li>有旧数据并且数据没有过期,就使用本地储存的旧数据</li>
</ul>
<pre class="language-none"><code class="language-none">init(){
<!-- 1,获取本地数据 -->
const getData = sessionStorage.getItem('key');
<!-- 2,判断数据是否存在 -->
if(!getData){
this.getData()
}else{
<!-- 定义过期时间 (如:10s) -->
if(Date.new() - getData.time > 1000*10){
<!-- 如果时间超过过期时间 重新发送请求 -->
this.getData()
}else{
<!-- 如果时间未超过过期时间 使用本地储存数据 -->
this.render(getData.data);
}
}
},
getData(){
<!-- 没有旧数据直接发送请求 -->
request('url').then(data=>{
<!-- 并将数据储存本地 -->
sessionStorage.setItem('key',{time: Date.new(), data});
this.render(data)
})
},
render(data){
<!-- 这里是数据展示 -->
console.log(data)
}</code></pre>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="https://xianzhiding.github.io/2021/07/12/%E5%B0%81%E8%A3%85Promise%E8%AF%B7%E6%B1%82request/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="Tom">
<meta itemprop="description" content="w3cbest是一个专注前端开发、用户体验设计,提供大量最新前端前沿技术文章及资源。">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="前端开发 大前端 W3Cbest">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2021/07/12/%E5%B0%81%E8%A3%85Promise%E8%AF%B7%E6%B1%82request/" class="post-title-link" itemprop="url">小程序封装Promise请求</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2021-07-12 00:00:00" itemprop="dateCreated datePublished" datetime="2021-07-12T00:00:00+08:00">2021-07-12</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p>思路:</p>
<pre class="language-none"><code class="language-none">let url = 'http://localhost:8080';
let requestTotal = 0;
const request = (params) =>{
requestTotal++;
wx.showLoading({
title: '加载中...',
mask: true
})
return new Promise((resolve, reject) =>{
wx.request({
url: url + params.url,
data: params.data || {},
method: params.method || 'GET',
header: {'content-type': 'application/x-www-form-urlencoded;charset=UTF-8'},
success:(result)=>{
resolve(result.data)
},
fail:(error)=>{
console.log(error);
reject(error)
},
complete:()=>{
requestTotal--;
if(requestTotal===0){
wx.hideLoading()
}
}
})
})
}</code></pre>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="https://xianzhiding.github.io/2021/04/19/color-scheme/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="Tom">
<meta itemprop="description" content="w3cbest是一个专注前端开发、用户体验设计,提供大量最新前端前沿技术文章及资源。">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="前端开发 大前端 W3Cbest">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2021/04/19/color-scheme/" class="post-title-link" itemprop="url">适配深色模式方案</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2021-04-19 09:40:38" itemprop="dateCreated datePublished" datetime="2021-04-19T09:40:38+08:00">2021-04-19</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h2 id="1-声明-color-scheme"><a href="#1-声明-color-scheme" class="headerlink" title="1.声明 color-scheme"></a>1.声明 color-scheme</h2><p>有两种方式。</p>
<h3 id="1-1-meta"><a href="#1-1-meta" class="headerlink" title="1.1 meta"></a>1.1 meta</h3><p>在head中声明 meta,声明当前页面支持 light 和 dark 两种模式,系统切换到深色模式时,浏览器默认样式也会切换到深色;</p>
<pre class="language-bash" data-language="bash"><code class="language-bash"><span class="token operator"><</span>meta <span class="token assign-left variable">name</span><span class="token operator">=</span><span class="token string">"color-scheme"</span> <span class="token assign-left variable">content</span><span class="token operator">=</span><span class="token string">"light dark"</span><span class="token operator">></span></code></pre>
<h3 id="1-2-CSS"><a href="#1-2-CSS" class="headerlink" title="1.2 CSS"></a>1.2 CSS</h3><p>下面的 css 同样可以实现上面 meta 声明的效果</p>
<pre class="language-bash" data-language="bash"><code class="language-bash">:root <span class="token punctuation">{</span>
color-scheme: light dark<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>注意:此声明并非为页面做自动适配,只影响浏览器默认样式</p>
<p>更多信息可查阅:<br> W3C文档:<a target="_blank" rel="noopener" href="https://drafts.csswg.org/css-color-adjust-1/"> CSS Color Adjustment Module Level 1</a><br> 微信开放文档:<a target="_blank" rel="noopener" href="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/DarkMode.html">DarkMode 适配指南</a></p>
<h2 id="2-通过-CSS-媒体查询"><a href="#2-通过-CSS-媒体查询" class="headerlink" title="2.通过 CSS 媒体查询"></a>2.通过 CSS 媒体查询</h2><p>prefers-color-scheme CSS 媒体特性用于检测用户是否有将系统的主题色设置为亮色或者暗色。</p>
<p>no-preference<br>表示系统未得知用户在这方面的选项。在布尔值上下文中,其执行结果为 false。</p>
<p>light<br>表示用户已告知系统他们选择使用浅色主题的界面。</p>
<p>dark<br>表示用户已告知系统他们选择使用暗色主题的界面。</p>
<pre class="language-bash" data-language="bash"><code class="language-bash">:root <span class="token punctuation">{</span>
color-scheme: light dark<span class="token punctuation">;</span>
background: white<span class="token punctuation">;</span>
color: black<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
@media <span class="token punctuation">(</span>prefers-color-scheme: dark<span class="token punctuation">)</span> <span class="token punctuation">{</span>
:root <span class="token punctuation">{</span>
background: black<span class="token punctuation">;</span>
color: white<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>颜色较多的情况,建议使用CSS变量对颜色值进行管理</p>
<pre class="language-bash" data-language="bash"><code class="language-bash">:root <span class="token punctuation">{</span>
color-scheme: light dark<span class="token punctuation">;</span>
--nav-bg-color: <span class="token comment">#F7F7F7;</span>
--content-bg-color: <span class="token comment">#FFFFFF;</span>
--font-color: rgba<span class="token punctuation">(</span><span class="token number">0,0</span>,0,.9<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
@media <span class="token punctuation">(</span>prefers-color-scheme: dark<span class="token punctuation">)</span> <span class="token punctuation">{</span>
:root <span class="token punctuation">{</span>
--nav-bg-color: <span class="token comment">#2F2F2F;</span>
--content-bg-color: <span class="token comment">#2C2C2C;</span>
--font-color: rgba<span class="token punctuation">(</span><span class="token number">255</span>, <span class="token number">255</span>, <span class="token number">255</span>, .8<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
:root <span class="token punctuation">{</span>
color: var<span class="token punctuation">(</span>--font-color<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
.header <span class="token punctuation">{</span>
background-color: var<span class="token punctuation">(</span>--nav-bg-color<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
.content <span class="token punctuation">{</span>
background-color: var<span class="token punctuation">(</span>--content-bg-color<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="3-图片适配"><a href="#3-图片适配" class="headerlink" title="3.图片适配"></a>3.图片适配</h2><p>利用picture+source标签,设置不同模式下的图片 url。</p>
<p>HTML <picture>元素通过包含零或多个 <source> 元素和一个 <img> 元素来为不同的显示/设备场景提供图像版本。浏览器会选择最匹配的子 <source> 元素,如果没有匹配的,就选择 <img> 元素的 src 属性中的URL。然后,所选图像呈现在<img>元素占据的空间中。</p>
<pre class="language-bash" data-language="bash"><code class="language-bash"><span class="token operator"><</span>picture<span class="token operator">></span>
<span class="token operator"><</span><span class="token operator">!</span>-- 深色模式下的图片 --<span class="token operator">></span>
<span class="token operator"><</span>source <span class="token assign-left variable">srcset</span><span class="token operator">=</span><span class="token string">"dark.jpg"</span> <span class="token assign-left variable">media</span><span class="token operator">=</span><span class="token string">"(prefers-color-scheme: dark)"</span> /<span class="token operator">></span>
<span class="token operator"><</span><span class="token operator">!</span>-- 默认模式下的图片 --<span class="token operator">></span>
<span class="token operator"><</span>img <span class="token assign-left variable">src</span><span class="token operator">=</span><span class="token string">"light.jpg"</span>/<span class="token operator">></span>
<span class="token operator"><</span>/picture<span class="token operator">></span></code></pre>
<h2 id="4-JavaScript中判断当前模式-amp-监听模式变化"><a href="#4-JavaScript中判断当前模式-amp-监听模式变化" class="headerlink" title="4. JavaScript中判断当前模式&监听模式变化"></a>4. JavaScript中判断当前模式&监听模式变化</h2><h3 id="4-1-matchMedia"><a href="#4-1-matchMedia" class="headerlink" title="4.1 matchMedia"></a>4.1 matchMedia</h3><p>Window 的matchMedia() 方法返回一个新的MediaQueryList 对象,表示指定的媒体查询 (en-US)字符串解析后的结果。返回的MediaQueryList 可被用于判定Document是否匹配媒体查询,或者监控一个document 来判定它匹配了或者停止匹配了此媒体查询。</p>
<h3 id="4-2-addListener"><a href="#4-2-addListener" class="headerlink" title="4.2 addListener()"></a>4.2 addListener()</h3><p>MediaQueryList接口的addListener()方法向MediaQueryListener添加一个侦听器,该侦听器将运行自定义回调函数以响应媒体查询状态的更改。</p>
<p>具体用法参考以下例子:</p>
<pre class="language-bash" data-language="bash"><code class="language-bash">const mediaQuery <span class="token operator">=</span> window.matchMedia<span class="token punctuation">(</span><span class="token string">'(prefers-color-scheme: dark)'</span><span class="token punctuation">)</span>
<span class="token keyword">function</span> <span class="token function-name function">darkModeHandler</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>mediaQuery.matches<span class="token punctuation">)</span> <span class="token punctuation">{</span>
console.log<span class="token punctuation">(</span><span class="token string">'现在是深色模式'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>