-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
1455 lines (605 loc) · 89.1 KB
/
index.html
File metadata and controls
1455 lines (605 loc) · 89.1 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
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 class="theme-next pisces use-motion" lang="zh-Hans">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">
<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />
<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />
<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css" />
<link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">
<link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">
<meta name="keywords" content="Hexo, NexT" />
<meta property="og:type" content="website">
<meta property="og:title" content="Hexo">
<meta property="og:url" content="https://amberyang.github.io.git/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:locale" content="zh-Hans">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Hexo">
<script type="text/javascript" id="hexo.configurations">
var NexT = window.NexT || {};
var CONFIG = {
root: '/',
scheme: 'Pisces',
version: '5.1.4',
sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
fancybox: true,
tabs: true,
motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
duoshuo: {
userId: '0',
author: '博主'
},
algolia: {
applicationID: '',
apiKey: '',
indexName: '',
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"}
}
};
</script>
<link rel="canonical" href="https://amberyang.github.io.git/"/>
<title>Hexo</title>
</head>
<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">
<div class="container sidebar-position-left
page-home">
<div class="headband"></div>
<header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"><div class="site-brand-wrapper">
<div class="site-meta ">
<div class="custom-logo-site-title">
<a href="/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<span class="site-title">Hexo</span>
<span class="logo-line-after"><i></i></span>
</a>
</div>
<p class="site-subtitle"></p>
</div>
<div class="site-nav-toggle">
<button>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
</button>
</div>
</div>
<nav class="site-nav">
<ul id="menu" class="menu">
<li class="menu-item menu-item-home">
<a href="/" rel="section">
<i class="menu-item-icon fa fa-fw fa-home"></i> <br />
首页
</a>
</li>
<li class="menu-item menu-item-archives">
<a href="/archives/" rel="section">
<i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
归档
</a>
</li>
</ul>
</nav>
</div>
</header>
<main id="main" class="main">
<div class="main-inner">
<div class="content-wrap">
<div id="content" class="content">
<section id="posts" class="posts-expand">
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="https://amberyang.github.io.git/2020/03/06/App 包大小 - 图片压缩自动化/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="Amber">
<meta itemprop="description" content="">
<meta itemprop="image" content="/images/avatar.gif">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Hexo">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2020/03/06/App 包大小 - 图片压缩自动化/" itemprop="url">App 包大小 - 图片压缩自动化</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2020-03-06T00:00:00+08:00">
2020-03-06
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="App-包大小-图片压缩自动化"><a href="#App-包大小-图片压缩自动化" class="headerlink" title="App 包大小 - 图片压缩自动化"></a>App 包大小 - 图片压缩自动化</h1><p>app 包大小一直是各家公司持续优化的一个项目,比如删除无用图片,无用文件等。<br>图片资源过多,整体图片资源过大也是其中一个问题,虽然设计同学提供的资源一般是压缩后的,但是为了包大小的问题,开发同学还会进行再次压缩,这可能需要设计同学配合或者在压缩网站上进行。</p>
<p>导入图片时很少会注意图片大小或者哪些图片被压缩了,这就需要开发同学检查图片大小或者将图片再次压缩。为了解决人工检查的成本,这里会介绍通过 git commit 压缩图片后提交的方法。</p>
<h2 id="图片压缩"><a href="#图片压缩" class="headerlink" title="图片压缩"></a>图片压缩</h2><p>再介绍自动化前,一定是需要一个图片压缩脚本的,tinypng 网站提供了压缩接口,需要注册获取自己对应的 key<br><a href="https://tinypng.com/developers" target="_blank" rel="noopener">https://tinypng.com/developers</a></p>
<p>压缩图片的 python 脚本,将自己的 key 替换一下文件中 ‘自己分配的 key’ 这部分</p>
<p><a href="media/15645597762445/imagecompress.py">imagecompress</a></p>
<p>脚本内容就不细说了,除了压缩图片,还统计了压缩了图片压缩相关的信息,感兴趣的同学可以自己看一下,根据自己的需求修改。</p>
<h2 id="git-钩子"><a href="#git-钩子" class="headerlink" title="git 钩子"></a>git 钩子</h2><p>有了压缩脚本以后,需要思考的是如何自动化执行脚本。一般的开发者都选用的 git 进行管理,所以在 git 操作时进行压缩是最简单有效的。这里就需要用到 git 钩子自定义脚本来控制 git 的工作流程,大家最常见的就是 code review。</p>
<ul>
<li><p>客户端钩子包括 pre-commit, prepare-commit-msg, commit-msg, post-commit。</p>
</li>
<li><p>hooks 的目录位于 .git 下面</p>
</li>
</ul>
<p><img src="/2020/03/06/App 包大小 - 图片压缩自动化/15645597762445/15834735142843.jpg" alt="-w197"></p>
<p>hooks 里面的文件都是 sample 结尾,需要注意的是这些文件都是示例脚本,是不会执行的,只有重命名后才会生效,具体可以参考 <a href="https://git-scm.com/book/zh/v2/自定义-Git-Git-钩子" target="_blank" rel="noopener">https://git-scm.com/book/zh/v2/自定义-Git-Git-钩子</a></p>
<h2 id="自动化压缩"><a href="#自动化压缩" class="headerlink" title="自动化压缩"></a>自动化压缩</h2><p>结合钩子和图片压缩脚本,接下来介绍一下如何修改脚本实现自动化压缩</p>
<h3 id="pre-commit"><a href="#pre-commit" class="headerlink" title="pre-commit"></a>pre-commit</h3><p>pre-commit 是在 git add 提交之后,git commit 时执行的,如果脚本执行正确则继续提交,否则驳回提交,所以在这里进行图片压缩是比较合适的时机。</p>
<h3 id="修改-pre-commit"><a href="#修改-pre-commit" class="headerlink" title="修改 pre-commit"></a>修改 pre-commit</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">filepath=$(cd "$(dirname "$0")"; pwd) # 获取文件路径</span><br><span class="line"></span><br><span class="line">branch=$(git symbolic-ref --short HEAD) # 获取分支名称</span><br><span class="line"></span><br><span class="line"># 获取到提交到暂存区的ACMR状态的文件,对 png 文件执行图片压缩脚本后提交图片</span><br><span class="line">git diff --cached --name-only --diff-filter=ACMR -z $against | while read -d $'\0' f; do</span><br><span class="line">if [[ $f == *".png" ]];then</span><br><span class="line"> path="$(cd "$(dirname "$0")";cd ..;cd ..; pwd)/$f"</span><br><span class="line"> python "$filepath/imagecompress.py" $path $branch</span><br><span class="line"> exec git add $f</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">done</span><br></pre></td></tr></table></figure>
<p>文件另存为 pre-commit,注意不要有 sample 后缀</p>
<h3 id="执行权限"><a href="#执行权限" class="headerlink" title="执行权限"></a>执行权限</h3><p>有时候也会遇到脚本文件没有执行权限的情况,这时hooks就无法生效,需要用到 chomd 指令给脚本文件加上执行权限。</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">chmod +x pre-commit</span><br></pre></td></tr></table></figure>
<h2 id="源文件"><a href="#源文件" class="headerlink" title="源文件"></a>源文件</h2><p><a href="App 包大小 - 图片压缩自动化/15645597762445/imagecompress.py">imagecompress</a></p>
<p><a href="App 包大小 - 图片压缩自动化/15645597762445/pre-commit">pre-commit</a></p>
<h1 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h1><p>图片压缩网站:<a href="https://tinypng.com" target="_blank" rel="noopener">https://tinypng.com</a></p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="https://amberyang.github.io.git/2018/09/26/Weex-创建多页面工程/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="Amber">
<meta itemprop="description" content="">
<meta itemprop="image" content="/images/avatar.gif">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Hexo">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2018/09/26/Weex-创建多页面工程/" itemprop="url">Weex 创建多页面工程</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2018-09-26T16:30:20+08:00">
2018-09-26
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="Weex-创建多页面工程"><a href="#Weex-创建多页面工程" class="headerlink" title="Weex 创建多页面工程"></a>Weex 创建多页面工程</h1><p>初学 Weex ,遇到很多问题,其中就有多页面的问题。</p>
<p>最开始看的 vue-router,很多资料建议使用 vue-router 进行页面切换。</p>
<p>大概看了一点资料,vue-router 的配置类似移动端的 tabController, 需要显示的页面作为 component,在 router.js 中进行注册。</p>
<p>在显示的地方调用 <router-view> 进行显示,通过 router-link 进行页面的切换。</router-view></p>
<h2 id="Webpack-多入口文件配置和-vue-router-的区别"><a href="#Webpack-多入口文件配置和-vue-router-的区别" class="headerlink" title="Webpack 多入口文件配置和 vue-router 的区别"></a>Webpack 多入口文件配置和 vue-router 的区别</h2><ol>
<li>bundle 文件的数量不同。 bundle 文件的打包和 entry.js 文件的配置数量有关,默认情况下之后一个 entry 文件,所以只有一个bundle文件,而通过 Webpack 配置的多个入口文件后,会被编译成多个bundle 文件</li>
<li>在浏览器中,route-link 会被渲染出 a 标签,在移动端则是 pushViewController,这样会导致浏览器和移动端看到的效果不同</li>
</ol>
<h2 id="创建二个页面入口文件"><a href="#创建二个页面入口文件" class="headerlink" title="创建二个页面入口文件"></a>创建二个页面入口文件</h2><p>weex create 创建一个新工程 pagesdemo,默认创建的都是单页面工程,在工程的 src 目录下包含 index.vue 和 entry.js。</p>
<p>创建一个新的入口,同样需要提供这两个文件。在同级目录下新增一个 detail.vue 和 detail.js。</p>
<p>detail.js 修改为:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">const router = require('./router')</span><br><span class="line">const detail = require('@/detail.vue')</span><br><span class="line"></span><br><span class="line">new Vue(Vue.util.extend({el: '#root', router}, detail))</span><br></pre></td></tr></table></figure>
<h2 id="修改-webpack"><a href="#修改-webpack" class="headerlink" title="修改 webpack"></a>修改 webpack</h2><p>新增文件后,npm start 并不会编译新增的文件。如果想要文件被编译,还需要修改 webpack 文件。</p>
<p>工程目录下的 webpack.config.js 内容如下:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><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">// You can see all the config in `./configs`.</span><br><span class="line">const buildPlugins = require('./configs/plugin');</span><br><span class="line">let webpackConfig;</span><br><span class="line">module.exports = env => {</span><br><span class="line"> switch (env.NODE_ENV) {</span><br><span class="line"> case 'prod':</span><br><span class="line"> case 'production':</span><br><span class="line"> webpackConfig = require('./configs/webpack.prod.conf');</span><br><span class="line"> break;</span><br><span class="line"> case 'test':</span><br><span class="line"> case 'testing':</span><br><span class="line"> webpackConfig = require('./configs/webpack.test.conf');</span><br><span class="line"> break;</span><br><span class="line"> case 'plugin':</span><br><span class="line"> buildPlugins();</span><br><span class="line"> case 'common':</span><br><span class="line"> webpackConfig = require('./configs/webpack.common.conf');</span><br><span class="line"> break;</span><br><span class="line"> case 'release':</span><br><span class="line"> webpackConfig = require('./configs/webpack.release.conf');</span><br><span class="line"> break;</span><br><span class="line"> case 'dev':</span><br><span class="line"> case 'development':</span><br><span class="line"> default:</span><br><span class="line"> webpackConfig = require('./configs/webpack.dev.conf');</span><br><span class="line"> }</span><br><span class="line"> return webpackConfig;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>可以看到,dev 下使用的是 configs 目录下的 webpack.dev.conf</p>
<h3 id="使用-npm-start-查看浏览器运行效果"><a href="#使用-npm-start-查看浏览器运行效果" class="headerlink" title="使用 npm start 查看浏览器运行效果"></a>使用 npm start 查看浏览器运行效果</h3><p>运行 npm start 后,通过浏览器可以看到显示的是 html 文件。web 编译后的文件存放在工程目录下的 web 文件下,打开文件夹可以看到有 index.html 文件,所以接下来我们需要查一下如何生成 html 入口文件。</p>
<p>查看 index.html 的源码:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><!DOCTYPE html></span><br><span class="line"><html></span><br><span class="line"><head></span><br><span class="line"> <meta charset="utf-8"></span><br><span class="line"> <title>Index</title></span><br><span class="line"> <meta name="weex-viewport" content="750"></span><br><span class="line"> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"></span><br><span class="line"> <meta name="apple-mobile-web-app-capable" content="yes"></span><br><span class="line"> <meta name="apple-touch-fullscreen" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"></span><br><span class="line"> <meta name="format-detection" content="telephone=no, email=no"></span><br><span class="line"> <style></span><br><span class="line"> html, body, #weex {</span><br><span class="line"> width: 100%;</span><br><span class="line"> height: 100%;</span><br><span class="line"> }</span><br><span class="line"> html, body {</span><br><span class="line"> -ms-overflow-style: scrollbar;</span><br><span class="line"> -webkit-tap-highlight-color: transparent;</span><br><span class="line"> padding: 0;</span><br><span class="line"> margin: 0;</span><br><span class="line"> width: 100%;</span><br><span class="line"> height: 100%;</span><br><span class="line"> overflow-x: hidden;</span><br><span class="line"> -webkit-overflow-scrolling: touch;</span><br><span class="line"> }</span><br><span class="line"> body::before {</span><br><span class="line"> content: "1";</span><br><span class="line"> height: 1px;</span><br><span class="line"> overflow: hidden;</span><br><span class="line"> color: transparent;</span><br><span class="line"> display: block;</span><br><span class="line"> }</span><br><span class="line"> </style></span><br><span class="line"></head></span><br><span class="line"><body></span><br><span class="line"> <div id="root"></div></span><br><span class="line"></body></span><br><span class="line"><%= htmlWebpackPlugin.options.devScripts %></span><br><span class="line"></html></span><br></pre></td></tr></table></figure>
<p>从源码中可以看到,index.html 是通过 <%= htmlWebpackPlugin.options.devScripts %> 获得需要显示的内容,那 htmlWebpackPlugin.options.devScripts 是什么东西呢?</p>
<p>带着疑问,我们回到 webpack.dev.conf 文件中</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">module.exports = new Promise((resolve, reject) => {</span><br><span class="line"> portfinder.basePort = process.env.PORT || config.dev.port</span><br><span class="line"> portfinder.getPort((err, port) => {</span><br><span class="line"> if (err) {</span><br><span class="line"> reject(err)</span><br><span class="line"> } else {</span><br><span class="line"> // publish the new Port, necessary for e2e tests</span><br><span class="line"> process.env.PORT = port</span><br><span class="line"> // add port to devServer config</span><br><span class="line"> devWebpackConfig.devServer.port = port</span><br><span class="line"> devWebpackConfig.devServer.public = `${ip}:${port}`</span><br><span class="line"> // Add FriendlyErrorsPlugin</span><br><span class="line"> devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({</span><br><span class="line"> compilationSuccessInfo: {</span><br><span class="line"> messages: [</span><br><span class="line"> `Your application is running here: ${chalk.yellow(`http://${devWebpackConfig.devServer.host}:${port}`)}.`</span><br><span class="line"> ],</span><br><span class="line"> },</span><br><span class="line"> onErrors: config.dev.notifyOnErrors</span><br><span class="line"> ? utils.createNotifierCallback()</span><br><span class="line"> : undefined</span><br><span class="line"> }))</span><br><span class="line"></span><br><span class="line"> resolve(devWebpackConfig)</span><br><span class="line"> }</span><br><span class="line"> })</span><br><span class="line">})</span><br></pre></td></tr></table></figure>
<p>在 module.exports 使用了 devWebpackConfig。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line">const devWebpackConfig = webpackMerge(commonConfig[0], {</span><br><span class="line"> module: {</span><br><span class="line"> rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })</span><br><span class="line"> },</span><br><span class="line"> devtool: config.dev.devtool,</span><br><span class="line"> plugins: [</span><br><span class="line"> new webpack.DefinePlugin({</span><br><span class="line"> 'process.env': {</span><br><span class="line"> 'NODE_ENV': config.dev.env</span><br><span class="line"> }</span><br><span class="line"> }),</span><br><span class="line"> </span><br><span class="line"> ...generateHtmlWebpackPlugin(commonConfig[0].entry),</span><br><span class="line"> </span><br><span class="line"> new ScriptExtHtmlWebpackPlugin({</span><br><span class="line"> defaultAttribute: 'defer'</span><br><span class="line"> })</span><br><span class="line"> ],</span><br><span class="line"> devServer: {</span><br><span class="line"> clientLogLevel: 'warning',</span><br><span class="line"> compress: true,</span><br><span class="line"> contentBase: config.dev.contentBase,</span><br><span class="line"> host: config.dev.host,</span><br><span class="line"> port: config.dev.port,</span><br><span class="line"> historyApiFallback: config.dev.historyApiFallback,</span><br><span class="line"> public: config.dev.public,</span><br><span class="line"> open:config.dev.open,</span><br><span class="line"> watchContentBase: config.dev.watchContentBase,</span><br><span class="line"> overlay: config.dev.errorOverlay</span><br><span class="line"> ? { warnings: false, errors: true }</span><br><span class="line"> : false,</span><br><span class="line"> proxy: config.dev.proxyTable,</span><br><span class="line"> quiet: true, // necessary for FriendlyErrorsPlugin</span><br><span class="line"> openPage: encodeURI(openPage),</span><br><span class="line"> watchOptions: config.dev.watchOptions</span><br><span class="line"> }</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line">const weexConfig = webpackMerge(commonConfig[1], {</span><br><span class="line"> watch: true</span><br><span class="line">})</span><br></pre></td></tr></table></figure>
<p>其中 plugins 调用了 generateHtmlWebpackPlugin</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">const generateHtmlWebpackPlugin = (entry) => {</span><br><span class="line"> let entrys = Object.keys(entry);</span><br><span class="line"> // exclude vendor entry.</span><br><span class="line"> entrys = entrys.filter(entry => entry !== 'vendor' );</span><br><span class="line"> const htmlPlugin = entrys.map(name => {</span><br><span class="line"> return new HtmlWebpackPlugin({</span><br><span class="line"> multihtmlCache: true,</span><br><span class="line"> filename: name + '.html',</span><br><span class="line"> template: helper.rootNode(`web/index.html`),</span><br><span class="line"> isDevServer: true,</span><br><span class="line"> chunksSortMode: 'dependency',</span><br><span class="line"> inject: true,</span><br><span class="line"> devScripts: config.dev.htmlOptions.devScripts,</span><br><span class="line"> chunks: ['vendor', name]</span><br><span class="line"> })</span><br><span class="line"> })</span><br><span class="line"> return htmlPlugin;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>从方法中可以看出,这个是返回一个 html 插件,模板为 web/index.html。 很显然这里就是生成 html 的地方。那参数 commonConfig[0].entry 就是提供的全部入口文件</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">const commonConfig = require('./webpack.common.conf');</span><br></pre></td></tr></table></figure>
<p>在 webpack.dev.conf 第一行,可以看出数据的提供方为 webpack.common.conf</p>
<h3 id="修改-webpack-common-conf-支持浏览器运行"><a href="#修改-webpack-common-conf-支持浏览器运行" class="headerlink" title="修改 webpack.common.conf 支持浏览器运行"></a>修改 webpack.common.conf 支持浏览器运行</h3><p>查看 module.exports</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">module.exports = [webConfig, weexConfig];</span><br></pre></td></tr></table></figure>
<p>从 module.exports 可以看出,数据由 webConfig 提供,查看 webConfig 的源码:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">const webConfig = {</span><br><span class="line"> entry: Object.assign(webEntry, {</span><br><span class="line"> 'vendor': [path.resolve('node_modules/phantom-limb/index.js')]</span><br><span class="line"> }),</span><br><span class="line"> output: {</span><br><span class="line"> path: helper.rootNode('./dist'),</span><br><span class="line"> filename: '[name].web.js'</span><br><span class="line"> },</span><br><span class="line"> …………</span><br></pre></td></tr></table></figure>
<p>这里只是指明了编译的 web.js 文件的位置,dist 目录下,那 webEntry 如何获取的呢?</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">const getEntryFile = () => {</span><br><span class="line"> const entryFile = path.join(vueWebTemp, config.entryFilePath)</span><br><span class="line"> const routerFile = path.join(vueWebTemp, config.routerFilePath)</span><br><span class="line"> fs.outputFileSync(entryFile, getEntryFileContent(helper.root(config.entryFilePath), routerFile));</span><br><span class="line"> fs.outputFileSync(routerFile, getRouterFileContent(helper.root(config.routerFilePath)));</span><br><span class="line"> </span><br><span class="line"> return {</span><br><span class="line"> index: entryFile</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">const webEntry = getEntryFile();</span><br></pre></td></tr></table></figure>
<p>从源码中可以看出,getEntryFile 是用来获取所有的入口问题,那我们来修改一下:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">const getEntryFile = () => {</span><br><span class="line"> const entryFile = path.join(vueWebTemp, config.entryFilePath)</span><br><span class="line"> const routerFile = path.join(vueWebTemp, config.routerFilePath)</span><br><span class="line"> fs.outputFileSync(entryFile, getEntryFileContent(helper.root(config.entryFilePath), routerFile));</span><br><span class="line"> fs.outputFileSync(routerFile, getRouterFileContent(helper.root(config.routerFilePath)));</span><br><span class="line"></span><br><span class="line">> const detailFilePath = 'detail.js'</span><br><span class="line">> const detailFile = path.join(vueWebTemp, modifyFilePath)</span><br><span class="line">> fs.outputFileSync(detailFile, getEntryFileContent(helper.root(detailFilePath), detailFile));</span><br><span class="line"> </span><br><span class="line"> return {</span><br><span class="line"> index: entryFile,</span><br><span class="line"> detail: detailFile,</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>新增 detail 的配置。</p>
<p>重新运行 npm start ,可以看到浏览器中有了2个页面的标签</p>
<p><img src="/2018/09/26/Weex-创建多页面工程/15378481399364/15378652688141.jpg" alt="-w331"></p>
<h3 id="修改-webpack-common-conf-支持生成多个-jsbundle"><a href="#修改-webpack-common-conf-支持生成多个-jsbundle" class="headerlink" title="修改 webpack.common.conf 支持生成多个 jsbundle"></a>修改 webpack.common.conf 支持生成多个 jsbundle</h3><p>和浏览器显示 html 的原理一下,端上需要显示 js 文件。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">const weexConfig = {</span><br><span class="line"> entry: weexEntry,</span><br><span class="line"> output: {</span><br><span class="line"> path: path.join(__dirname, '../dist'),</span><br><span class="line"> filename: '[name].js'</span><br><span class="line"> },</span><br></pre></td></tr></table></figure>
<p>可以看到 js 源文件的提供方为 weexConfig, 查看源码,比起浏览器要简单很多,只需要简单修改配置。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">const weexEntry = {</span><br><span class="line"> 'index': helper.root('entry.js'),</span><br><span class="line">> 'detail': helper.root('detail.js')</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="添加-navigator-跳转"><a href="#添加-navigator-跳转" class="headerlink" title="添加 navigator 跳转"></a>添加 navigator 跳转</h2><p>在需要跳转的地方添加此方法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">let bundleUrl = weex.config.bundleUrl</span><br><span class="line">let nativeBase</span><br><span class="line">let host = 'localhost:8080'</span><br><span class="line">let matches = /\/\/([^/]+?)\//.exec(bundleUrl)</span><br><span class="line">if (matches && matches.length >= 2) {</span><br><span class="line"> host = matches[1]</span><br><span class="line">}</span><br><span class="line">if (weex.config.env.platform === 'iOS') {</span><br><span class="line"> nativeBase = 'http://' + host + '/dist/modify.js'</span><br><span class="line">} else {</span><br><span class="line"> nativeBase = 'http://' + host + '/modify.html'</span><br><span class="line">} </span><br><span class="line">navigator.push({</span><br><span class="line"> url: nativeBase,</span><br><span class="line"> animated: "true"</span><br><span class="line">}, null)</span><br></pre></td></tr></table></figure>
<p>weex 提供了一些环境变量,通过 platform 可以获取到设备类型,除此之外,还有很多其他字段:<br><a href="http://weex.apache.org/cn/references/weex-variable.html" target="_blank" rel="noopener">http://weex.apache.org/cn/references/weex-variable.html</a></p>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>搜索和很多资料,终于解决了问题,不过使用 weexplayground 扫描跳转还有问题,目前正在解决。解决后,再补充。</p>
<h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><p><a href="https://www.jianshu.com/p/ae1d7a2b0a8a" target="_blank" rel="noopener">https://www.jianshu.com/p/ae1d7a2b0a8a</a><br><a href="https://blog.csdn.net/u012182853/article/details/80559363" target="_blank" rel="noopener">https://blog.csdn.net/u012182853/article/details/80559363</a><br><a href="https://blog.csdn.net/u012182853/article/details/80559363" target="_blank" rel="noopener">https://blog.csdn.net/u012182853/article/details/80559363</a><br><a href="https://www.jianshu.com/p/a0c4c8f3ad2d" target="_blank" rel="noopener">https://www.jianshu.com/p/a0c4c8f3ad2d</a><br><a href="https://juejin.im/entry/5a0938586fb9a0451a75e010" target="_blank" rel="noopener">https://juejin.im/entry/5a0938586fb9a0451a75e010</a><br><a href="https://www.webpackjs.com/concepts/output/#用法-usage-" target="_blank" rel="noopener">https://www.webpackjs.com/concepts/output/#用法-usage-</a></p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="https://amberyang.github.io.git/2018/07/18/UIView动画/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="Amber">
<meta itemprop="description" content="">
<meta itemprop="image" content="/images/avatar.gif">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Hexo">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2018/07/18/UIView动画/" itemprop="url">UIView 动画</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2018-07-18T16:21:20+08:00">
2018-07-18
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="首要任务"><a href="#首要任务" class="headerlink" title="首要任务"></a>首要任务</h1><p>针对 Core Animation 进行探讨</p>
<p>虽然很多东西也可以用更高层级的 UIKit 的方法来完成,但是 Core Animation 将会让你更好的理解正在发生什么。它以一种更明确地方式来描述动画。</p>
<p>再看动画如何与我们在屏幕上看到的内容交互之前,我们需要快速浏览一下 Core Animation 的 CALayer,这是动画产生作用的地方。</p>
<p>UIView 实例以及 layer-backed 的 NSView,修改他们的 layer 来委托强大的 Core Graphics 框架来进行渲染。然而,你务必要理解,当把动画添加到一个 layer 时,是不直接修改它的属性的。</p>
<p>取而代之,Core Animation 维护了两个平行 layer 层次结构:model layer tree (模型层树)和 presentation layer tree (表示层树)。前者中的 layers 反映了我们能直接看到的 layers 的状态,而后者的 layers 则是动画正在表现的值的近似。</p>
<p>实际上还有所谓的第三个 layer 树,叫做 rendering tree(渲染书)。因为它对 Core Animation 而言是私有的,所以暂时不讨论。</p>
<p>考虑在 view 上增加一个渐出动画。如果在动画中的任意时刻,查看 layer 的 opacity 值,你是得不到与屏幕内容对应的透明度的。取而代之,你需要查看 presentation layer 以获得正确的结果。</p>
<p>虽然你可能不会去直接设置 presentation layer 的属性,但是使用它的当前值来创建新的动画,或者在动画发生时与 layers 交互是非常有用的。</p>
<p>通过使用 - [CALayer presentationLayer] 和 - [CALayer modelLayer],你可以在两个 layer 之间轻松切换。</p>
<h1 id="基本动画"><a href="#基本动画" class="headerlink" title="基本动画"></a>基本动画</h1><p>使用 CABasicAnimation 实现 线性动画</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">CABasicAnimation *animation = [CABasicAnimation animation];</span><br><span class="line">animation.keyPath = @"position.x";</span><br><span class="line">animation.fromValue = @77;</span><br><span class="line">animation.toValue = @455;</span><br><span class="line">animation.duration = 1;</span><br><span class="line"> </span><br><span class="line">[rocket.layer addAnimation:animation forKey:@"basic"];</span><br></pre></td></tr></table></figure>
<p>注意我们的动画的键路径,也就是 position.x,实际上包含一个存储在 position 属性中的 CGPoint 结构体成员。这是 Core Animation 一个非常方便的特性。</p>
<p><strong>完整列表<br><a href="https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreAnimation_guide/Key-ValueCodingExtensions/Key-ValueCodingExtensions.html" target="_blank" rel="noopener">https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreAnimation_guide/Key-ValueCodingExtensions/Key-ValueCodingExtensions.html</a></strong></p>
<p>然而,当我们运行该代码时,我们意识到完成动画后对象马上回到了初始位置。这是因为在默认情况下,动画不会在超出其持续时间后还修改 presentation layer。实际上,在结束时它甚至会被彻底移除。</p>
<p>一但动画被移除,presentation layer 将回到 model layer 的值,并且因为我们从未修改该 layer 的 postion 属性,所以对象将重新出现在它开始的地方。</p>
<p>这里有两种解决这个问题的方法:</p>
<ol>
<li>直接在 model layer 上更新属性。这个是推荐的做法,因为它是的动画完全可选。<br>一旦动画完成并且从 layer 中移除,presentation layer 将回到 model layer 设置的值,而这个值抢号与动画最后一个步骤相匹配。</li>
</ol>
<p>恰好与动画最后一个步骤相匹配。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">CABasicAnimation *animation = [CABasicAnimation animation];</span><br><span class="line">animation.keyPath = @"position.x";</span><br><span class="line">animation.fromValue = @77;</span><br><span class="line">animation.toValue = @455;</span><br><span class="line">animation.duration = 1;</span><br><span class="line"> </span><br><span class="line">[rocket.layer addAnimation:animation forKey:@"basic"];</span><br><span class="line"> </span><br><span class="line">rocket.layer.position = CGPointMake(455, 61);</span><br></pre></td></tr></table></figure>
<p>或者,你可以通过设置动画的 fillModel 属性为 kCAFillModeForward 以留在最终状态,并设置 removedOnCompletion 为 NO 以防止它被自动移除:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">CABasicAnimation *animation = [CABasicAnimation animation];</span><br><span class="line">animation.keyPath = @"position.x";</span><br><span class="line">animation.fromValue = @77;</span><br><span class="line">animation.toValue = @455;</span><br><span class="line">animation.duration = 1;</span><br><span class="line"> </span><br><span class="line">animation.fillMode = kCAFillModeForward;</span><br><span class="line">animation.removedOnCompletion = NO;</span><br><span class="line"> </span><br><span class="line">[rectangle.layer addAnimation:animation forKey:@"basic"];</span><br></pre></td></tr></table></figure>
<p>如果将已完成的动画保持在 layer 上时,会造成额外的开销,因为渲染器回去进行额外的绘画工作。</p>
<p>值得提出的是,实际我们创建的动画对象被添加到 layer 时立刻就复制了一份。这个特性在多个 view 中重用动画时这非常有用。比如想要第二个对象在第一个动画不久后也开始动画:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">CABasicAnimation *animation = [CABasicAnimation animation];</span><br><span class="line">animation.keyPath = @"position.x";</span><br><span class="line">animation.byValue = @378;</span><br><span class="line">animation.duration = 1;</span><br><span class="line"> </span><br><span class="line">[rocket1.layer addAnimation:animation forKey:@"basic"];</span><br><span class="line">rocket1.layer.position = CGPointMake(455, 61);</span><br><span class="line"> </span><br><span class="line">animation.beginTime = CACurrentMediaTime() + 0.5;</span><br><span class="line"> </span><br><span class="line">[rocket2.layer addAnimation:animation forKey:@"basic"];</span><br><span class="line">rocket2.layer.position = CGPointMake(455, 111);</span><br></pre></td></tr></table></figure>
<p>设置动画的 beginTime 为未来 0.5秒将智慧影响 rocket2,因为动画在执行语句 [rocket1.layer addAnimation:animation forKey:@”basic”]; 时已经被赋值了,并且之后 rocket1 也不会考虑对动画对象的改变。</p>
<p>我决定再使用 CABasicAnimation 的 byValue 属性创建一个动画,这个动画从 presentation layer 的当前值开始,加上 byValue的值后结束。这使得动画更易于重用,因为你不需要精确的指定可能无法提前知道的 from- 和 toValue 的值。</p>
<p>fromValue, byValue 和 toValue 的不同组合可以用来实现不同的效果</p>
<p>文档:<br><strong><a href="https://developer.apple.com/reference/quartzcore/cabasicanimation#//apple_ref/doc/uid/TP40004496-CH1-SW4" target="_blank" rel="noopener">https://developer.apple.com/reference/quartzcore/cabasicanimation#//apple_ref/doc/uid/TP40004496-CH1-SW4</a></strong></p>
<h1 id="多步动画"><a href="#多步动画" class="headerlink" title="多步动画"></a>多步动画</h1><p>如果想要为你的动画定义超过两个步骤,可以使用更通用的 CAKeyframeAnimation,而不是链接多个 CABasicAnimation 实例。</p>
<p>关键帧(keyframe) 使我们能够定义动画中任意的一个点,然后让 Core Animation 填充所谓的中间帧。</p>
<p>比如晃动的效果:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];</span><br><span class="line">animation.keyPath = @"position.x";</span><br><span class="line">animation.values = @[ @0, @10, @-10, @10, @0 ];</span><br><span class="line">animation.keyTimes = @[ @0, @(1 / 6.0), @(3 / 6.0), @(5 / 6.0), @1 ];</span><br><span class="line">animation.duration = 0.4;</span><br><span class="line"> </span><br><span class="line">animation.additive = YES;</span><br><span class="line"> </span><br><span class="line">[form.layer addAnimation:animation forKey:@"shake"];</span><br></pre></td></tr></table></figure>
<p>values 数组定义了表单应该到哪些位置。</p>
<p>设置 keyTimes 属性让我们能够制定关键帧动画发生的时间。他们被指定为关键帧动画总只需时间的一个分数。</p>
<p>请注意我</p>
<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="http://ios.jobbole.com/69111/" target="_blank" rel="noopener">http://ios.jobbole.com/69111/</a></p>
<p><a href="http://wiki.jikexueyuan.com/project/ios-core-animation/" target="_blank" rel="noopener">http://wiki.jikexueyuan.com/project/ios-core-animation/</a></p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="https://amberyang.github.io.git/2018/04/18/Define-宏/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="Amber">
<meta itemprop="description" content="">
<meta itemprop="image" content="/images/avatar.gif">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Hexo">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2018/04/18/Define-宏/" itemprop="url">Define 宏</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2018-04-18T16:21:20+08:00">
2018-04-18
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="define用法集锦"><a href="#define用法集锦" class="headerlink" title="define用法集锦"></a>define用法集锦</h1><p>Syntax</p>
<p> #define identifier token-stringopt</p>
<p> #define identifier(identifieropt , … , identifieropt) token-stringopt</p>
<h1 id="宏的基本内容"><a href="#宏的基本内容" class="headerlink" title="宏的基本内容"></a>宏的基本内容</h1><ol>
<li>程序第一步是在预编译之前会有一些操作,例如删除反斜线和换行符的组合,将每个注释用一个空格替代…</li>
<li>然后在进入预编译的时候,寻找可能存在的预处理指定(由#开头),例如 C 中常用的 #include,或者 oc 中的 #import,#define…</li>
<li>处理 #define 的时候,然后预处理器会从 # 开始,一直执行到第一个换行符(写代码的时候换行的作用),自然,#define 只会允许定义一行的宏,不过正因为上面提到的预处理之前会删除反斜线和换行符的组合,所以可以利用反斜线定义多行宏,在删除反斜线和换行符的组合后,逻辑上就成了一行的宏了</li>
<li>红作用在预编译使其,其真正的效果就是代码替换,而且是直接替换(内联函数),这个和函数有着很大的区别,并且正因为是直接替换,在使用的时候就会有一些的注意点</li>
<li>红可以被称为类对象红,类函数宏</li>
<li>宏在预处理阶段只进行文本的替换,不会进行具体的计算(发生在编译使其)</li>
</ol>
<h1 id="用法"><a href="#用法" class="headerlink" title="用法"></a>用法</h1><p> #define A(x) T_##x => T_1</p>
<p> #define B(x) #@x => ‘1’</p>
<p> #define C(x) #x => “1”</p>
<h1 id="定义宏,取消宏"><a href="#定义宏,取消宏" class="headerlink" title="定义宏,取消宏"></a>定义宏,取消宏</h1><p>//定义宏 #define [MacroName] [MacroValue]<br>//取消宏 #undef [MacroName]<br>//普通宏 #define PI (3.1415926)<br>//带参数的宏 #define max(a,b) ((a)>(b)? (a),(b)) </p>
<p>通过条件编译开关来避免重复包含(重复定义)<br>例如 #ifndef <strong>headerfileXXX</strong> #define <strong>headerfileXXX</strong> … //文件内容 … #endif</p>
<p>1、防止一个头文件被重复包含</p>
<pre><code>#ifndef COMDEF_H
#define COMDEF_H
//头文件内容
#endif
</code></pre><p>2、重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植。<br>typedef unsigned char boolean; // Boolean value type.<br>typedef unsigned long int uint32; // Unsigned 32 bit value<br>typedef unsigned short uint16; // Unsigned 16 bit value<br>typedef unsigned char uint8; // Unsigned 8 bit value<br>typedef signed long int int32; // Signed 32 bit value<br>typedef signed short int16; // Signed 16 bit value<br>typedef signed char int8; // Signed 8 bit value<br>//下面的不建议使用<br>typedef unsigned char byte; // Unsigned 8 bit value type.<br>typedef unsigned short word; // Unsinged 16 bit value type.<br>typedef unsigned long dword; // Unsigned 32 bit value type.<br>typedef unsigned char uint1; // Unsigned 8 bit value type.<br>typedef unsigned short uint2; // Unsigned 16 bit value type.<br>typedef unsigned long uint4; // Unsigned 32 bit value type.<br>typedef signed char int1; // Signed 8 bit value type.<br>typedef signed short int2; // Signed 16 bit value type.<br>typedef long int int4; // Signed 32 bit value type.<br>typedef signed long sint31; // Signed 32 bit value<br>typedef signed short sint15; // Signed 16 bit value<br>typedef signed char sint7; // Signed 8 bit value </p>
<p>3、得到指定地址上的一个字节或字</p>
<pre><code>#define MEM_B( x ) ( *( (byte *) (x) ) )
#define MEM_W( x ) ( *( (word *) (x) ) )
</code></pre><p>4、求最大值和最小值</p>
<p> #define MAX( x, y ) ( ((x) > (y)) ? (x) : (y) )</p>
<p> #define MIN( x, y ) ( ((x) < (y)) ? (x) : (y) )</p>
<p>5、得到一个field在结构体(struct)中的偏移量</p>
<pre><code>#define FPOS( type, field ) /
</code></pre><p>//lint -e545 //<br>( (dword) &;(( type *) 0)-> field )<br>//lint +e545 //</p>
<p>6、得到一个结构体中field所占用的字节数</p>
<pre><code>#define FSIZ( type, field ) sizeof( ((type *) 0)->field )
</code></pre><p>7、按照LSB格式把两个字节转化为一个Word</p>
<pre><code>#define FLIPW( ray ) ( (((word) (ray)[0]) * 256) + (ray)[1] )
</code></pre><p>8、按照LSB格式把一个Word转化为两个字节</p>
<pre><code>#define FLOPW( ray, val ) /
</code></pre><p> (ray)[0] = ((val) / 256); /<br> (ray)[1] = ((val) &; 0xFF)</p>
<p>9、得到一个变量的地址(word宽度)</p>
<pre><code>#define B_PTR( var ) ( (byte *) (void *) &;(var) )
#define W_PTR( var ) ( (word *) (void *) &;(var) )
</code></pre><p>10、得到一个字的高位和低位字节</p>
<pre><code>#define WORD_LO(xxx) ((byte) ((word)(xxx) &; 255))
#define WORD_HI(xxx) ((byte) ((word)(xxx) >> 8))
</code></pre><p>11、返回一个比X大的最接近的8的倍数</p>
<pre><code>#define RND8( x ) ((((x) + 7) / 8 ) * 8 )
</code></pre><p>12、将一个字母转换为大写</p>
<pre><code>#define UPCASE( c ) ( ((c) >= 'a' &;&; (c) <= 'z') ? ((c) - 0x20) : (c) )
</code></pre><p>13、判断字符是不是10进值的数字</p>
<pre><code>#define DECCHK( c ) ((c) >= '0' &;&; (c) <= '9')
</code></pre><p>14、判断字符是不是16进值的数字</p>
<pre><code>#define HEXCHK( c ) ( ((c) >= '0' &;&; (c) <= '9') ||/
((c) >= 'A' &;&; (c) <= 'F') ||/
</code></pre><p>((c) >= ‘a’ &;&; (c) <= ‘f’) )</p>
<p>15、防止溢出的一个方法</p>
<pre><code>#define INC_SAT( val ) (val = ((val)+1 > (val)) ? (val)+1 : (val))
</code></pre><p>16、返回数组元素的个数</p>
<pre><code>#define ARR_SIZE( a ) ( sizeof( (a) ) / sizeof( (a[0]) ) )
</code></pre><p>17、返回一个无符号数n尾的值MOD_BY_POWER_OF_TWO(X,n)=X%(2^n)</p>
<pre><code>#define MOD_BY_POWER_OF_TWO( val, mod_by ) /
( (dword)(val) &; (dword)((mod_by)-1) )
</code></pre><p>18、对于IO空间映射在存储空间的结构,输入输出处理</p>
<p> #define inp(port) (*((volatile byte *) (port)))</p>
<p> #define inpw(port) (*((volatile word *) (port)))</p>
<p> #define inpdw(port) (*((volatile dword *)(port)))</p>
<p> #define outp(port, val) (*((volatile byte *) (port)) = ((byte) (val)))</p>
<p> #define outpw(port, val) (*((volatile word *) (port)) = ((word) (val)))</p>
<p> #define outpdw(port, val) (*((volatile dword *) (port)) = ((dword) (val)))</p>
<p>19、使用一些宏跟踪调试<br>ANSI标准说明了五个预定义的宏名。它们是:<br><strong>LINE</strong><br><strong>FILE</strong><br><strong>DATE</strong><br><strong>TIME</strong><br><strong>STDC</strong></p>
<p>C++中还定义了 __cplusplus</p>
<p>如果编译器不是标准的,则可能仅支持以上宏名中的几个,或根本不支持。记住编译程序也许还提供其它预定义的宏名。<br><strong>LINE</strong> 及 <strong>FILE</strong> 宏指示,#line指令可以改变它的值,简单的讲,编译时,它们包含程序的当前行数和文件名。<br><strong>DATE</strong> 宏指令含有形式为月/日/年的串,表示源文件被翻译到代码时的日期。<br><strong>TIME</strong> 宏指令包含程序编译的时间。时间用字符串表示,其形式为:分:秒<br><strong>STDC</strong> 宏指令的意义是编译时定义的。一般来讲,如果<strong>STDC</strong>已经定义,编译器将仅接受不包含任何非标准扩展的标准C/C++代码。如果实现是标准的,则宏<strong>STDC</strong>含有十进制常量1。如果它含有任何其它数,则实现是非标准的。<br>__cplusplus 与标准c++一致的编译器把它定义为一个包含至少6为的数值。与标准c++不一致的编译器将使用具有5位或更少的数值。<br>可以定义宏,例如:<br>当定义了_DEBUG,输出数据信息和所在文件所在行</p>
<pre><code>#ifdef _DEBUG
#define DEBUGMSG(msg,date) printf(msg);printf(“%d%d%d”,date,_LINE_,_FILE_)
#else
#define DEBUGMSG(msg,date)
#endif
</code></pre><p>20、宏定义防止错误使用小括号包含。<br>例如:<br>有问题的定义:#define DUMP_WRITE(addr,nr) {memcpy(bufp,addr,nr); bufp += nr;}<br>应该使用的定义: #difne DO(a,b) do{a+b;a++;}while(0)<br>例如:<br>if(addr)<br> DUMP_WRITE(addr,nr);<br>else<br> do_somethong_else();<br>宏展开以后变成这样:<br>if(addr)<br> {memcpy(bufp,addr,nr); bufp += nr;};<br>else<br> do_something_else();<br>gcc在碰到else前面的“;”时就认为if语句已经结束,因而后面的else不在if语句中。而采用do{} while(0)的定义,在任何情况下都没有问题。而改为 #difne DO(a,b) do{a+b;a++;}while(0) 的定义则在任何情况下都不会出错</p>
<ol>
<li>define中的特殊标识符<br>#define Conn(x,y) x##y<br>#define ToChar(x) #@x<br>#define ToString(x) #x<br>int a=Conn(12,34); char b=ToChar(a); char c[]=ToString(a); 结果是 a=1234,c=’a’,c=’1234’;<br>可以看出 ## 是简单的连接符,#@用来给参数加单引号,#用来给参数加双引号即转成字符串</li>
</ol>
<h1 id="define-和-inline-的区别"><a href="#define-和-inline-的区别" class="headerlink" title="define 和 inline 的区别"></a>define 和 inline 的区别</h1><p>define:定义预编译时的处理宏<br>只进行简单的字符替换,无类型检测</p>
<h2 id="static"><a href="#static" class="headerlink" title="static"></a>static</h2><h3 id="产生背景"><a href="#产生背景" class="headerlink" title="产生背景"></a>产生背景</h3><p>引出原因:函数内部定义的变量,在程序执行到它的定义处时,编译器为它在栈上分配空间,大家知道,函数在栈上分配的空间在此函数执行结束时会释放掉,这样就产生了一个问题: 如果想将函数中此变量的值保存至下一次调用时,如何实现?<br>最容易想到的方法是定义一个全局的变量,但定义为一个全局变量有许多缺点,最明显的缺点是破坏了此变量的访问范围(使得在此函数中定义的变量,不仅仅受此函数控制)。类的静态成员也是这个道理。<br>解决方案:因此C++ 中引入了static,用它来修饰变量,它能够指示编译<br>器将此变量在程序的静态存储区分配空间保存,这样即实现了目的,又使得此变量的存取范围不变。</p>
<h3 id="具体作用"><a href="#具体作用" class="headerlink" title="具体作用"></a>具体作用</h3><p>Static作用分析总结:static总是使得变量或对象的存储形式变成静态存储,连接方式变成内部连接,对于局部变量(已经是内部连接了),它仅改变其存储方式;对于全局变量(已经是静态存储了),它仅改变其连接类型。(1 连接方式:成为内部连接;2 存储形式:存放在静态全局存储区)</p>
<h2 id="const"><a href="#const" class="headerlink" title="const"></a>const</h2><h3 id="产生背景-1"><a href="#产生背景-1" class="headerlink" title="产生背景"></a>产生背景</h3><p>C++有一个类型严格的编译系统,这使得C++程序的错误在编译阶段即可发现许多,从而使得出错率大为减少,因此,也成为了C++与C相比,有着突出优点的一个方面。<br>C中很常见的预处理指令 #define VariableName VariableValue 可以很方便地进行值替代,这种值替代至少在三个方面优点突出:<br>一是避免了意义模糊的数字出现,使得程序语义流畅清晰,如下例:<br> #define USER_NUM_MAX 107 这样就避免了直接使用107带来的困惑。<br>二是可以很方便地进行参数的调整与修改,如上例,当人数由107变为201时,改动此处即可;<br>三是提高了程序的执行效率,由于使用了预编译器进行值替代,并不需要为这些常量分配存储空间,所以执行的效率较高。</p>
<p>然而,预处理语句虽然有以上的许多优点,但它有个比较致命的缺点,即,预处理语句仅仅只是简单值替代,缺乏类型的检测机制。这样预处理语句就不能享受C++严格类型检查的好处,从而可能成为引发一系列错误的患。</p>
<p>Const 推出的初始目的,正是为了取代预编译指令,消除它的缺点,同时继承它的优点。<br>现在它的形式变成了:<br>Const DataType VariableName = VariableValue ;</p>
<h3 id="具体作用-1"><a href="#具体作用-1" class="headerlink" title="具体作用"></a>具体作用</h3><p>1.const 用于指针的两种情况分析:<br> int const *A; //A可变,*A不可变<br> int *const A; //A不可变,*A可变<br> 分析:const 是一个左结合的类型修饰符,它与其左侧的类型修饰符和为一个类型修饰符,所以,int const 限定 *A,不限定A。int *const 限定A,不限定*A。<br>2.const 限定函数的传递值参数:<br> void Fun(const int Var);<br> 分析:上述写法限定参数在函数体中不可被改变。<br>3.const 限定函数的值型返回值:<br>const int Fun1();<br>const MyClass Fun2();<br> 分析:上述写法限定函数的返回值不可被更新,当函数返回内部的类型时(如Fun1),已经是一个数值,当然不可被赋值更新,所以,此时const无意义,最好去掉,以免困惑。当函数返回自定义的类型时(如Fun2),这个类型仍然包含可以被赋值的变量成员,所以,此时有意义。</p>
<ol>
<li>传递与返回地址: 此种情况最为常见,由地址变量的特点可知,适当使用const,意义昭然。<br>5. const 限定类的成员函数:<br>class ClassName {<br> public:<br> int Fun() const;<br> …..<br>}<br> 注意:采用此种const 后置的形式是一种规定,亦为了不引起混淆。在此函数的声明中和定义中均要使用const,因为const已经成为类型信息的一部分。<br>获得能力:可以操作常量对象。<br>失去能力:不能修改类的数据成员,不能在函数中调用其他不是const的函数。</li>
</ol>
<h2 id="inline"><a href="#inline" class="headerlink" title="inline"></a>inline</h2><h3 id="产生背景-2"><a href="#产生背景-2" class="headerlink" title="产生背景"></a>产生背景</h3><p>inline这个关键字的引入原因和const十分相似,inline 关键字用来定义一个类的内联函数,引入它的主要原因是用它替代C中<br>表达式形式的宏定义。<br>表达式形式的宏定义一例:<br> #define ExpressionName(Var1,Var2) (Var1+Var2)*(Var1-Var2)<br>这种表达式形式宏形式与作用跟函数类似,但它使用预编译器,没有堆栈,使用上比函数高效。但它只是预编译器上符号表的简单替换,不能进行参数有效性检测及使用C++类的成员访问控制。<br>inline 推出的目的,也正是为了取代这种表达式形式的宏定义,它消除了它的缺点,同时又很好地继承了它的优点。inline代码放入预编译器符号表中,高效;它是个真正的函数,调用时有严格的参数检测;它也可作为类的成员函数。</p>
<h3 id="具体作用-2"><a href="#具体作用-2" class="headerlink" title="具体作用"></a>具体作用</h3><p>直接在class类定义中定义各函数成员,系统将他们作为内联函数处理;成员函数是内联函数,意味着:每个对象都有该函数一份独立的拷贝。<br>在类外,如果使用关键字inline定义函数成员,则系统也会作为内联函数处理;</p>
<h2 id="C关键字"><a href="#C关键字" class="headerlink" title="C关键字"></a>C关键字</h2><pre><code>#define 宏名要替换的代码
</code></pre><p>宏定义,保存在预编译器的符号表中,执行高效;作为一种简单的符号替换,不进行其中参数有效性的检测<br>typedef 已有类型 新类型<br>别名, 常用于创建平台无关类型, typedef 在编译时被解释,因此让编译器来应付超越预处理器能力的文本替换</p>
<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://msdn.microsoft.com/en-us/library/teas0593.aspx" target="_blank" rel="noopener">https://msdn.microsoft.com/en-us/library/teas0593.aspx</a></p>
<p><a href="https://www.jianshu.com/p/f3917ae186f4" target="_blank" rel="noopener">https://www.jianshu.com/p/f3917ae186f4</a></p>
<p><a href="http://www.cnblogs.com/iloveyoucc/archive/2012/03/18/2404658.html" target="_blank" rel="noopener">http://www.cnblogs.com/iloveyoucc/archive/2012/03/18/2404658.html</a></p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="https://amberyang.github.io.git/2018/01/18/Hexo-上传 GitHub/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="Amber">
<meta itemprop="description" content="">
<meta itemprop="image" content="/images/avatar.gif">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Hexo">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2018/01/18/Hexo-上传 GitHub/" itemprop="url">Hexo 上传 github</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2018-01-18T16:21:20+08:00">
2018-01-18
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h2 id="config-yml-修改配置"><a href="#config-yml-修改配置" class="headerlink" title="_config.yml 修改配置"></a>_config.yml 修改配置</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">deploy:</span><br><span class="line"> type: git</span><br><span class="line"> repo: https://github.com/amberyang/amberyang.github.io</span><br><span class="line"> branch: master</span><br></pre></td></tr></table></figure>
<p><strong>XXX.github.io, XXX 一定要是你的 github 名称,否则提示页面找不到</strong></p>
<h2 id="上传-github"><a href="#上传-github" class="headerlink" title="上传 github"></a>上传 github</h2><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">➜ hexo clean</span><br></pre></td></tr></table></figure>
<p>生成静态文件</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">➜ hexo generate</span><br></pre></td></tr></table></figure>
<p>部署网站</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">➜ hexo deploy</span><br></pre></td></tr></table></figure>
<p>PS:报错</p>
<h3 id="npm-install-hexo-deployer-git-–save"><a href="#npm-install-hexo-deployer-git-–save" class="headerlink" title="npm install hexo-deployer-git –save"></a>npm install hexo-deployer-git –save</h3><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">npm install hexo-deployer-git --save</span><br></pre></td></tr></table></figure>
<h3 id="Error-Permission-denied-publickey-fatal-Could-not-read-from-remote-repository"><a href="#Error-Permission-denied-publickey-fatal-Could-not-read-from-remote-repository" class="headerlink" title="Error: Permission denied (publickey). fatal: Could not read from remote repository"></a>Error: Permission denied (publickey). fatal: Could not read from remote repository</h3><p>删除 /node_modules/hexo-deployer-git 文件夹,再执行一次 hexo-deployer,正常情况下需要输入用户名和密码。</p>
<h2 id="分类和标签无法显示或者无法点击"><a href="#分类和标签无法显示或者无法点击" class="headerlink" title="分类和标签无法显示或者无法点击"></a>分类和标签无法显示或者无法点击</h2><p>1.在 source 文件夹下创建文件夹 tags 和 categories。</p>