-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
331 lines (177 loc) · 142 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>陈钰博的博客</title>
<link href="/atom.xml" rel="self"/>
<link href="https://chenyubo.me/"/>
<updated>2019-03-04T02:27:28.634Z</updated>
<id>https://chenyubo.me/</id>
<author>
<name>陈钰博</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>从零开始一个Hexo主题</title>
<link href="https://chenyubo.me/hexo-theme-0-to-1/"/>
<id>https://chenyubo.me/hexo-theme-0-to-1/</id>
<published>2019-02-26T03:38:38.000Z</published>
<updated>2019-03-04T02:27:28.634Z</updated>
<content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>本文将会从零开始编写一个简单的Hexo博客主题,目的是了解一个Hexo博客主题的构成以及如何编写,因此,本示例中的博客页面样式不做过多描绘,样式主要参考 <a href="https://hexo.io/themes/" target="_blank" rel="noopener">Hexo theme</a> 中的 <a href="https://github.com/lotabout/hexo-theme-noise" target="_blank" rel="noopener">Noise</a> 主题。</p><p>在开始前,你需要对以下的一些知识点有必要的了解:</p><ul><li>模板引擎语法</li><li>CSS预处理器</li><li>YML语法</li><li>Hexo文档</li></ul><p>本文使用的模板引擎为 <a href="https://ejs.bootcss.com/" target="_blank" rel="noopener">ejs</a>,使用的 CSS 预处理器为 <a href="http://stylus-lang.com/" target="_blank" rel="noopener">stylus</a>。这也是 hexo 项目预装了的 render 插件,如果想使用其他模板引擎或者其他 CSS 预处理器,可以安装相对应的 render 插件。</p><p>本文的代码:<a href="https://github.com/cccyb/theme-example" target="_blank" rel="noopener">https://github.com/cccyb/theme-example</a></p><h3 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h3><p>根据下图,在<code>themes</code>目录下新建一个<code>theme-example</code>文件夹作为我们的主题目录。</p><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1g0ipnb7mhgj20f407e0t6.jpg" alt=""></p><p>如图所示,一个hexo主题的目录主要包括以下五部分:</p><ul><li><code>languages</code>:用于国际化的语言文件</li><li><code>layout</code>:主题布局模板文件</li><li><code>scripts</code>:hexo脚本插件目录,可以编写一些辅助函数脚本</li><li><code>source</code>:资源文件目录,包括页面样式,js脚本等</li><li><code>_config.yml</code>:主题配置文件</li></ul><h3 id="局部模板"><a href="#局部模板" class="headerlink" title="局部模板"></a>局部模板</h3><p>我们通过分析常见的博客网站可以知道,大部分的博客网站都由三部分组成:顶部导航栏,中间内容区域,以及底部信息展示区域。每次点击导航栏选项跳转页面时,顶部导航栏以及底部信息展示区域是不变的,只是中间的内容区域重新渲染,因此,我们可以将通用的代码抽离成局部模板以复用。</p><p>我们在<code>layout</code>目录下新建<code>_partial</code>目录,在该目录下添加<code>head.ejs</code>,<code>header.ejs</code>以及<code>footer.ejs</code>文件。</p><p><code>layout/_partial/head.ejs</code>:</p><pre><code class="ejs"><head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"> <title>标题</title></head></code></pre><p><code>layout/_partial/header.ejs</code>:</p><pre><code class="ejs"><header>我是导航栏</header></code></pre><p><code>layout/_partial/footer.ejs</code>:</p><pre><code class="ejs"><footer>我是底部信息</footer></code></pre><p>我们在<code>layout</code>中创建<code>layout.ejs</code>,并引入<code>head.ejs</code>,<code>header/ejs</code>和<code>footer.ejs</code>文件,<code>layout.ejs</code>文件是通用的布局文件模板,我们在后面新增的<code>ejs</code>文件都会继承<code>layout.ejs</code>,并将其内容填充到<code>body</code>中。</p><p><code>layout/layout.ejs</code>:</p><pre><code class="ejs"><!DOCTYPE html><html><%- partial('_partial/head') %><body> <div class="container"> <%- partial('_partial/header') %> <%- body %> <%- partial('_partial/footer') %> </div></body></html> </code></pre><h3 id="首页"><a href="#首页" class="headerlink" title="首页"></a>首页</h3><p>首页是我们的网站加载完毕后的第一个页面。</p><p>我们在 <code>layout</code> 中创建 <code>index.ejs</code> 文件,<code>index.ejs</code>首页将会继承<code>layout.ejs</code>布局模板生成 HTML 文件。</p><blockquote><p>partial()函数的作用是可以引入其他模板文件,详情参考hexo文档</p></blockquote><p><code>layout/index.ejs</code>:</p><pre><code class="ejs"><h1>Hello World</h1></code></pre><p>修改<strong>站点配置文件</strong>中的主题配置,使用我们刚刚创建的 <code>theme-example</code> 主题:</p><pre><code class="yaml"># Extensions## Plugins: https://hexo.io/plugins/## Themes: https://hexo.io/themes/theme: theme-example</code></pre><p>运行 <code>hexo server</code> 开启 Hexo 本地服务器预览,访问 <a href="http://localhost:4000/" target="_blank" rel="noopener">http://localhost:4000/</a>。</p><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1g0iqkcsz2dj21z20fen08.jpg" alt=""></p><h3 id="编写导航栏和底部信息"><a href="#编写导航栏和底部信息" class="headerlink" title="编写导航栏和底部信息"></a>编写导航栏和底部信息</h3><p>前面,我们只是搭了个页面框架,接下来我们就将开始正式开始一步步的完善我们的主题,以下两个文档我们将频繁的使用,最好可以提前阅读一遍有个了解:</p><ul><li><a href="https://hexo.io/zh-cn/docs/variables" target="_blank" rel="noopener">Hexo | 变量</a></li><li><a href="https://hexo.io/zh-cn/docs/helpers" target="_blank" rel="noopener">Hexo | 辅助函数</a></li></ul><p><code>layout/_partial/head.ejs</code>:</p><pre><code class="ejs"><head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"> <title><%= config.title %></title></head></code></pre><p>这里我们使用了<code>config</code>全局变量,该变量包含的是站点配置(即站点根目录下 <code>_config.yml</code> 中的配置)。除此之外,我还有将经常使用的是<code>theme</code>变量,该变量是主题配置(即主题根目录下 <code>_config.yml</code> 中的配置),其他变量参见hexo文档。</p><p>编辑导航栏部分,<code>layout/_partial/header.ejs</code>:</p><pre><code class="ejs"><header class="header"> <div class="title"> <a href="<%= url_for() %>" class="logo"><%= config.title %></a> </div> <nav class="navbar"> <ul class="menu"> <li class="menu-item"> <a href="/" class="menu-item-link">Home</a> </li> <li class="menu-item"> <a href="/categories" class="menu-item-link">Categories</a> </li> <li class="menu-item"> <a href="/tags" class="menu-item-link">Tags</a> </li> <li class="menu-item"> <a href="/archives" class="menu-item-link">Archives</a> </li> </ul> </nav></header></code></pre><p>编辑底部信息部分,<code>layout/_partial/footer.ejs</code>:</p><pre><code class="ejs"><footer> <p>Theme is <a href="/" target="_blank">Theme-example</a> by <a href="<%= config.url %>" target="_blank"><%= config.author %></a></p> <p>Powered by <a href="https://hexo.io/" target="_blank" rel="nofollow">hexo</a> &copy; <%- date(Date.now(), 'YYYY') %></p></footer></code></pre><p>这样,我们就得到了一个包含导航栏和底部信息的简单页面。</p><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1g0is6aotexj21z20l2n17.jpg" alt=""></p><h3 id="添加主题配置"><a href="#添加主题配置" class="headerlink" title="添加主题配置"></a>添加主题配置</h3><p>实际上我们需要让导航菜单根据我们的需要显示不同的项,上面这种写法不方便修改。所以我们会在主题的配置文件中添加导航菜单的配置。在 <code>theme-example</code> 下的配置文件 <code>_config.yml</code>,在其中添加需要配置的字段。然后可以通过 <code>theme</code> 这个变量来拿到该配置文件中的配置。</p><p><code>theme-example/_config.yml</code>:</p><pre><code class="yaml">menu: home: / categories: /categories tags: /tags archives: /archives</code></pre><p>这样我们就可以在 <code>header.ejs</code> 中使用 <code>theme.menu</code> 获取到导航菜单的设置。将 <code>header.ejs</code> 修改为:</p><pre><code class="ejs"><header class="header"> <div class="title"> <a href="<%= url_for() %>" class="logo"><%= config.title %></a> </div> <nav class="navbar"> <ul class="menu"> <% for (name in theme.menu) { %> <li class="menu-item"> <a href="<%- url_for(theme.menu[name]) %>" class="menu-item-link"><%= name %></a> </li> <% } %> </ul> </nav></header></code></pre><p> 这样,我们就可以动态的配置导航的信息了,我们还可以在主题配置文件中添加其他配置项供我们使用。</p><h3 id="添加文章列表"><a href="#添加文章列表" class="headerlink" title="添加文章列表"></a>添加文章列表</h3><p>接着我们完善首页的模板,使其能够显示文章列表。前面已经说过 Hexo 提供了各种有用的变量,在这里将会使用到 <code>page</code> 这个变量。<code>page</code> 会根据不同的页面拥有不同的属性。具体有什么属性,可以获取到哪些数据可以查看<a href="https://hexo.io/docs/variables.html#Page-Variables" target="_blank" rel="noopener">这里</a>。</p><p>那么这里我们会使用 <code>page</code> 变量的 <code>posts</code> 属性拿到文章数据的集合。编辑 <code>index.ejs</code> 文件:</p><pre><code class="ejs"><section class="posts"> <% page.posts.each(function (post) { %> <article class="post"> <div class="post-title"> <a class="post-title-link" href="<%- url_for(post.path) %>"><%= post.title %></a> </div> <div class="post-content"> <%- post.content %> </div> <div class="post-meta"> <span class="post-time"><%- date(post.date, "YYYY-MM-DD") %></span> </div> </article> <% }) %></section></code></pre><p>从 <code>page.posts</code> 中获取单篇文章的数据,并获取文章的标题,内容等数据填充到模板中。处理文章创建时间的时候使用了 <code>date()</code> 函数,这是 Hexo 提供的时间处理的<a href="https://hexo.io/docs/helpers.html#date" target="_blank" rel="noopener">辅助函数</a>。</p><p>由于首页显示文章内容时使用的是 <code>post.content</code>,即文章的全部内容。所以首页会显示每一篇文章的内容,实际上我们并不想在首页显示那么多内容,只想显示文章的摘录。</p><p>Hexo 提供了 <code>excerpt</code> 属性来获取文章的摘录部分,不过这里需要在文章中添加一个 <code><!--more--></code> 标记。添加了这个标记之后,<code>post.excerpt</code> 将会获取到标记之前的内容。如果没有这个标记,那么 <code>post.excerpt</code> 会是空的。所以我们可以把首页文章内容部分的 <code>post.content</code> 替换成 <code>post.excerpt</code>。</p><pre><code class="ejs"><div class="post-content"> <%- post.excerpt %></div></code></pre><h3 id="添加样式"><a href="#添加样式" class="headerlink" title="添加样式"></a>添加样式</h3><p>到目前为止,我们完成了首页的整体页面结构,不过由于没添加css样式,因此整体页面非常难看,所以我们需要给页面加上一些样式来美化一下我们的页面。</p><p>由于 Hexo 在新建项目的时候会安装 <code>hexo-renderer-stylus</code> 这个插件,所以我们无需其他步骤,只需要将样式文件放到 <code>css</code> 文件夹中。Hexo 在生成页面的时候会将 <code>source</code> 中的所有文件复制到生成的 <code>public</code> 文件中,并且在此之前会编译 <code>styl</code> 为 <code>css</code> 文件。</p><p>在 <code>css</code> 文件夹中创建 <code>style.styl</code>,编写一些基础的样式,并把所有样式 <code>import</code> 到这个文件。所以最终编译之后只会有 <code>style.css</code> 一个文件。创建 <code>_partial/header.styl</code> 与 <code>_partial/post.styl</code> 存放页面导航以及文章的样式,并且在 <code>style.styl</code> 中 <code>import</code> 这两个文件。</p><p><code>_partial/header.styl</code>:</p><pre><code class="stylus">.header { margin-top: 2em display: flex align-items: baseline justify-content: space-between .blog-title .logo { color: #AAA; font-size: 2em; font-family: "Comic Sans MS",cursive,LiSu,sans-serif; text-decoration: none; } .menu { margin: 0; padding: 0; .menu-item { display: inline-block; margin-right: 10px; } .menu-item-link { color: #AAA; text-decoration: none; &:hover { color: #368CCB; } } }}</code></pre><p><code>index.styl</code>:</p><pre><code class="stylus">.post { margin: 1em auto; padding: 30px 50px; background-color: #fff; border: 1px solid #ddd; box-shadow: 0 0 2px #ddd;}.posts { .post:first-child { margin-top: 0; } .post-title { font-size: 1.5em; .post-title-link { color: #368CCB; text-decoration: none; } } .post-content { a { color: #368CCB; text-decoration: none; } } .post-meta { color: #BABABA; }}</code></pre><p><code>style.styl</code>:</p><pre><code class="stylus">body { background-color: #F2F2F2; font-size: 1.25rem; line-height: 1.5;}.container { max-width: 960px; margin: 0 auto;}@import "_partial/header";@import "_partial/index";</code></pre><p>最后,我们需要把样式添加到页面中,这里使用了另外一个辅助函数 <a href="https://hexo.io/docs/helpers.html#css" target="_blank" rel="noopener"><code>css()</code></a>:</p><p><code>layout/_partial/head.ejs</code>:</p><pre><code class="ejs"><head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"> <title><%= config.title %></title> <%- css('css/style.styl') %></head></code></pre><p>至此,我们会看到站点的首页是这个样子的:</p><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1g0it4ozg82j21yy0vmq8g.jpg" alt=""></p><h3 id="添加分页"><a href="#添加分页" class="headerlink" title="添加分页"></a>添加分页</h3><p>在站点的 <code>source/_post/</code> 目录下存放的是我们的文章,现在我们把原本的 <code>hello-world.md</code> 复制黏贴 10+ 次,再查看站点首页。会发现,首页只显示了 10 篇文章。</p><p>首页显示的文章数量我们可以通过站点配置文件中的 <code>per_page</code> 字段来修改,但是我们不可能把所有文章都放在一页,所以我们现在来添加文章列表的分页。</p><p>新建 <code>_partial/paginator.ejs</code>:</p><pre><code class="ejs"><% if (page.total > 1){ %> <nav class="page-nav"> <%- paginator({ prev_text: "&laquo; Prev", next_text: "Next &raquo;" }) %> </nav><% } %></code></pre><p>在 <code>index.ejs</code> 中添加这个文件的内容:</p><pre><code class="ejs">...</section><%- partial('_partial/paginator') %></code></pre><p>这里我们使用到了另外的一个辅助函数 <a href="https://hexo.io/docs/helpers.html#paginator" target="_blank" rel="noopener"><code>paginator</code></a>,它能够帮助我们插入分页链接,这里我们只是实现了一个最基本的分页,具体的样式可以自行添加,或者根据文档使用其他配置自定义分页。</p><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1g0ity1ov1qj21z014q7a5.jpg" alt=""></p><h3 id="添加文章详情页"><a href="#添加文章详情页" class="headerlink" title="添加文章详情页"></a>添加文章详情页</h3><p>文章详情页对应的布局文件是 <code>post.ejs</code>,新建 <code>post.ejs</code>:</p><pre><code class="ejs"><article class="post"> <div class="post-title"> <h2 class="title"><%= page.title %></h2> </div> <div class="post-meta"> <span class="post-time"><%- date(page.date, "YYYY-MM-DD") %></span> </div> <div class="post-content"> <%- page.content %> </div></article></code></pre><p>由于这里是文章的模板,所以变量 <code>page</code> 表示的是文章的数据,而不是首页的文章数据集合。</p><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1g0ityp6mwmj21z214mtf5.jpg" alt=""></p><h3 id="添加归档页"><a href="#添加归档页" class="headerlink" title="添加归档页"></a>添加归档页</h3><p>创建归档页使用的模板文件 <code>archive.ejs</code>:</p><pre><code class="ejs"><section class="archive"> <ul class="post-archive"> <% page.posts.each(function (post) { %> <li class="post-item"> <span class="post-date"><%= date(post.date, "YYYY-MM-DD") %></span> <a class="post-title" href="<%- url_for(post.path) %>"><%= post.title %></a> </li> <% }) %> </ul></section><%- partial('_partial/paginator') %></code></pre><p>其实结构跟首页差不多,只是不显示文章内容而已。添加归档页的样式:</p><p><code>css/_partial/archive.styl</code>:</p><pre><code class="stylus">.archive { margin: 1em auto; padding: 30px 50px; background-color: #fff; border: 1px solid #ddd; box-shadow: 0 0 2px #ddd; .post-archive { list-style: none; padding: 0; .post-item { margin: 5px 0; .post-date { display: inline-block; margin-right: 10px; color: #BABABA; } .post-title { color: #368CCB; text-decoration: none; } } }}</code></pre><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1g0iu1jngalj21z214qqax.jpg" alt=""></p><h3 id="添加分类页"><a href="#添加分类页" class="headerlink" title="添加分类页"></a>添加分类页</h3><p>分类页跟归档页也类似,相当于根据不同的分类进行归档。</p><p>分类页和标签页的模板编写比较特殊,本质上,分类页和标签页属于自定义页面,我们需要新建自定义页面模板<code>page.ejs</code>:</p><pre><code class="ejs"><% if (is_current(theme.menu.categories)) { %><%- partial('_partial/category') %><% } else if (is_current(theme.menu.tags)) { %><%- partial('_partial/tag') %><% } else { %><%- partial('_partial/custom') %><% } %></code></pre><p>这里,我们需要根据当前自定义页面的类型来决定渲染何种自定义页面模板。</p><p>新建<code>_partial/category.ejs</code>:</p><pre><code class="ejs"><section class="archive"> <ul class="post-archive"> <% site.categories.each(function (category) { %> <span><%= category.name %></span> <% category.posts.forEach(function(post) { %> <li class="post-item"> <span class="post-date"><%= date(post.date, "YYYY-MM-DD") %></span> <a class="post-title" href="<%- url_for(post.path) %>"><%= post.title %></a> </li> <% }) %> <% }) %> </ul></section></code></pre><p><code>site.categories</code>包括了站点所有的分类信息,可以遍历获取分类信息,其中<code>category.posts</code>又包含了该分类的所有文章信息。</p><p>需要注意的是,要想在页面中展示分类页,需要先执行<code>hexo new page categories</code>生成分类页面,并添加<code>type</code>为<code>categories</code>:</p><pre><code class="markdown">title: categoriesdate: 2019-02-25 18:19:55type: "categories"---</code></pre><p>后续的标签页类似。</p><h3 id="添加标签页"><a href="#添加标签页" class="headerlink" title="添加标签页"></a>添加标签页</h3><p>标签页与分类页及其类似,只是根据标签进行归档。</p><p>新建<code>_partial/tag.ejs</code>:</p><pre><code class="ejs"><section class="archive"> <ul class="post-archive"> <% site.tags.each(function (tag) { %> <span><%= tag.name %></span> <% tag.posts.forEach(function(post) { %> <li class="post-item"> <span class="post-date"><%= date(post.date, "YYYY-MM-DD") %></span> <a class="post-title" href="<%- url_for(post.path) %>"><%= post.title %></a> </li> <% }) %> <% }) %> </ul></section></code></pre><h3 id="添加自定义页面"><a href="#添加自定义页面" class="headerlink" title="添加自定义页面"></a>添加自定义页面</h3><p>自定义页面与文章详情页类似。</p><p>新建<code>_partial/custom.ejs</code>:</p><pre><code class="ejs"><article class="post"> <div class="post-title"> <h2 class="title"><%= page.title %></h2> </div> <div class="post-meta"> <span class="post-time"><%- date(page.date, "YYYY-MM-DD") %></span> </div> <div class="post-content"> <%- page.content %> </div></article></code></pre><p>我们在主题配置文件中添加自定义页面的菜单:</p><pre><code class="yaml">menu: home: / categories: /categories tags: /tags archives: /archivesz about: /about</code></pre><p>执行<code>hexo new page about</code>进行手动生成页面,编辑文件内容即可。</p><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1g0iw9k3aonj21z214safs.jpg" alt=""></p><h3 id="Hexo插件"><a href="#Hexo插件" class="headerlink" title="Hexo插件"></a>Hexo插件</h3><p>Hexo 有强大的插件系统,让我们能够轻松扩展功能而不用修改核心模块的源码。在 Hexo 中有两种形式的插件:</p><ul><li><p>脚本(Scripts)</p></li><li><p>插件(Packages)</p></li></ul><p>如果我们的代码很简单,我们可以编写脚本,只需要把 JavaScript 文件放到 <code>scripts</code> 文件夹,在启动时就会自动载入。简单来说,脚本文件可以相当于一些这样的的工具函数,当我们发现Hexo官方提供的函数不能满足我们的需求时,我们可以通过添加一个脚本来实现。</p><p>比如,我们现在有这样一个简单的需求,我们想给首页文章列表中的文章块添加一个背景颜色,背景颜色我们可以在文章md文件中定义,如果未定义,则随机选用一种颜色。</p><p>首先,我们先在文章md文件中顶部<a href="https://hexo.io/zh-cn/docs/front-matter" target="_blank" rel="noopener">Front-matter</a>添加一个<code>color</code>字段:</p><p><code>_posts/hello-world-1.md</code>:</p><pre><code class="markdown">title: Hello World 1date: 2019-02-12 17:49:32categories: 分类1tags: - 标签1color: blue---</code></pre><p>定义完成后,我们就可以在文章信息字段<code>post</code>或者<code>page</code>中获取到<code>color</code>。</p><p>然后,我们需要添加一个脚本函数来根据<code>color</code>字段来获取文章块的背景颜色,新增<code>scripts/getPostBgColor.js</code>:</p><pre><code class="js">const arr = [ 'blue', 'purple', 'green', 'yellow', 'red', 'orange' ];var getPostBgColor = function(color) { if (arr.indexOf(color) >= 0) { return `bg-${color}`; } return 'bg-' + randBgColor();};function randBgColor() { return arr[randomInt(0, 5)];}function randomInt(min, max) { return Math.round(Math.random() * (max - min)) + min;}hexo.extend.helper.register('getPostBgColor', getPostBgColor);</code></pre><p>最后一行我们通过<code>hexo.extend.helper.register</code>全局注册一个脚本函数,注册完成后,我们就可以在模板文件中和Hexo官方提供的全局函数一样使用。</p><p>修改<code>layout/index.ejs</code>:</p><pre><code class="ejs">...<article class="post <%= getPostBgColor(post.color) %>">...</code></pre><p>添加背景颜色样式,编辑<code>css/index.styl</code>:</p><pre><code class="stylus">....bg-blue { background-color: #6fa3ef;}.bg-purple { background-color: #bc99c4;}.bg-green { background-color: #46c47c;}.bg-yellow { background-color: #f9bb3c;}.bg-red { background-color: #e8583d;}.bg-orange { background-color: #f68e5f;}</code></pre><p>看下效果,Hello World 1这篇文章我们定义了<code>color:blue</code>,因此是蓝色,其他文章,我们未定义<code>color</code>,因此是随机颜色。</p><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1g0jm9hctmlj21z214sq8n.jpg" alt=""></p><p>这样,我们就实现了随机背景色这个小需求,当然这只是一个非常简单的例子,如果有其他复杂的需求,我们可以通过编写更加复杂的脚本来实现。</p><h3 id="Hexo的数据DB扩展查询"><a href="#Hexo的数据DB扩展查询" class="headerlink" title="Hexo的数据DB扩展查询"></a>Hexo的数据DB扩展查询</h3><p>我们已经知道,Hexo已经为我们预先定义了很多常用的变量供我们使用,具体可以在 <a href="https://hexo.io/zh-cn/docs/variables" target="_blank" rel="noopener">Hexo | 变量</a> 查询。但是如果系统提供的变量数据不能满足我们的要求,那我们该怎么办呢?其实我们可以通过扩展查询来获取到我们期望的数据。</p><p>其实Hexo所有的文章分类标签等等变量信息,在编译成本地静态文件之前,都是本地存储在一个<code>db.json</code>中的,相当于小型的本地数据库,Hexo在运行阶段,所有的数据相关操作其实都是在这个小型数据库上进行操作,其底层使用的查询引擎就是<a href="https://hexojs.github.io/warehouse/Query.html" target="_blank" rel="noopener">Warehouse</a>。因此我们可以通过Warehouse的语法进行自定义扩展查询。</p><p>比如我们需要在页面的底部展示全站的最近6篇文章列表,由于Hexo首页只提供了第一页的数据,因此我们可以基于<code>site</code>变量进行扩展查询:</p><pre><code class="ejs">site.posts.sort({date: -1}).limit(6)</code></pre><p><code>site.posts</code>表示所有的文章,<code>sort({date: -1})</code>表示按创建时间倒序排列,<code>limit(6)</code>表示只取前6条数据,这样我们就可以拿到了全站的最近6文章信息,后续进行相应展示操作即可。</p><p>其他更多复杂的扩展查询都可以根据Warehouse语法文档进行按需扩展。</p><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>其实说白了,Hexo就是把那些 Markdown 文件,按照我们编写的对应布局模板,填上对应的数据生成 HTML 页面,然后在编译的过程中将JS/CSS等文件引入HTML,然后生成每个页面的对应HMTL静态文件。</p><p>而Hexo主题的作用就是决定每个布局模板长什么样。</p><h3 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h3><ul><li><a href="https://hexojs.github.io/warehouse/index.html" target="_blank" rel="noopener">Warehouse 文档</a></li><li><a href="https://hexo.io/zh-cn/docs/themes" target="_blank" rel="noopener">Hexo | 主题</a></li><li><a href="https://hexo.io/zh-cn/docs/templates" target="_blank" rel="noopener">Hexo | 模板</a></li><li><a href="https://hexo.io/zh-cn/docs/variables" target="_blank" rel="noopener">Hexo | 变量</a></li><li><a href="https://hexo.io/zh-cn/docs/helpers" target="_blank" rel="noopener">Hexo | 辅助函数</a></li><li><a href="https://www.ahonn.me/2016/12/15/create-a-hexo-theme-from-scratch/#%E6%B7%BB%E5%8A%A0%E5%BD%92%E6%A1%A3%E9%A1%B5" target="_blank" rel="noopener">https://www.ahonn.me/2016/12/15/create-a-hexo-theme-from-scratch/#%E6%B7%BB%E5%8A%A0%E5%BD%92%E6%A1%A3%E9%A1%B5</a></li></ul>]]></content>
<summary type="html">
<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>本文将会从零开始编写一个简单的Hexo博客主题,目的是了解一个Hexo博客主题的构成以及如何编写,因此,本示例中的博客页面样式不做过多描绘,
</summary>
<category term="Tutorials" scheme="https://chenyubo.me/categories/Tutorials/"/>
<category term="Hexo" scheme="https://chenyubo.me/tags/Hexo/"/>
<category term="Theme" scheme="https://chenyubo.me/tags/Theme/"/>
</entry>
<entry>
<title>Pinghsu,A Hexo Theme</title>
<link href="https://chenyubo.me/hexo-theme-pinghsu/"/>
<id>https://chenyubo.me/hexo-theme-pinghsu/</id>
<published>2019-02-02T04:46:25.000Z</published>
<updated>2019-02-20T14:07:28.996Z</updated>
<content type="html"><![CDATA[<h2 id="Pinghsu"><a href="#Pinghsu" class="headerlink" title="Pinghsu"></a>Pinghsu</h2><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzsfoy2cpkj21i40w4agz.jpg" alt=""></p><p>本主题移植于<a href="https://github.com/chakhsu" target="_blank" rel="noopener">chakhsu</a>的Typecho主题<a href="https://github.com/chakhsu/pinghsu" target="_blank" rel="noopener">pinghsu</a>,将其基于Hexo进行重写。</p><p>引用原作者对主题的一句话介绍:</p><blockquote><p>Pinghsu 是一款以前端性能优化为出发点而制作的 Hexo 主题,同时又兼顾设计美学和视觉传达。</p></blockquote><p>非常感谢原作者写出这么精美的主题供我们使用。</p><h2 id="更多预览"><a href="#更多预览" class="headerlink" title="更多预览"></a>更多预览</h2><table><thead><tr><th>首页 - 三栏</th><th>首页 - 单栏</th></tr></thead><tbody><tr><td><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs472hub0j212o0u0x4b.jpg" alt=""></td><td><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs47jccpdj212o0u0asm.jpg" alt=""></td></tr></tbody></table><table><thead><tr><th>文章内容页 - 题图</th><th>文章页 - 目录</th></tr></thead><tbody><tr><td><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs4ebe3g8j212o0u04c1.jpg" alt=""></td><td><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs4ekgj9zj212o0u0gtj.jpg" alt=""></td></tr></tbody></table><table><thead><tr><th>页面内容页</th><th>归档页</th></tr></thead><tbody><tr><td><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs4et3z9jj212o0u0afa.jpg" alt=""></td><td><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs4eyxefjj212o0u0tdo.jpg" alt=""></td></tr></tbody></table><table><thead><tr><th>分类页</th><th>分类详情页</th></tr></thead><tbody><tr><td><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs4fstfgvj212o0u0af9.jpg" alt=""></td><td><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs4fzojorj212o0u0wkl.jpg" alt=""></td></tr></tbody></table><table><thead><tr><th>标签页</th><th>标签详情页</th></tr></thead><tbody><tr><td><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs4g6fv2xj212o0u0wkg.jpg" alt=""></td><td><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs4gbxbb3j212o0u0wjy.jpg" alt=""></td></tr></tbody></table><table><thead><tr><th>移动端 - 首页</th><th>移动端 - 文章页</th><th>移动端 - 归档页</th></tr></thead><tbody><tr><td><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs4nqaebfj20yi22ohdz.jpg" alt=""></td><td><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs4nvydnvj20yi22o7g3.jpg" alt=""></td><td><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs4q06qtnj20yi22ok05.jpg" alt=""></td></tr></tbody></table><table><thead><tr><th>移动端 - 分类页</th><th>移动端 - 标签页</th><th>移动端 - 详情归档页</th></tr></thead><tbody><tr><td><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs4oif8u9j20yi22ownz.jpg" alt=""></td><td><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs4on2tsrj20yi22ogx7.jpg" alt=""></td><td><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs4ot9p54j20yi22ok43.jpg" alt=""></td></tr></tbody></table><p>下载地址:<a href="https://github.com/cccyb/hexo-theme-pinghsu" target="_blank" rel="noopener">https://github.com/cccyb/hexo-theme-pinghsu</a></p><p>在线预览:<a href="https://chenyubo.me">https://chenyubo.me</a></p><h2 id="主题亮点"><a href="#主题亮点" class="headerlink" title="主题亮点"></a>主题亮点</h2><ul><li>页面预加载与DNS预解析保证极快访问速度</li><li>无JQuery,无前端框架,无webfont</li><li>HighlightJS代码高亮,支持22种编程代码</li><li>响应式设计,支持平板与手机,访问体验甚至优于桌面</li><li>支持图片CDN镜像,支持多种文章缩略图设置</li><li>支持首页三栏和单栏选择,文章题图和色块</li><li>支持文章目录、相关文章与数学公式渲染</li><li>支持文章个性化标徽设置,10种标徽选择</li><li>支持个人社交按钮,社交分享</li><li>还有更多亮点等你去发现~</li></ul><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><h3 id="前期准备"><a href="#前期准备" class="headerlink" title="前期准备"></a>前期准备</h3><blockquote><p>安装主题前请确保已根据Hexo官方文档已搭建好本地站点,并能正常启动。</p></blockquote><p>参考链接:</p><ul><li><a href="https://hexo.io/zh-cn/docs" target="_blank" rel="noopener">概述</a></li><li><a href="https://hexo.io/zh-cn/docs/setup" target="_blank" rel="noopener">建站</a></li></ul><h3 id="下载主题"><a href="#下载主题" class="headerlink" title="下载主题"></a>下载主题</h3><p>进入<code>Hexo</code>博客目录下,下载主题至主题<code>themes</code>目录下:</p><pre><code class="bash">$ cd your-hexo-site$ git clone https://github.com/cccyb/hexo-theme-pinghsu.git themes/pinghsu</code></pre><h3 id="启用主题"><a href="#启用主题" class="headerlink" title="启用主题"></a>启用主题</h3><p>修改根目录下的<strong>站点配置文件</strong><code>_config.yml</code>中的 <code>theme</code> 字段为 <code>pinghsu</code>:</p><pre><code class="yml"># Extensions## Plugins: https://hexo.io/plugins/## Themes: https://hexo.io/themes/theme: pinghsu</code></pre><h3 id="更新主题"><a href="#更新主题" class="headerlink" title="更新主题"></a>更新主题</h3><p>进入<code>Hexo</code>博客目录下的主题<code>themes</code>目录下的<code>pinghsu</code>目录:</p><pre><code class="bash">$ cd your-hexo-site/themes/pinghsu$ git pull</code></pre><h2 id="主题设定"><a href="#主题设定" class="headerlink" title="主题设定"></a>主题设定</h2><h3 id="选择主题外观"><a href="#选择主题外观" class="headerlink" title="选择主题外观"></a>选择主题外观</h3><p>主题提供两套外观进行选择,他们是:</p><ul><li>三栏(three)- 默认三栏</li><li>单栏(one)</li></ul><p>你可以通过修改<code>主题配置文件</code>下的<code>postListSwitch</code>字段进行修改:</p><pre><code class="yaml"># 首页文章列表设置# 默认三列# three: 三列,one:一列postListSwitch: three</code></pre><h3 id="设置网站通用配置"><a href="#设置网站通用配置" class="headerlink" title="设置网站通用配置"></a>设置网站通用配置</h3><p>编辑<strong>站点配置文件</strong><code>_config.yml</code>,修改相关配置:</p><pre><code class="yml"># Sitetitle: 输入你的博客标题...description: 输入你的博客描述keywords: 输入你的博客关键词author: 输入你的名字# URLurl: 你的域名</code></pre><h3 id="设置语言和时区"><a href="#设置语言和时区" class="headerlink" title="设置语言和时区"></a>设置语言和时区</h3><p>编辑<strong>站点配置文件</strong><code>_config.yml</code>,将 <code>language</code> 设置成你所需要的语言。建议明确设置你所需要的语言,例如选用简体中文。将<code>timezone</code>设置成你所在的时区,配置如下:</p><pre><code class="yml">language: zh-CNtimezone: Asia/Shanghai</code></pre><p>目前本主题支持以下语言:</p><table><thead><tr><th>语言</th><th>代码</th><th>设定示例</th></tr></thead><tbody><tr><td>简体中文</td><td>zh-CN</td><td><code>language: zh-CN</code></td></tr><tr><td>繁體中文</td><td>zh-TW</td><td><code>language: zh-TW</code></td></tr><tr><td>English</td><td>en</td><td><code>language: en</code></td></tr><tr><td>日本語</td><td>ja</td><td><code>language: ja</code></td></tr><tr><td>Korean</td><td>ko</td><td><code>language: ko</code></td></tr></tbody></table><p>默认使用简体中文(zh-CN)语言,如有需要,可以按需进行更改。</p><h4 id="禁用Hexo默认自带代码高亮"><a href="#禁用Hexo默认自带代码高亮" class="headerlink" title="禁用Hexo默认自带代码高亮"></a>禁用Hexo默认自带代码高亮</h4><p>由于hexo默认自带的代码高亮配置与主题代码高亮样式有所冲突,所以需要将默认的禁用,后续在主题配置文件中进行代码高亮配置。</p><p>编辑<strong>站点配置文件</strong><code>_config.yml</code>:</p><pre><code class="yml"># Writing...highlight: enable: false line_number: false auto_detect: false tab_replace: </code></pre><h2 id="文档"><a href="#文档" class="headerlink" title="文档"></a>文档</h2><ul><li>主题配置文档见:<a href="https://github.com/cccyb/hexo-theme-pinghsu/wiki/%E4%B8%BB%E9%A2%98%E9%85%8D%E7%BD%AE" target="_blank" rel="noopener">主题配置</a></li><li>第三方服务文档见:<a href="https://github.com/cccyb/hexo-theme-pinghsu/wiki/%E7%AC%AC%E4%B8%89%E6%96%B9%E6%9C%8D%E5%8A%A1" target="_blank" rel="noopener">第三方服务</a></li></ul><h2 id="感谢"><a href="#感谢" class="headerlink" title="感谢"></a>感谢</h2><p>再次感谢原作者<a href="https://github.com/chakhsu" target="_blank" rel="noopener">chakhsu</a>创作出这么精美的主题 <a href="https://github.com/chakhsu/pinghsu" target="_blank" rel="noopener">pinghsu</a> 。</p><h2 id="贡献"><a href="#贡献" class="headerlink" title="贡献"></a>贡献</h2><p>欢迎各种形式的贡献,包括但不限于优化,添加功能,文档 & 代码的改进,问题和 bugs 的报告。</p><h2 id="许可证"><a href="#许可证" class="headerlink" title="许可证"></a>许可证</h2><p><a href="https://opensource.org/licenses/MIT" target="_blank" rel="noopener">MIT</a></p>]]></content>
<summary type="html">
<h2 id="Pinghsu"><a href="#Pinghsu" class="headerlink" title="Pinghsu"></a>Pinghsu</h2><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1
</summary>
<category term="Tutorials" scheme="https://chenyubo.me/categories/Tutorials/"/>
<category term="Hexo" scheme="https://chenyubo.me/tags/Hexo/"/>
<category term="Theme" scheme="https://chenyubo.me/tags/Theme/"/>
<category term="Pinghsu" scheme="https://chenyubo.me/tags/Pinghsu/"/>
</entry>
<entry>
<title>服务器入门指北</title>
<link href="https://chenyubo.me/server-guide/"/>
<id>https://chenyubo.me/server-guide/</id>
<published>2019-01-18T04:46:25.000Z</published>
<updated>2019-02-02T09:49:45.958Z</updated>
<content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>说起为啥又双叒叕的折腾起新服务器了,具体原因概括起来应该就是以下几点:</p><ul><li>以前在大学弄的阿里云学生主机过期了,</li><li>原来的阿里云学生主机上也部署了几个项目,想着还是捡回来的比较好</li><li>以前单纯为了搭ss买的vps硬盘和内存都太小了,装完ss基本就告罄了,也折腾不了其他东西了</li><li>国内的主机都有点太贵了,只能退而求其次买个国外的配置稍微好点的主机,一可以多折腾一些小东西,二可以顺便搭个ss,也就可以把以前的那个ss主机停了</li></ul><p>总结起来就是一句话:不要怂,就是折腾,干就完了~</p><h3 id="选择服务器"><a href="#选择服务器" class="headerlink" title="选择服务器"></a>选择服务器</h3><p>我选用的是国外比较著名的<a href="https://www.vultr.com/" target="_blank" rel="noopener">Vlutr</a>,洛杉矶主机,CentOs7.0系统,5刀/月的套餐。具体选啥主机,选啥套餐,用啥系统,根据每个人的需求因人而异,我不多做介绍。如果有兴趣的可以看下我同事写的文章,<a href="http://taoweng.site/index.php/archives/99/#directory01186845456699059412" target="_blank" rel="noopener">国外服务器如何选择以及搭建ShadowSocks教程</a>,里面比较详细的介绍了如果选择国外服务器。</p><h3 id="登录服务器"><a href="#登录服务器" class="headerlink" title="登录服务器"></a>登录服务器</h3><p>购买完主机了,就可以开始登录我们的服务器了。由于本人使用的是Mac系统,Mac的终端自带ssh,下面都以Mac系统为主,所以如果使用Windows的同学,可以自行百度搜索如何登录服务器,比较著名的是Putty和Xshell。</p><p>打开iTerm终端,username一般默认是root,然后在终端使用<code>ssh root@ip</code>命令远程连接服务器,在Vultr主机信息页面复制密码,在终端粘贴即可,<strong>注意,这里输入密码时终端是看不到的,</strong>粘贴完回车即可。</p><p>正常情况下,没有意外的话,你的终端应该已经成功进入了服务器的终端命令行输入界面。</p><p>但是,如果你输完ip,一直处于空白等待状态,没有提示你输入密码,那这时候要注意了,极有可能是你申请的主机ip和端口被墙了,导致ssh连接不上,这时你就需要检测一下主机是否真的被墙了。</p><p>具体可以见<a href="https://www.vultrcn.com/11.html" target="_blank" rel="noopener">Vultr 能 Ping 但是 SSH 无法连接的解决办法</a>,按照里面的方法进行测试,如果确定是被ip和端口被封了,解决方案就是申请新的服务器主机以获取新的ip<strong>(注意:这里操作时必须保留原有的服务器,再额外申请新的服务器,这样才能获得新的ip,如果你先删除原有的服务器,然后在申请,这样申请到的服务器ip是和原先的一样的,)</strong>,同时对新得到的ip继续进行ssh登录,如果ssh登录时提示输入密码,即表示这台服务器的ip是可以使用的,此时可以删除前面申请的无效的服务器,否则重复申请操作直到获取一个可以使用的ip为止。</p><h3 id="安装宝塔面板"><a href="#安装宝塔面板" class="headerlink" title="安装宝塔面板"></a>安装宝塔面板</h3><p>简单好用的 Linux/Windows 面板:<a href="https://www.bt.cn/" target="_blank" rel="noopener">https://www.bt.cn/</a></p><p>建议安装一个宝塔面板,方便管理Linux,对于服务器小白特别适用,也适合我这种懒人,如果有服务器大神或者愿意折腾的小伙伴可以跳过。</p><ol><li>安装宝塔</li></ol><ul><li>CentOS安装命令:</li></ul><pre><code class="bash">yum install -y wget && wget -O install.sh http://download.bt.cn/install/install.sh && sh install.sh</code></pre><ul><li>Ubuntu/Deepin安装命令:</li></ul><pre><code class="bash">wget -O install.sh http://download.bt.cn/install/install-ubuntu.sh && sudo bash install.sh</code></pre><ul><li>Debian安装命令:</li></ul><pre><code class="bash">wget -O install.sh http://download.bt.cn/install/install-ubuntu.sh && bash install.sh</code></pre><ul><li>Fedora安装命令:</li></ul><pre><code class="bash">wget -O install.sh http://download.bt.cn/install/install.sh && bash install.sh</code></pre><p>中间需要根据提示输入 “y” 或者自定义目录,新手不了解的情况下最好不要动。</p><ol start="2"><li><p>安装完终端会显示宝塔登录地址,以及随机生成的用户名密码,在浏览器中输入登录宝塔面板</p></li><li><p>进入首页,会建议你安装web运行环境:LNMP(Linux + Nginx + MySQL + PHP)或LAMP(Linux + Apache + MySQL + PHP),这里推荐使用LNMP,使用极速安装,对新手友好。</p></li><li><p>点击侧边栏的面板设置,修改面板别名、默认端口、面板用户和密码。</p></li><li><p>点击侧边栏的安全,修改ssh登录端口号。</p></li><li><p>宝塔常用linux命令大全:<a href="https://www.bt.cn/btcode.html,有需要可以查看。" target="_blank" rel="noopener">https://www.bt.cn/btcode.html,有需要可以查看。</a></p></li></ol><h3 id="搭建-Shadowsocks-服务,科学上网"><a href="#搭建-Shadowsocks-服务,科学上网" class="headerlink" title="搭建 Shadowsocks 服务,科学上网"></a>搭建 Shadowsocks 服务,科学上网</h3><ol><li>检测是否安装Python和Pip</li></ol><pre><code class="bash">python -Vpip -V</code></pre><p>如果正确显示python和pip的版本,则跳转第3步进行安装Shadowsocks,否则跳转第2步安装pip</p><ol start="2"><li>安装pip</li></ol><pre><code class="bash">yum install python-setuptools && easy_install pip</code></pre><ol start="3"><li>安装Shadowsocks</li></ol><pre><code class="bash">pip install shadowsocks</code></pre><ol start="4"><li>配置服务器参数</li></ol><p>生成配置文件:<code>touch /etc/shadowsocks.json</code></p><p>编辑配置文件:<code>vi /etc/shadowsocks.json</code></p><p>写入以下配置:</p><pre><code class="json">{ "server":"my_server_ip", // 你的服务器ip "server_port": 8388, // 端口自定义 "local_address": "127.0.0.1", "local_port":1080, "password":"mypassword", // 自定义密码,后续客户端连接需要用到 "timeout":300, "method":"aes-256-cfb", "fast_open": false}</code></pre><ul><li>server:填写你的服务器的ip</li><li>server_port:填写端口,自定义</li><li>password:填写你自定义的密码,后续客户端连接需要用到</li></ul><ol start="5"><li>开启防火墙端口</li></ol><p>进入宝塔面板,点击安全,在下方端口界面出输入8388端口,点击放行即可。</p><p>或者使用命令行</p><pre><code class="bash">firewall-cmd --permanent --zone=public --add-port=8388/tcpfirewall-cmd --reload</code></pre><ol start="6"><li>后台运行服务</li></ol><pre><code class="bash">ssserver -c /etc/shadowsocks.json -d start</code></pre><p>至此,服务端的搭建就完成了,后续只需要在你的电脑上下载一个客户端配置即可。</p>]]></content>
<summary type="html">
<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>说起为啥又双叒叕的折腾起新服务器了,具体原因概括起来应该就是以下几点:</p>
<ul>
<li>以前在大学弄的阿里云学生主机过期了,</l
</summary>
<category term="Tutorials" scheme="https://chenyubo.me/categories/Tutorials/"/>
<category term="Server" scheme="https://chenyubo.me/tags/Server/"/>
<category term="Node" scheme="https://chenyubo.me/tags/Node/"/>
<category term="Vps" scheme="https://chenyubo.me/tags/Vps/"/>
</entry>
<entry>
<title>初见Scroll-Snap</title>
<link href="https://chenyubo.me/start-scroll-snap/"/>
<id>https://chenyubo.me/start-scroll-snap/</id>
<published>2018-10-18T04:46:25.000Z</published>
<updated>2019-02-02T09:50:31.331Z</updated>
<content type="html"><![CDATA[<h2 id="什么是CSS-Scroll-Snap?"><a href="#什么是CSS-Scroll-Snap?" class="headerlink" title="什么是CSS Scroll Snap?"></a>什么是CSS Scroll Snap?</h2><p>我们先看一下MDN里对scroll snap的解释:</p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/181019_64d78b0fga46dbf98cc8ce5fb2lkh_642x245.jpg" alt=""></p><p>英语不好的童鞋可以悄悄咪咪的使用百度翻译或者谷歌翻译帮个忙,这段话的大意应该就是:</p><blockquote><p> CSS Scroll Snap是CSS的一个模块,它引入了滚动捕捉位置,可以在滚动操作完成后强制滚动容器的滚动窗口到我们指定的滚动位置。</p></blockquote><p>看了还是一脸懵逼?没关系,我们先看个在线🌰(<a href="https://codepen.io/airen/pen/EeYNwr" target="_blank" rel="noopener">https://codepen.io/airen/pen/EeYNwr</a>),思考一下这个🌰里的滚动与我们平时写的滚动有什么区别呢?</p><p>没错,在使用了scroll snap属性后,元素滚动起来有了一种阻尼感,并没有原生滚动的那种顺滑感,并且可以精确定位到指定位置。</p><p>简单来说,就是CSS Scroll Snap(CSS 滚动捕捉)允许你在用户完成滚动后多锁定特定的元素或位置。</p><h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>开始之前,我们先介绍两个概念。</p><ul><li>捕捉</li></ul><p>学过 CAD 系列软件的同学可能很清楚,我们在移动一个对象时,对象总能够自动吸附在栅格线上,使得对象只能落在栅格上的确定位置上,这就是栅格捕捉。或者这样说,在一个普通的量尺上,规定你的画笔只能落在 1mm 和 2mm 的刻度上,而不能落在他们之间。</p><ul><li>滚动捕捉</li></ul><p>滚动捕捉,即在滚动时对滚动位置进行捕捉。</p><p>其实scroll snap的用法很简单,最最最基本的用法只要两行代码就可以实现,先在父元素上定义<code>scroll-snap-type</code>,然后在子元素上定义<code>scroll-snap-align</code>即可。</p><pre><code class="html"><div class="container"> <section class="child"></section> <section class="child"></section> <section class="child"></section> ...</div></code></pre><pre><code class="css">.container { scroll-snap-type: y madatory;}.child { scroll-snap-align: start;}</code></pre><p>是不是很简单,这里我们先对scroll snap属性有个大概的了解,后续我们会详细讲解。</p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/181019_0l24i1l0c1hk9ddi1d1fkfci35i4l_922x290.jpg" alt=""></p><p>上图是来自w3c标准里的一个图示,这个图其实非常形象了描述了滚动捕捉。</p><p>图中的红色区域即为可滚动容器的可视区域或叫捕捉视口。图片黄色框的地方被称为捕捉区域。我们上面设置的 scroll-snap-align 中指定了横轴捕捉点为中心位置。此时将在捕捉视口区域中心(红色虚线)以及捕捉区域中心(黄色虚线)形成捕捉点。</p><p>由此我们可以知道,要想形成捕捉,需要以下两个条件:</p><ol><li>是个可滚动的区域</li><li>确定捕捉视口和捕捉区域的捕捉点</li></ol><p>既然我们要使用CSS属性,那么了解它的流量器兼容性是必不可少的。</p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/181019_34cl4f6h459549l348i816a7000di_915x400.jpg" alt=""></p><p>自2016年推出CSS Scroll Snap以来,浏览器对它的支持有了显著的改善。Google 69+、Firefox、Edge和Safari都支持它的某些版本。但是现实其实还是很残酷的,整体浏览器对scroll snap的支持度并不是很高,只要50%多,不到60%,因此,这个属性我们在平时使用还是需要谨慎考虑兼容性,使用最新的浏览器进行尝鲜未尝不可。待后续各大浏览器稳定支持后再进行扩展。</p><h2 id="属性"><a href="#属性" class="headerlink" title="属性"></a>属性</h2><p>与任何属性一样,熟悉它们所接受的值是一个好主意。滚动捕捉属性应用于父元素和子元素,每个元素都有特定的值。就像Flexbox和Grid那样,父类变成了Flex或Grid容器。在这种情况下,父元素变成了快照(Snap)容器。</p><p>父容器属性主要有两个:</p><ul><li>scroll-snap-type</li></ul><p><img src="https://s10.mogucdn.com/mlcdn/c45406/181019_5b71f8hcbakj2ckdf4jglk0h1401g_796x544.jpg" alt=""></p><p>通过设置 scroll-snap-type 将一个滚动容器转变为一个滚动捕捉容器,并且可以控制捕捉的严格度,如果没有指定严格度,默认为非精确的捕捉(proximity)。</p><p>scroll-snap-type 支持设置两个参数,第一个为捕捉轴向,第二个参数为捕捉严格度,可省略。</p><p>proximity值与mandatory十分相似,只是没有那么严格。改变浏览器的大小或者增加内容区,它可能会(或者而不会)重新获取snap点,取决于它与snap点间的距离。</p><ul><li>scroll-snap-padding</li></ul><p>默认情况下,内容会吸附到容器的边缘。你可以通过在容器上设置scroll-snap-padding属性来改变它。它遵循与常规padding属性相同的语法。如果你的布局中有可能妨碍内容的元素(比如固定的标题),那么这个属性就非常的有用。</p><p>子元素属性主要有三个:</p><ul><li>scroll-snap-align</li></ul><p><img src="https://s10.mogucdn.com/mlcdn/c45406/181019_7dkf7fig7i557lh15ike64fcfe9g4_731x451.jpg" alt=""></p><p>这些是相对于滚动方向的。如果是垂直滚动,start指的是元素的顶部边缘。如果是水平滚动条,它指的是左边缘。center和end遵循相同的原则。你可以为滚动条的不同方向设置不同的值,这两个值之间用空格分隔开。</p><ul><li>scroll-snap-margin</li></ul><p>scroll-margin 则是指定了捕捉区域与捕捉元素之间的边距。例如对捕捉区域设置了 scroll-margin: 20px; 那么实际上生成的捕捉区域会比捕捉元素的尺寸大。 scroll-margin 的参数与我们常见的 margin 参数形式相同,同时也有 margin 一样的 scroll-margin-top 等属性。</p><ul><li>scroll-snap-stop</li></ul><p>默认情况下,滚动捕捉仅在用户停止滚动时启动,这意味着用户可以在停止之前跳过多个捕捉点。</p><p>你可以在任何子元素上设置scroll-snap-stop: always来改变它。这会强制滚动容器在该元素上停止,然后用户可以继续滚动。</p><h2 id="举几个🌰"><a href="#举几个🌰" class="headerlink" title="举几个🌰"></a>举几个🌰</h2><ul><li>垂直列表</li></ul><p>要使用垂直列表与每个列表元素对齐,只需要几行CSS。首先,我们告诉容器沿骑垂直轴捕捉:</p><pre><code class="css">.container { scroll-snap-type: y mandatory;}</code></pre><p> 然后,我们定义捕捉点。这里,我们指定每个列表元素的顶部将成为一个捕捉点:</p><pre><code class="css">.child { scroll-snap-align: start;}</code></pre><p>在线预览效果见:<a href="https://codepen.io/airen/pen/yxBMPa" target="_blank" rel="noopener">https://codepen.io/airen/pen/yxBMPa</a></p><ul><li>水平滑块</li></ul><p>为了制作一个水平滑块,我们告诉容器沿着它的<code>x</code>轴对齐。</p><pre><code class="css">.container { scroll-snap-type: x mandatory;}</code></pre><p> 然后,我们告诉容器哪个点被捕捉。为了使图库居中,我们将每个元素的中心点定义为一个捕捉点。</p><pre><code class="css">.child { scroll-snap-align: center;}</code></pre><p>在线预览效果见:<a href="https://codepen.io/cccyb/pen/KGQdMz" target="_blank" rel="noopener">https://codepen.io/cccyb/pen/KGQdMz</a></p><ul><li>垂直全屏</li></ul><p>我们可以直接在<code>body</code>元素<code>y</code>轴上设置捕捉点:</p><pre><code class="css">body { scroll-snap-type: y mandatory;}</code></pre><p>然后,我们将每个部分的大小设置和视窗一样大,并将顶部边缘定义为捕捉点:</p><pre><code class="css">section { height: 100vh; width: 100vw; scroll-snap-align: start;}</code></pre><p> 在线预览效果见:<a href="https://codepen.io/airen/pen/GXKWyL" target="_blank" rel="noopener">https://codepen.io/airen/pen/GXKWyL</a></p><ul><li>水平全屏</li></ul><p>这个案例与前面的垂直全屏类似,但在<code>x</code>轴上使用了捕捉点。</p><pre><code class="css">body { scroll-snap-type: x mandatory;}section { height: 100vh; width: 100vw; scroll-snap-align: start;}</code></pre><p>在线预览见:<a href="https://codepen.io/airen/pen/EeYWQb" target="_blank" rel="noopener">https://codepen.io/airen/pen/EeYWQb</a></p><ul><li>2D图像网格</li></ul><p>滚动捕捉可以同时在两个方向上工作。同样,我们可以直接在<code>body</code>元素上设置<code>scroll-snap-type</code>:</p><pre><code class="css">.container { scroll-snap-type: both mandatory;}</code></pre><p>然后,将每个<code>.tile</code>左上角定义为一个捕捉点:</p><pre><code class="css">.tile { scroll-snap-align: start;}</code></pre><p><a href="https://codepen.io/airen/pen/aaoJGq" target="_blank" rel="noopener">在线预览见:https://codepen.io/airen/pen/aaoJGq</a></p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>一旦浏览器可以稳定的支持CSS Scroll Snap属性时,对于触控设备产生的意义将十分重大。如,我们可以在next/previous之间快速查看画廊中的每一张图片。</p><p>使用CSS创建Scroll Snap意味着不再需要使用JavaScript或者导入一个多余的库定义滚动行为。并且Scroll Snap属于硬件加速,保证了可以在浏览器中平滑的执行。</p><h2 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h2><ul><li><a href="https://www.w3.org/TR/css-scroll-snap-1/#scroll-snap-stop" target="_blank" rel="noopener">https://www.w3.org/TR/css-scroll-snap-1/#scroll-snap-stop</a></li><li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Scroll_Snap" target="_blank" rel="noopener">https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Scroll_Snap</a></li><li><a href="https://mp.weixin.qq.com/s/0Duum2IKSpc5fPNXPAPf6Q" target="_blank" rel="noopener">https://mp.weixin.qq.com/s/0Duum2IKSpc5fPNXPAPf6Q</a></li><li><a href="https://www.w3cplus.com/css/practical-css-scroll-snapping.html" target="_blank" rel="noopener">https://www.w3cplus.com/css/practical-css-scroll-snapping.html</a></li><li><a href="https://caniuse.com/#search=scroll-snap" target="_blank" rel="noopener">https://caniuse.com/#search=scroll-snap</a></li></ul>]]></content>
<summary type="html">
<h2 id="什么是CSS-Scroll-Snap?"><a href="#什么是CSS-Scroll-Snap?" class="headerlink" title="什么是CSS Scroll Snap?"></a>什么是CSS Scroll Snap?</h2><p>我们
</summary>
<category term="Tutorials" scheme="https://chenyubo.me/categories/Tutorials/"/>
<category term="CSS" scheme="https://chenyubo.me/tags/CSS/"/>
<category term="Scroll Snap" scheme="https://chenyubo.me/tags/Scroll-Snap/"/>
</entry>
<entry>
<title>Mac安装Python3开发环境随记</title>
<link href="https://chenyubo.me/mac-install-python3-env/"/>
<id>https://chenyubo.me/mac-install-python3-env/</id>
<published>2018-08-11T04:46:25.000Z</published>
<updated>2019-02-02T09:49:20.276Z</updated>
<content type="html"><![CDATA[<blockquote><p>前言:毕业后正式入职公司,公司给发了新电脑Mac,为了在平时空余时间可以学习一下大热的Python语言,虽然自己的Mac已经安装过Python开发环境了,但是为了省去来回切换机器的麻烦,因此准备从头安装Python开发环境,顺便记录一下安装过程和踩过的坑,方便大家。</p></blockquote><h3 id="0x00-前言"><a href="#0x00-前言" class="headerlink" title="0x00 前言"></a>0x00 前言</h3><p>Mac已经默认为用户安装内置了Python2.7.10,但是现在Python的版本已经到了Python3,所以我们为了开发时体验到Python最新的版本特性,最好安装Python3。但是直接升级系统默认的Python环境,升级步骤复杂不说,而且可能会因为操作不当导致某些问题,所以为了保险起见,我建议额外安装一个Python3环境,与原有的共存。</p><h3 id="0x01-安装Homebrew"><a href="#0x01-安装Homebrew" class="headerlink" title="0x01 安装Homebrew"></a>0x01 安装Homebrew</h3><p>Homebrew是Mac上一款优秀的包管理工具,具体介绍见官网:<a href="https://brew.sh/" target="_blank" rel="noopener">Homebrew</a></p><p>安装很简单,在终端输入如下命令即可:</p><pre><code class="bash">ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"</code></pre><p>替换Homebrew源,加快安装包的速度,具体步骤这里就不叙述了,详情可以参考:<a href="https://blog.csdn.net/u010275932/article/details/76080833" target="_blank" rel="noopener">更换Homebrew的更新源</a></p><h3 id="0x02-安装Python3"><a href="#0x02-安装Python3" class="headerlink" title="0x02 安装Python3"></a>0x02 安装Python3</h3><p>我们使用前面安装的Homebrew来安装最新的Python</p><p>使用Homebrew安装,在终端输入如下命令:</p><pre><code class="bash">brew install python</code></pre><p>检测Python3是否安装成功:</p><pre><code class="bash">python3 -V</code></pre><p>如显示版本号则表示安装成功</p><h3 id="0x03-替换pip3源"><a href="#0x03-替换pip3源" class="headerlink" title="0x03 替换pip3源"></a>0x03 替换pip3源</h3><p>pip是Python中非常方便易用的安装包管理器,但是在实际下载安装包的时候总是连接不上或者下载速度特别慢,pypi.python.org就是其中一个。</p><p>所以,使用pip给Python安装软件时,经常出现Timeout连接超时错误。修改pip连接的软件库可以解决这个问题。</p><blockquote><p>注意:pip是对应Python2,最新的Python3对应的则是pip3。不管你用的是pip3还是pip,方法都是一样的。</p></blockquote><p>新建.pip文件夹</p><pre><code class="bash">cd ~mkdir .pip</code></pre><p>编辑pip.conf配置文件</p><pre><code class="bash">sudo vi pip.conf</code></pre><p>按<code>i</code>切换成insert模式,输入以下内容:</p><pre><code class="bash">[global] timeout = 6000 index-url = http://pypi.douban.com/simple/ [install] use-mirrors = true mirrors = http://pypi.douban.com/simple/ trusted-host = pypi.douban.com</code></pre><p>依次按下<code>esc</code>,<code>:</code>,<code>w</code> <code>q</code>,退出并保存文件。</p><h3 id="0x04-使用"><a href="#0x04-使用" class="headerlink" title="0x04 使用"></a>0x04 使用</h3><p>可以在终端中使用Python3命令来运行你编写的python代码啦。</p><pre><code class="bash">python3 xxx.py</code></pre><p>你还可以在终端中使用pip3命令来安装你需要的python包。</p><pre><code class="bash">pip3 install xxx</code></pre><h3 id="0x05-结束语"><a href="#0x05-结束语" class="headerlink" title="0x05 结束语"></a>0x05 结束语</h3><p>到此为止,一个最新、快速、简单的Python3开发环境就基本安装配置好了,现在你可以使用编辑器新建一个py后缀文件,编写你的Python代码,然后使用Python3命令来运行。如果代码中需要用到某些Python包,你也可以pip3命令来安装。</p><p>后续更多精彩内容,敬请期待!</p>]]></content>
<summary type="html">
<blockquote>
<p>前言:毕业后正式入职公司,公司给发了新电脑Mac,为了在平时空余时间可以学习一下大热的Python语言,虽然自己的Mac已经安装过Python开发环境了,但是为了省去来回切换机器的麻烦,因此准备从头安装Python开发环境,顺便记录一下安装过程和踩
</summary>
<category term="Notes" scheme="https://chenyubo.me/categories/Notes/"/>
<category term="Mac" scheme="https://chenyubo.me/tags/Mac/"/>
<category term="Python" scheme="https://chenyubo.me/tags/Python/"/>
<category term="Environment" scheme="https://chenyubo.me/tags/Environment/"/>
</entry>
<entry>
<title>初探Grid-Layout布局</title>
<link href="https://chenyubo.me/start-grid-layout/"/>
<id>https://chenyubo.me/start-grid-layout/</id>
<published>2018-08-08T04:46:25.000Z</published>
<updated>2019-02-02T09:58:24.175Z</updated>
<content type="html"><![CDATA[<h1 id="初探Grid-Layout布局"><a href="#初探Grid-Layout布局" class="headerlink" title="初探Grid-Layout布局"></a>初探Grid-Layout布局</h1><h2 id="Grid布局简介"><a href="#Grid布局简介" class="headerlink" title="Grid布局简介"></a>Grid布局简介</h2><p>开始之前,我们先来看一张图:</p><p><img src="https://user-gold-cdn.xitu.io/2018/3/1/161dd2b9841e67fb?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" alt="小草本"></p><p>没错,这其实就是我们小时候写的小格子本本,其实它跟我们今天要讲的主题Grid布局非常类似,其实Grid布局就是它的升级加强版。</p><p>CSS网格布局(又称“网格”),是一种二维网格布局系统。</p><p>CSS在处理网页布局方面一直做的不是很好。一开始我们用的是table(表格)布局,然后用float(浮动),position(定位)和inline-block(行内块)布局,但是这些方法本质上是hack,遗漏了很多功能,例如垂直居中。后来出了<a href="https://link.juejin.im/?target=http%3A%2F%2Fpeale.cn%2F2016%2F11%2F30%2F2016_11_30_flex%2F%23more" target="_blank" rel="noopener">flexbox(盒子布局)</a>,解决了很多布局问题,但是它仅仅是一维布局,而不是复杂的二维布局,实际上它们(flexbox与grid)能很好的配合使用。</p><p>Grid布局是第一个专门为解决布局问题而创建的CSS模块,2012年11月06日成立<a href="https://link.juejin.im/?target=https%3A%2F%2Fwww.w3.org%2FTR%2Fcss3-grid-layout%2F" target="_blank" rel="noopener">草案</a>。</p><p>Grid是一个趋势,grid-layout不是为了取代flex-layout,它是flex的补充。grid擅长二维布局,flex擅长一维布局。他们需要各司其职。</p><h2 id="Grid-Table2-0?"><a href="#Grid-Table2-0?" class="headerlink" title="Grid === Table2.0?"></a>Grid === Table2.0?</h2><p>既然说grid布局是网格布局,那是不是grid布局就是table布局的2.0升级版呢?其实不然。</p><p>他们是有相同之处的。比如都是把元素排列成行和列。但是表格和grid的区别在于,表格是有内容结构的,不能很自由地在里面做布局。而grid内部元素可以自由设定位置,允许重叠和设定层级的样。</p><h2 id="浏览器兼容性"><a href="#浏览器兼容性" class="headerlink" title="浏览器兼容性"></a>浏览器兼容性</h2><p>既然要使用最新的css布局,那浏览器对grid布局的兼容性这个点是逃避不了的,那我们接下来就来看看grid布局的兼容性如何呢。</p><blockquote><p>在将兼容性之前,介绍一个非常实用的网站,<a href="https://caniuse.com" target="_blank" rel="noopener">https://caniuse.com</a>,这个网站上面可以对我们用到的各种web相关的属性,包括html,css属性进行浏览器兼容性的查询。 </p></blockquote><ul><li>Flex布局兼容性</li></ul><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_4ck07e203b6hlb7ijcl35jkh992g3_2312x1110.png" alt=""></p><p>可以看到,我们现在用的最多的Flex布局的浏览器兼容性已经达到了一个非常高的比例——95%,说明在如今的前端开发环境下,如果对浏览器要求不是非常苛刻,基本可以非常愉快的使用Flex布局了。</p><ul><li>Grid布局兼容性</li></ul><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_66jb69f0idk0k7ig40jbblliaa6k9_2330x1106.png" alt=""></p><p>从图中可以看到,Grid布局和前面的Flex布局相比起来,虽然没有那么高的兼容比例,但是,经过了6年的沉淀与发展,也已经达到了86%,相对来说也已经比较完备了。所以,如果你们的代码基本都是在常见的最新的浏览器上进行允许,不用兼容万恶的前端克星IE,可以在平时的开发中尝试使用体验一下最新的Grid布局。</p><h2 id="Grid和Flex对比"><a href="#Grid和Flex对比" class="headerlink" title="Grid和Flex对比"></a>Grid和Flex对比</h2><p>Grid与Flex布局的共同点是元素均存放在一个父级容器内,尺寸与位置受容器影响。最核心的区别是Flex布局使用单坐标轴的布局系统,而Grid布局中使用二维布局,使元素可以在二个维度上进行排列,如下图所示:</p><ul><li>flex-layout</li></ul><p><img src="https://www.w3.org/TR/css3-grid-layout/images/flex-layout.png" alt="flex"></p><ul><li>grid-layout</li></ul><p><img src="https://www.w3.org/TR/css3-grid-layout/images/grid-layout.png" alt="grid"></p><p>上面两张图片来自于w3c官方css规范对Grid布局的介绍中的一组对比图,我们可以看到,flex布局很明显的是一维布局,元素在容器中都是横向或者纵向进行排列,并不能跨越维度进行排列。</p><p>而grid布局相比于flex布局,很明显是二维布局,grid布局不仅可以在横向上像flex已经排列,某些子元素还可以跨越维度,同时可以在横向和纵向上进行布局。</p><h3 id="一维-vs-二维"><a href="#一维-vs-二维" class="headerlink" title="一维 vs 二维"></a>一维 vs 二维</h3><p>有这样一张图:</p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_3ecg91kl5hfaaabbh2b51khjhk7fg_465x118.png" alt=""></p><p>上面这个布局,我们其实主要是在一个方向上即横线上布局,比如在<code>header</code>里放3个button,此时,我们其实使用flex布局是最佳方案,我们可以使用很少的代码来实现这些布局。</p><p>又比如有这样一张图:</p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_89hcc0hf69e50hb7j77gka2j0445i_499x274.png" alt=""></p><p>我们看到,其实这个布局已经不单单是一个维度了,他同时在横向和纵向上都有布局,这种情况下,其实我们使用Grid布局会更加灵活,并且会使你的标签更坚定,代码更容易维护。</p><p>你也可以结合两者一起使用,在上面的例子中最完美的做法是使用Grid来布局页面,使用Flex去对齐header里面的内容。</p><h3 id="内容优先-vs-布局优先"><a href="#内容优先-vs-布局优先" class="headerlink" title="内容优先 vs 布局优先"></a>内容优先 vs 布局优先</h3><p>再者,其实这两种布局方式的另一个核心区别是Flex是以<strong>内容</strong>为基础,而<strong>Grid</strong>是以布局为基础,听起来有些抽象,我们来用一个实际的例子来看一下。</p><p>我们有这样一段header的HTML代码:</p><pre><code class="html"><header> <div>Home</div> <div>Search</div> <div>Logout</div></header></code></pre><p>在没有使用任何布局时,他们是这样的:</p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_7jh25ig17l7d4a9f399fjil5chcl4_673x161.png" alt=""></p><p>当我们给外部<code>header</code>容器添加一个<code>display: flex</code>之后,他们会漂亮的在一条线上。</p><pre><code class="css">header { display: flex;}</code></pre><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_6fc6dc8j307ja00ja17i765232jfh_668x76.png" alt=""></p><p>为了让logout button在最右边,我们可以给他指定一个margin:</p><pre><code class="css">header > div:nth-child(3) { margin-left: auto;}</code></pre><p>效果如下:</p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_2gl52ecbh70060a8011gidl774cg3_670x77.png" alt=""></p><p>值得注意的是,让元素本身决定他放在哪里,我们除了<code>display: flex</code>之外没有添加任何东西。</p><p>这就是Flex和Grid的核心差别,当我们使用Grid来创建这个header时,这个差别会更加明显。</p><p>使用Grid来实现上面的header布局,有很多方法,我们这里用一种非常简单的去做,我们的Grid有十列,没一列都是一个单位宽度。</p><pre><code class="css">header { display: grid; grid-template-columns: repeat(10, 1fr);}</code></pre><p>添加上面的代码后,看起来其实和Flex的解决方案是一样的。</p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_6fc6dc8j307ja00ja17i765232jfh_668x76.png" alt=""></p><p>但是我们可以使用chrome的审查元素在上帝视角来看看两者有什么不同:</p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_58j3egaefjf9833691k1g4i83li54_748x138.png" alt=""></p><p>最关键的区别就是,这种方式必须先定义布局的列。从定义列的宽度开始,然后我们才能将元素放在可用的单元格中。这种方式强迫我们去分割我们的header有多少列。除非我们改变Grid,否则我们会被困死在这10列中,但是Flex中我们不会被这个麻烦困扰。</p><p>为了把logout放在最右边,我们会把他放在第十列:</p><pre><code class="css">header > div:nth-child(3) { grid-column: 10;}</code></pre><p>审查元素时,看起来是这样的:</p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_7lkl68d536gl00lja0fd44k4k3ij6_701x126.png" alt=""></p><p>我们不能简单的添加一个<code>margin-left: auto;</code>因为它引进被放在了第三个单元格中,想要移动它,我们得再找一个单元格把它放进去。</p><p>Grid和flex的区别,总结起来就是以下几点:</p><ul><li>CSS Grid适用于布局整体页面。它们使页面的布局变得非常容易,甚至可以处理一些不规则和非对称的设计。</li><li>Flexbox非常适合对齐元素内的内容。你可以使用Flexbox来定位设计上一些较小的细节问题。</li><li>CSS Grid适用于二维布局(行与列)。Flexbox适用于一维布局(行或列)。</li><li>同时学习它们,并配合使用。</li></ul><h2 id="重要术语"><a href="#重要术语" class="headerlink" title="重要术语"></a>重要术语</h2><p>前面对Grid有了一个大概的了解后,我们来介绍以下Grid中比较重要的几个术语。</p><ul><li>网格容器(grid-container)</li></ul><p>网格容器,类似于Flex的容器,我们可以通过添加<code>display: grid</code>将一个元素设置成一个网格容器。比如下面这段代码中的<code>container</code>就是一个网格容器。</p><pre><code class="html"><div class="conatiner"> <div class="item item1">1</div> <div class="item item2">2</div> <div class="item item3">3</div></div></code></pre><ul><li>网格项目(grid-item)</li></ul><p>网格项目,就是网格容器中的一个子元素。比如下面代码中的<code>item</code>就是一个网格项目,但要注意,<code>sub-item</code>不是一个网格项目。</p><pre><code class="html"><div class="conatiner"> <div class="item"></div> <div class="item"> <p class="sub-item"></p> </div> <div class="item"></div></div></code></pre><ul><li>网格线(grid-line)</li></ul><p>网格线就是将网格划分开的线条。</p><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs8bye7zrj20an06306x.jpg" alt=""></p><ul><li>网格单元格(grid-cell)</li></ul><p>网格单元格就是网格容器中划分出来最小的单元。</p><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs8cfc0uoj20an06306u.jpg" alt=""></p><ul><li>网格轨道(grid-track)</li></ul><p>网格轨道就是由若干个网格单元格组成的横向或者纵向区域,他的常见规格是1x8,或者8x1这种格式。</p><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs8csje9pj20an06306r.jpg" alt=""></p><ul><li>网格区域(grid-area)</li></ul><p>网格区域也是由若干个网格单元格组成的区域,但是不用与网格轨道,他的规格不局限与单个维度。</p><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs8dgkwdwj20an06306n.jpg" alt=""></p><h2 id="基本属性"><a href="#基本属性" class="headerlink" title="基本属性"></a>基本属性</h2><p>前面我们对grid布局的一些重要术语进行了介绍,接下来我们来一一介绍以下grid布局相关的基本属性。</p><h4 id="容器属性"><a href="#容器属性" class="headerlink" title="容器属性"></a>容器属性</h4><p>容器属性,顾名思义,就是添加可以在网格容器中添加是属性,是对网格整体进行控制的一系列属性。</p><ul><li>display</li><li>grid-template-columns</li><li>grid-template-rows</li></ul><p>这三个属性是用来定义网格布局最基本的三个属性,我们通过添加<code>display: grid</code>来设置一个网格容器,通过设置<code>grid-template-columns</code>和<code>grid-template-rows</code>来给网格容器定义具体的行和列。</p><pre><code class="css">.container { display: grid; grid-template-columns: 40px 50px auto 50px 40px; grid-template-rows: 25% 100px auto;}</code></pre><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs8dyw8pxj20cw0a5a9u.jpg" alt=""></p><ul><li>fr单位</li></ul><p>fr单位是grid布局中的一个新单位,它代表的是网格容器中<strong>可用空间</strong>的一份。下面我举三个小例子来介绍以下这个单位,注意,我们这里只关注列的宽度。</p><p><code>1fr 1fr 1fr</code>表示三个轨道三等分。</p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_396cg5l61dj1c7cf9gf3he9blidj8_619x418.png" alt="">)</p><p><code>2fr 1fr 1fr</code>表示三个轨道,空间四等分,两份给第一个轨道,剩下三个轨道各占一份。</p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_6akc87d6hg2bhk3kldibc0g1b7d31_621x412.png" alt=""></p><p><code>400px 2fr 1fr</code>表示三个轨道,第一个轨道400px,抽走400px后剩下空间三等分,两份给第二个轨道,一份给第三个轨道。</p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_209b72gal4136kl69ag5ce105ck81_589x403.png" alt=""></p><ul><li>repeat()和minmax()</li></ul><p>repeat和minmax是grid布局中的两个常用函数,可用减少我们代码的重复编写。</p><p>repeat(time, content),表示的是标记重复部分或整个轨道列表,第一个参数time表示重复的次数,第二个参数content表示重新的内容。具体见下面的三个小例子。</p><pre><code>repeat(3, 1fr) = 1fr 1fr 1fr20px repeat(3, 1fr) 20px = 20px 1fr 1fr 1fr 20pxrepeat(3, 1fr 2fr) = 1fr 2fr 1fr 2fr 1fr 2fr</code></pre><p>minmax(min, max),可用给网格定义一个尺寸的范围,第一个参数min表示网格尺寸的最小值,第二个参数表示网格尺寸的最大值。具体见下面的两个小例子。</p><pre><code>minmax(100px, 200px):表示网格最小是100px,最大是200pxminmax(100px, auto):表示网格最小是100px,最大为auto,auto意思是行高将根据内容的大小自动变换</code></pre><ul><li>grid-template-areas</li></ul><p>grid-template-areas表示的网格容器中的一个区域。通过获取网格项中的grid-area属性值(名称),来定义网格模版。重复网格区(grid-area)名称将跨越网格单元格,’.’代表空网格单元。</p><p>下面这个例子我们通过给a,b,c,d四个div添加grid-area属性定义了名字,如果通过grid-template-areas这个属性来快速的定义网格的布局。</p><pre><code class="css">.item-a { grid-area: header;}.item-b { grid-area: main;}.item-c { grid-area: sidebar;}.item-d { grid-area: footer;}.container { display: grid; grid-template-columns: 50px 50px 50px 50px; grid-template-rows: auto; grid-template-areas: "header header header header" "main main . sidebar" "footer footer footer footer"}</code></pre><p><img src="https://user-gold-cdn.xitu.io/2016/12/12/8b3d9c5cbdbba4375f2e4eee09107d18?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" alt=""></p><ul><li>grid-column-gap</li><li>grid-row-gap</li><li>grid-gap</li></ul><p>这三个属性,主要是用来定义网格项之间的间隙,类似于margin。grid-column-gap和grid-row-gap分别定义网格之间的列间距和行间距,而grid-gap则是简写,第一个值为行间距,第二个值为列间距。</p><pre><code class="css">.container { grid-template-columns: 100px 50px 100px; grid-template-rows: 80px auto 80px; grid-column-gap: 10px; grid-row-gap: 15px;}</code></pre><p>或者</p><pre><code class="css">.container { ... grid-gap: 15px 10px;}</code></pre><p><img src="https://user-gold-cdn.xitu.io/2016/12/12/57614742c974852d68a45aeb3b549335?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" alt=""></p><ul><li>justify-items</li><li>align-items</li><li>justify-content</li><li>align-content</li></ul><p>这四个属性主要是用来控制网格项的对齐方式,具体用法和效果与Flex类似,这里就不详细展开,看图说话吧。</p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_15h2gddfbed4i8gb01lj753j2ea5k_993x742.png" alt=""></p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_6kjbdic8f2j5853111jl9g7dllh8e_978x778.png" alt=""></p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_0ahbjl914lah4aaghcb5fk9i8de8d_1270x1004.png" alt=""></p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_3fkc4990h47elf541cg3k05lc4ikg_1256x909.png" alt=""></p><ul><li>grid-auto-columns</li><li>grid-auto-rows</li></ul><p>这两个属性是自动生成隐式网格轨道(列和行),当你定位网格项超出网格容器范围时,将自动创建隐式网格轨道。</p><p>我们看下面这个例子。</p><pre><code class="css">.container { display: grid; grid-template-columns: 60px 60px; grid-template-rows: 90px 90px;}</code></pre><p><img src="https://user-gold-cdn.xitu.io/2016/12/12/c18240896c8ea2108874dad1c3db5c44?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" alt=""></p><p>这是2x2的网格,但是我们来用grid-column 和 grid-row给网格项定位如下:</p><pre><code>.item-a { grid-column: 1 / 2; grid-row: 2 / 3;}.item-b { grid-column: 5 / 6; grid-row: 2 / 3;}</code></pre><p><img src="https://user-gold-cdn.xitu.io/2016/12/12/50645e52f1d44650e93ee2b410de7e65?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" alt=""></p><p>我们可以看出,网格项item-b定位在第五根列网格线(column line 5 )和第六根列网格线(column line 6 )之间。但是我们网格容器根本不存在这两条网格线,所以就用两个0宽度来填充。在这里我们可以用网格自动行(grid-auto-rows)和网格自动列(grid-auto-columns)来定义这些隐式轨道宽度。</p><p><img src="https://user-gold-cdn.xitu.io/2016/12/12/9bae2992a3f353fc0f1de9d44e20da3e?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" alt=""></p><ul><li>grid-auto-flow</li></ul><p>在没有设置网格项的位置时,这个属性控制网格项怎样排列。</p><p>他的属性值有:</p><pre><code>row: 按照行依次从左到右排列。column: 按照列依次从上倒下排列。dense: 按先后顺序排列。</code></pre><p>我们看下面的这个例子:</p><pre><code class="html"><div class="container"> <div class="item-a">item-a</div> <div class="item-b">item-b</div> <div class="item-c">item-c</div> <div class="item-d">item-d</div> <div class="item-e">item-e</div></div></code></pre><p>我们定义一个5行2列的网格,同时定义grid-auto-flow:flow。</p><pre><code class="css">.container { display: grid; grid-template-columns: 60px 60px 60px 60px 60px; grid-template-rows: 30px 30px; grid-auto-flow: row;}</code></pre><p>然后对item-a和item-e进行布局。</p><pre><code class="css">.item-a{ grid-column: 1; grid-row: 1 / 3;}.item-e{ grid-column: 5; grid-row: 1 / 3;}</code></pre><p>由于我们设置了grid-auto-flow:row,item-b、item-c和item-d在行上是从左到右排列,如下:</p><p><img src="https://user-gold-cdn.xitu.io/2016/12/12/1514a1df1667618e3259fefcef9a8b9b?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" alt=""></p><p>如果我们设置 grid-auto-flow: column;结果如下:</p><p><img src="https://user-gold-cdn.xitu.io/2016/12/12/4b1c7ece0f66b1d6be3e6a82fad0a1c0?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" alt=""></p><h4 id="网格项目属性"><a href="#网格项目属性" class="headerlink" title="网格项目属性"></a>网格项目属性</h4><p>网格项目属性,是添加在具体的网格单元上来控制网格单元的属性。</p><ul><li>grid-column-start</li><li>grid-column-end</li><li>grid-row-start</li><li>grid-row-end</li><li>grid-column</li><li>grid-row</li></ul><p>这6个属性是通过网格线来定义网格项的位置。grid-column-start、grid-row-start定义网格项的开始位置,grid-column-end、grid-row-end定义网格项的结束位置。</p><p>这四个属性的值可以是:</p><pre><code>line: 指定带编号或者名字的网格线。span: 跨越轨道的数量。span: 跨越轨道直到对应名字的网格线。auto: 自动展示位置,默认跨度为1。</code></pre><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_66h2dcgef69gg214bgg6k3h99hlf9_1312x715.png" alt=""></p><p>grid-column,grid-row是grid-column-start、grid-column-end 和 grid-row-start、grid-row-end 的简写。</p><p><img src="https://user-gold-cdn.xitu.io/2016/12/12/d2bb8e2996cc62dd620642020463a2ca?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" alt=""></p><ul><li>gid-area</li></ul><p>定义网格项名字,以便创建模块(容器属性grid-template-areas来定义模块)。可以是数字或网格线名字。看如下两个例子。</p><p>定义网格项名字:</p><pre><code class="css">.item-d { grid-area: header;}</code></pre><p>通过网格线定义网线项:</p><pre><code class="css">.item-d { grid-area: 1 / col-start / last-line / 6;}</code></pre><p><img src="https://user-gold-cdn.xitu.io/2016/12/12/e6c5321f34896104ac004ee45ac50e58?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" alt=""></p><ul><li>justify-self</li><li>align-self</li></ul><p>这两属性用来定义单个网格项垂直于列网格线的对齐方式。</p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_639hfc468ffighej44il14j5i4j11_1010x706.png" alt=""></p><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180810_7ekdll98jiada99247401bf6ehf38_1031x709.png" alt=""></p><h3 id="实际布局应用"><a href="#实际布局应用" class="headerlink" title="实际布局应用"></a>实际布局应用</h3><p>说了这么多,下面我们就拿几个常见的布局来应用一下刚刚学到的grid布局。</p><ul><li>左右固定,中间自适应</li></ul><pre><code class="html"><div class="container"> <div class="left">left</div> <div class="middle">middle</div> <div class="right">right</div></div></code></pre><pre><code class="css">.container { display: grid; grid-template-columns: 100px 1fr 100px; height: 200px;}.container div { text-align: center;}.left { background: greenyellow;}.middle { background: lightblue;}.right { background: greenyellow;}</code></pre><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180811_1af7a6170cgac69gae8875988da5g_1786x510.png" alt=""></p><ul><li>九宫格</li></ul><pre><code class="html"><div class="container"> <div class="item">1</div> <div class="item">2</div> <div class="item">3</div> <div class="item">4</div> <div class="item">5</div> <div class="item">6</div> <div class="item">7</div> <div class="item">8</div> <div class="item">9</div></div></code></pre><pre><code class="css">.container { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr); height: 400px; width: 400px; grid-gap: 8px;}.item { background: lightskyblue;}</code></pre><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180811_1ek17147c2075fj4g2d9d6gf980h8_938x944.png" alt=""></p><ul><li>圣杯布局和双飞翼布局</li></ul><pre><code class="html"><div class="container"> <div class="header">header</div> <div class="left">left</div> <div class="body">body</div> <div class="right">right</div> <div class="footer">footer</div></div></code></pre><pre><code class="css">.container { display: grid; grid-template-columns: 100px 1fr 100px; grid-template-rows: 50px 300px 50px;}.header { grid-area: 1 / 1 / 2 / 4; background: lightsalmon;}.left { background: lightseagreen;}.body { background: lightslategray;}.right { background: lightyellow;}.footer { grid-area: 3 / 1 / 4 / 4; background: yellowgreen;}</code></pre><p><img src="https://s10.mogucdn.com/mlcdn/c45406/180811_80ic9digjjg4hh0e2kd738fgllj6l_1718x620.png" alt=""></p><h2 id="结束语"><a href="#结束语" class="headerlink" title="结束语"></a>结束语</h2><p>但是也不要放弃flex-layout,它是目前为止最厉害的页面布局属性,是时代召唤的结果,只是它并不适合布局整个页面框架。flex在响应式布局中是很关键的,它是内容驱动型的布局。不需要预先知道会有什么内容,可以设定元素如何分配剩余的空间以及在空间不足的时候如何表现。显得较为强大的是一维布局的能力,而grid优势在于二维布局。这也是他们设计的初衷。</p><p>大概可以设想,网格布局被广泛支持之后会出现很多网格布局内嵌flex的布局情形。</p><h3 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h3><ul><li><a href="https://www.w3.org/TR/css-grid-1/" target="_blank" rel="noopener">https://www.w3.org/TR/css-grid-1/</a></li><li><a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Grid_Layout" target="_blank" rel="noopener">https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Grid_Layout</a></li><li><a href="https://caniuse.com/#feat=css-grid" target="_blank" rel="noopener">https://caniuse.com/#feat=css-grid</a></li><li><a href="http://griddy.io/" target="_blank" rel="noopener">http://griddy.io/</a></li><li><a href="https://alialaa.github.io/css-grid-cheat-sheet/" target="_blank" rel="noopener">https://alialaa.github.io/css-grid-cheat-sheet/</a></li><li><a href="http://www.w3cplus.com/css3/playing-with-css-grid-layout.html" target="_blank" rel="noopener">http://www.w3cplus.com/css3/playing-with-css-grid-layout.html</a></li></ul><blockquote><p>本文部分内容参考自其他相关文章,若有冒犯,请联系我删除。 </p></blockquote><p>#蘑菇街</p>]]></content>
<summary type="html">
<h1 id="初探Grid-Layout布局"><a href="#初探Grid-Layout布局" class="headerlink" title="初探Grid-Layout布局"></a>初探Grid-Layout布局</h1><h2 id="Grid布局简介"><a
</summary>
<category term="Tutorials" scheme="https://chenyubo.me/categories/Tutorials/"/>
<category term="CSS" scheme="https://chenyubo.me/tags/CSS/"/>
<category term="Grid" scheme="https://chenyubo.me/tags/Grid/"/>
<category term="Layout" scheme="https://chenyubo.me/tags/Layout/"/>
</entry>
<entry>
<title>阿里云部署项目笔记——Node篇</title>
<link href="https://chenyubo.me/aliyun-deploy-node/"/>
<id>https://chenyubo.me/aliyun-deploy-node/</id>
<published>2017-05-10T04:46:25.000Z</published>
<updated>2019-02-02T10:00:34.989Z</updated>
<content type="html"><![CDATA[<p>最近找了个网易云的API项目,由于是<code>Node</code>项目,便计划着部署到服务器上,方便访问,顺便学一学<code>Node</code>项目的部署。</p><h2 id="在服务器上安装Node"><a href="#在服务器上安装Node" class="headerlink" title="在服务器上安装Node"></a>在服务器上安装Node</h2><p>先在终端使用<code>ssh username@ip</code>命令远程连接服务器。</p><h3 id="下载源码"><a href="#下载源码" class="headerlink" title="下载源码"></a>下载源码</h3><p>你需要在<a href="https://nodejs.org/en/download/" target="_blank" rel="noopener">https://nodejs.org/en/download/</a>下载最新的<code>Nodejs</code>版本,本文以现在的最新的<code>v6.10.3</code>为例:</p><pre><code class="bash">cd /usr/local/src/wget http://nodejs.org/dist/v6.10.3/node-v6.10.3.tar.gz</code></pre><p>若直接下载后续解压出现问题,可以直接在<code>Nodejs</code>官网下载编译好的<code>Linux</code>二进制包,然后上传到服务器<code>/usr/local/src/</code>目录下。</p><h3 id="解压源码"><a href="#解压源码" class="headerlink" title="解压源码"></a>解压源码</h3><pre><code>cd /usr/local/src/tar zxvf node-v6.10.3.tar.gz</code></pre><h3 id="编译安装"><a href="#编译安装" class="headerlink" title="编译安装"></a>编译安装</h3><pre><code>cd node-v6.10.3./configure --prefix=/usr/local/node/6.10.3makemake install</code></pre><p>这里<code>make</code>过程可能比较久,需要耐心等待。</p><h3 id="配置NODE-HOME,进入profile编辑环境变量"><a href="#配置NODE-HOME,进入profile编辑环境变量" class="headerlink" title="配置NODE_HOME,进入profile编辑环境变量"></a>配置<code>NODE_HOME</code>,进入<code>profile</code>编辑环境变量</h3><pre><code>vim /etc/profile</code></pre><p>设置 <code>Node.js</code> 环境变量,在 <code>export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL</code> 一行的上面添加如下内容:</p><pre><code>#set for nodejsexport NODE_HOME=/usr/local/node/6.10.3export PATH=$NODE_HOME/bin:$PATH </code></pre><p><code>:wq</code>保存并退出,编译 <code>/etc/profile</code> 使配置生效</p><pre><code class="bash">source /etc/profile </code></pre><h3 id="验证是否安装配置成功"><a href="#验证是否安装配置成功" class="headerlink" title="验证是否安装配置成功"></a>验证是否安装配置成功</h3><pre><code class="bash">node -v</code></pre><p>输出 <code>v6.10.3</code> 表示配置成功<br>npm模块安装路径</p><pre><code>/usr/local/node/6.10.3/lib/node_modules/ </code></pre><h2 id="传输项目"><a href="#传输项目" class="headerlink" title="传输项目"></a>传输项目</h2><p>将需要部署的项目通过可视化工具或者命令行传输到服务器上,具体方法见上一篇博客<a href="http://www.chenyubo.me/2017/05/10/deploy-node-project/" target="_blank" rel="noopener">阿里云部署项目笔记之Vue篇</a></p><h2 id="安装pm2"><a href="#安装pm2" class="headerlink" title="安装pm2"></a>安装pm2</h2><p>执行命令安装<code>pm2</code>来守护进程:</p><pre><code>npm install pm2 -g</code></pre><h2 id="开启项目"><a href="#开启项目" class="headerlink" title="开启项目"></a>开启项目</h2><p>进入项目文件夹内,执行命令:</p><pre><code>pm2 start app.js</code></pre><p>至此结束。</p>]]></content>
<summary type="html">
<p>最近找了个网易云的API项目,由于是<code>Node</code>项目,便计划着部署到服务器上,方便访问,顺便学一学<code>Node</code>项目的部署。</p>
<h2 id="在服务器上安装Node"><a href="#在服务器上安装Node" class
</summary>
<category term="Notes" scheme="https://chenyubo.me/categories/Notes/"/>
<category term="Server" scheme="https://chenyubo.me/tags/Server/"/>
<category term="Node" scheme="https://chenyubo.me/tags/Node/"/>
</entry>
<entry>
<title>阿里云部署项目笔记——Vue篇</title>
<link href="https://chenyubo.me/aliyun-deploy-vue/"/>
<id>https://chenyubo.me/aliyun-deploy-vue/</id>
<published>2017-04-02T04:46:25.000Z</published>
<updated>2019-02-02T09:52:02.292Z</updated>
<content type="html"><![CDATA[<p>上个月13号弄到了阿里云9.9的学生主机,而且前段时间刚好又完成了练手项目Vue版知乎日报,但是生成的dist文件在Github Pages直接预览会有跨域问题,于是想着能不能使用手上的服务器解决一下这个问题。但是因为种种原因,一直拖着没有去实践,于是趁着清明小长假,花了一点时间折腾了一番,将项目部署至了服务器上,实现了在线预览功能,也了解了在服务器项目部署的大致流程。</p><h2 id="前期准备"><a href="#前期准备" class="headerlink" title="前期准备"></a>前期准备</h2><p>首先你需要有一台阿里云服务器(9.9学生ECS美滋滋,可惜过几个月就没有了,扎心了!)</p><p>付费时选择了Windows系统,可以通过阿里云的控制台在线控制,略卡,然后尝试使用Mac下的远程控制软件操作,不知为何失败,故选择重装<code>CentOS</code>(<code>Linux</code>大法好!锻炼动手能力的时候到了),具体步骤自行搜索。</p><p>然后在终端使用<code>ssh username@ip</code>命令远程连接服务器,然后输入密码,<strong>注意,这里输入密码时终端是看不到的,输完直接回车即可。</strong></p><ul><li>安装<code>Nginx</code>:<code>yum -y install nginx</code></li><li>开启<code>Nginx</code>:<code>nginx -s start</code></li><li>修改<code>Nginx</code>配置文件:<code>vi /etc/nginx/nginx.conf</code></li><li>修改配置文件后重启<code>Nginx</code>:<code>nginx -s reload</code></li><li>直接重启<code>Nginx</code>:<code>nginx -s restart</code></li></ul><p>至此,在浏览器中输入服务器的公网ip即可访问<code>Nginx</code>默认的页面,服务器已准备好。</p><h2 id="生成部署项目文件"><a href="#生成部署项目文件" class="headerlink" title="生成部署项目文件"></a>生成部署项目文件</h2><p>在开发环境下,修改<code>config/index.js</code>里的<code>proxyTable</code>,解决跨域问题:</p><pre><code class="javascript">proxyTable: { '/api': { target: 'http://news-at.zhihu.com', changeOrigin: true, pathRewrite: { '^/api': '/api/4' } }}</code></pre><p>组件请求方式:</p><pre><code class="javascript">axios.get('api/news/latest') .then(response => { // todo }) .catch(error => { console.log(error); });</code></pre><p>这里设置后请求<code>api/xxx</code>将会代理成<code>http://news-at.zhihu.com/api/4/xxx</code>。</p><p><strong>注:这里设置这种形式是为了与后面部署的Nginx配置文件相匹配。</strong></p><p>然后,执行<code>npm run build</code>生成静态文件夹<code>dist</code>。</p><h2 id="部署项目至服务器"><a href="#部署项目至服务器" class="headerlink" title="部署项目至服务器"></a>部署项目至服务器</h2><p>将前面生成的<code>dist</code>文件夹传输到服务器。我这里使用了<code>scp</code>命令。</p><ul><li>具体为:<code>scp -r local_dir username@servername:remote_dir</code>,把当前目录的<code>local_dir</code>目录上传到服务器的<code>remote_dir</code>目录。</li><li>例如:<code>scp -r test [email protected]:/var/www/</code>,把当前目录下的<code>test</code>目录上传到服务器的<code>/var/www/</code> 目录。具体使用方法可以自行搜索。</li><li>也可以使用可视化工具,比如<code>FileZilla</code>之类…</li></ul><p>然后登录服务器,找到并打开<code>Nginx</code>的配置文件:<code>vi /etc/nginx/nginx.conf</code></p><p>添加新server:</p><pre><code>server { listen 8888; server_name localhost; location / { root /usr/local/var/www/zhihu-daily/; index index.html; } location ^~ /api/ { proxy_pass http://news-at.zhihu.com/api/4/; proxy_set_header Host news-at.zhihu.com; } }</code></pre><ul><li><code>root</code>:填写刚刚传输至服务器的静态文件夹路径,这里我将<code>dist</code>修改为对应项目名</li><li><code>index</code>:首页文件名</li><li>location:转发代理配置<ul><li><code>proxy_pass</code>:转发地址</li><li><code>proxy_set_header Host</code>:转发主机名</li></ul></li></ul><p>这样配置完<code>Nginx</code>后即可通过请求<code>http://your_ip/api/xxx</code>的方式请求数据,同时与前面开发环境下的请求模式匹配,部署时只是改变ip与端口号,后面的匹配规则则不需要改变,故无需生产环境无需修改请求代码。</p><p>修改后保存,然后执行命令<code>nginx -s reload</code>重启<code>Nginx</code>即可。</p><p>然后直接在浏览器中输入服务器的ip+端口号即可预览部署好的项目。至此,部署完成!!!</p>]]></content>
<summary type="html">
<p>上个月13号弄到了阿里云9.9的学生主机,而且前段时间刚好又完成了练手项目Vue版知乎日报,但是生成的dist文件在Github Pages直接预览会有跨域问题,于是想着能不能使用手上的服务器解决一下这个问题。但是因为种种原因,一直拖着没有去实践,于是趁着清明小长假,花了一
</summary>
<category term="Notes" scheme="https://chenyubo.me/categories/Notes/"/>
<category term="Server" scheme="https://chenyubo.me/tags/Server/"/>
<category term="Vue" scheme="https://chenyubo.me/tags/Vue/"/>
</entry>
<entry>
<title>当Vue遇上知乎日报</title>
<link href="https://chenyubo.me/vue-zhihu-daily-intro/"/>
<id>https://chenyubo.me/vue-zhihu-daily-intro/</id>
<published>2017-03-30T04:46:25.000Z</published>
<updated>2019-02-03T05:38:22.900Z</updated>
<content type="html"><![CDATA[<h1 id="vue-zhihu-daily"><a href="#vue-zhihu-daily" class="headerlink" title="vue-zhihu-daily"></a>vue-zhihu-daily</h1><p><a href="https://travis-ci.org/cccyb/vue-zhihu-daily" target="_blank" rel="noopener"><img src="https://travis-ci.org/cccyb/vue-zhihu-daily.svg?branch=master" alt="Build Status"></a> <a href="http://opensource.org/licenses/MIT" target="_blank" rel="noopener"><img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license"></a></p><blockquote><p>这是一个基于Vue全家桶开发的知乎日报WebApp,页面样式主要参考iOS版知乎日报APP。</p></blockquote><blockquote><p>个人博客:<a href="http://www.chenyubo.me" target="_blank" rel="noopener">陈钰博的博客</a></p></blockquote><blockquote><p>项目github地址:<a href="https://github.com/cccyb/vue-zhihu-daily" target="_blank" rel="noopener">vue-zhihu-daily</a></p></blockquote><blockquote><p>如果觉得对您有帮助,您可以点右上角给个 star 支持一下,十分感谢!如果有问题,也欢迎提交 issue 一起探讨!</p></blockquote><h2 id="声明"><a href="#声明" class="headerlink" title="声明"></a>声明</h2><blockquote><p>『知乎』是 知乎. Inc 的注册商标。本软件与其代码非由知乎创作或维护。软件中所包含的信息与内容皆违反版权与知乎用户协议。本项目所有文字图片等稿件内容均由<a href="https://www.zhihu.com" target="_blank" rel="noopener">知乎</a>提供,获取与共享之行为或有侵犯知乎权益的嫌疑。若被告知需停止共享与使用,本人会及时删除整个项目。请您了解相关情况,并遵守知乎协议。</p></blockquote><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>前段时间抽空学习了Vue,并跟着慕课网的黄轶老师<a href="https://github.com/ustbhuangyi" target="_blank" rel="noopener">@ustbhuangyi</a>完成了第一个Vue小demo<a href="https://github.com/cccyb/vue-eleme-app" target="_blank" rel="noopener">Vue高仿饿了么APP</a>。通过这个小demo,对Vue的开发有了一个初步的认识,然而这个demo是跟着老师的视频敲的代码,所以为了更好的学习Vue,就萌生了完整的写一个复杂webApp的想法,有了想法,就开始干呗。</p><p>为什么是知乎日报呢?</p><ul><li>首先呢,知乎日报是一个完整的已经上线的APP,并且它的功能比较完善,但是页面还不是很复杂,比较适合新手练手。</li><li>其次,由于开发的是前端项目,数据获取是一个比较恼火的问题,然而github上已经有大神给出了<a href="https://github.com/izzyleung/ZhihuDailyPurify/wiki/%E7%9F%A5%E4%B9%8E%E6%97%A5%E6%8A%A5-API-%E5%88%86%E6%9E%90" target="_blank" rel="noopener">知乎日报 API 分析</a>,这极大的方便的解决了数据的获取问题,我们只需关注前端,而不需关注后台数据。</li></ul><h2 id="技术栈"><a href="#技术栈" class="headerlink" title="技术栈"></a>技术栈</h2><p>vue2 + vue-router + axios + vuex + vue-cli<br>mint-ui + sass + flex + eslint</p><h2 id="在线Demo"><a href="#在线Demo" class="headerlink" title="在线Demo"></a>在线Demo</h2><p><del>在线预览</del></p><p><strong>阿里云学生服务器到期,在线预览已失效。。。若想实时预览建议clone项目到本地后预览</strong></p><p><strong>(PC端建议开启Chrome手机调试模式食用更佳,移动端直接在浏览器开启即可)</strong></p><h2 id="功能"><a href="#功能" class="headerlink" title="功能"></a>功能</h2><ul><li style="list-style: none"><input type="checkbox" checked> 首页</li><li style="list-style: none"><input type="checkbox" checked> 启动欢迎页</li><li style="list-style: none"><input type="checkbox" checked> 首页滚动到底部加载更多</li><li style="list-style: none"><input type="checkbox" checked> 查看新闻详情</li><li style="list-style: none"><input type="checkbox" checked> 新闻详情页载入下一篇</li><li style="list-style: none"><input type="checkbox" checked> 收藏新闻</li><li style="list-style: none"><input type="checkbox" checked> 查看评论</li><li style="list-style: none"><input type="checkbox" checked> 短评展开和收缩</li><li style="list-style: none"><input type="checkbox" checked> 编写评论页(不能发送到后台)</li><li style="list-style: none"><input type="checkbox" checked> 侧边栏</li><li style="list-style: none"><input type="checkbox" checked> 查看指定主题新闻</li><li style="list-style: none"><input type="checkbox" checked> 查看指定主题下的编辑列表</li><li style="list-style: none"><input type="checkbox" checked> 查看某个编辑的个人信息</li><li style="list-style: none"><input type="checkbox" checked> 查看收藏新闻</li></ul><h2 id="项目截图"><a href="#项目截图" class="headerlink" title="项目截图"></a>项目截图</h2><h3 id="首页"><a href="#首页" class="headerlink" title="首页"></a>首页</h3><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs8ilyq4tj20960g8n3m.jpg" alt=""></p><h3 id="新闻详情页"><a href="#新闻详情页" class="headerlink" title="新闻详情页"></a>新闻详情页</h3><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs8jbq5eaj20960gbjx3.jpg" alt=""></p><h3 id="评论查看页"><a href="#评论查看页" class="headerlink" title="评论查看页"></a>评论查看页</h3><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs8jjcisgj20960gawil.jpg" alt=""></p><h3 id="编写评论页"><a href="#编写评论页" class="headerlink" title="编写评论页"></a>编写评论页</h3><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs8lmfwouj20960gdglu.jpg" alt=""></p><h3 id="主题页"><a href="#主题页" class="headerlink" title="主题页"></a>主题页</h3><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs8k9rxfcj20960gc0w6.jpg" alt=""></p><h3 id="编辑列表页"><a href="#编辑列表页" class="headerlink" title="编辑列表页"></a>编辑列表页</h3><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs8kgikxlj20960g7t9r.jpg" alt=""></p><h3 id="编辑个人详情页"><a href="#编辑个人详情页" class="headerlink" title="编辑个人详情页"></a>编辑个人详情页</h3><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs8kmp1u3j20960g8abh.jpg" alt=""></p><h3 id="收藏页"><a href="#收藏页" class="headerlink" title="收藏页"></a>收藏页</h3><p><img src="https://ws1.sinaimg.cn/large/c542ee77ly1fzs8kssn9lj20960gadhb.jpg" alt=""></p><h2 id="项目运行"><a href="#项目运行" class="headerlink" title="项目运行"></a>项目运行</h2><pre><code class="bash"># 克隆项目到本地git clone https://github.com/cccyb/vue-zhihu-daily.git# 切换到项目所在文件夹cd vue-zhihu-daily# 安装依赖npm install# 本地开发,开启服务器,浏览器访问 http://localhost:8088即可npm run dev# 构建生产npm run build</code></pre><h2 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h2><pre><code>.|-- build // webpack配置文件|-- config // 项目打包路径|-- dist // 项目部署文件,放在服务器即可正常访问|-- src // 源码目录| |-- assets // 资源目录| | |-- images // 图片目录| | |-- sass // sass目录| | |-- components // 组件sass目录| | |-- pages // 页面sass目录| |-- components // 组件| | |-- LongComment.vue // 长评组件| | |-- NewsList.vue // 新闻列表组件| | |-- NewsMenu.vue // 新闻详情底部菜单组件| | |-- Share.vue // 新闻详情分享弹框组件| | |-- ShortComment.vue // 短评组件| | |-- Sidebar.vue // 侧边栏组件| | |-- Swipe.vue // 轮播图组件| |-- pages // 页面| | |-- Collect.vue // 收藏页面| | |-- Comment.vue // 评论页面| | |-- Editor.vue // 查看编辑个人信息页面| | |-- EditorList.vue // 编辑列表页面| | |-- Index.vue // 首页| | |-- NewsDetail.vue // 新闻详情页面| | |-- ThemeDetail.vue // 主题页面| | |-- WriteCommnet.vue // 编写评论页面| |-- router| | |-- index.js // 路由配置| |-- store| | |-- index.js // vuex配置| | |-- actions.js // actions| | |-- getters.js // getters| | |-- mutation-types.js // mutation常量| | |-- mutations.js // mutation| | |-- state.js // state| |-- App.vue // 页面入口文件| |-- main.js // 程序入口文件,加载各种公共组件|-- static // 静态文件目录| |-- css| | |-- animate.css // 动画css| | |-- iconfont.css // 图标字体css| | |-- icontont.ttf // 图标字体ttf| | |-- iconfont.woff // 图标字体woff| | |-- news_qa_auto.css // 页面详情内容css| | |-- reset.css // 统一浏览器样式css|-- .babelrc // ES6语法编译配置|-- .editorconfig // 代码编写规格配置|-- .eslintignore // 忽略eslint检查文件配置|-- .eslint.js // eslint配置文件|-- .gitattributes // 修改项目在github显示类型配置文件|-- .gitignore // git忽略上传文件|-- .postcssrc.js|-- index.html // 入口html文件|-- package.json // 项目及工具的依赖配置文件|-- README.md // readme说明|-- yarn.lock // yarn文件.</code></pre><h2 id="Todo"><a href="#Todo" class="headerlink" title="Todo"></a>Todo</h2><ul><li style="list-style: none"><input type="checkbox" checked> <del>启动欢迎页</del></li><li style="list-style: none"><input type="checkbox"> 首页新闻时间分隔栏</li><li style="list-style: none"><input type="checkbox"> 首页头部上滑颜色渐变效果</li><li style="list-style: none"><input type="checkbox" checked> <del>首页下拉刷新</del></li><li style="list-style: none"><input type="checkbox"> 消息页面</li><li style="list-style: none"><input type="checkbox"> 设置页面</li><li style="list-style: none"><input type="checkbox"> 个人信息页面</li><li style="list-style: none"><input type="checkbox"> 离线</li><li style="list-style: none"><input type="checkbox"> 夜间模式</li><li style="list-style: none"><input type="checkbox"> 整体代码重构,性能优化</li><li style="list-style: none"><input type="checkbox"> 移动端1px边框优化</li><li style="list-style: none"><input type="checkbox" checked> <del>侧边栏主题列表滚动效果</del></li><li style="list-style: none"><input type="checkbox" checked> <del>图片懒加载</del></li><li style="list-style: none"><input type="checkbox"> 页面切换动画</li><li style="list-style: none"><input type="checkbox"> 手势侧滑功能</li><li style="list-style: none"><input type="checkbox" checked> <del>vuex状态管理文件重构优化</del></li><li style="list-style: none"><input type="checkbox"> 浏览器兼容性</li><li style="list-style: none"><input type="checkbox" checked> <del>生产环境部署</del></li><li style="list-style: none"><input type="checkbox"> 流程跳转优化</li><li style="list-style: none"><input type="checkbox"> localStorage</li><li>…</li></ul><h2 id="ChangeLog"><a href="#ChangeLog" class="headerlink" title="ChangeLog"></a>ChangeLog</h2><p>见 <a href="./CHANGELOG.md">ChangeLog</a></p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><h3 id="1-知乎接口跨域问题(开发环境)"><a href="#1-知乎接口跨域问题(开发环境)" class="headerlink" title="1.知乎接口跨域问题(开发环境)"></a>1.知乎接口跨域问题(开发环境)</h3><p>调用知乎API时遇到了跨域问题,但是知乎的接口好像不支持jsonp,谷歌一波发现可以使用vue-cli自带的config的proxyTable文件配置进行解决,配置非常简单:</p><pre><code class="js">proxyTable: { '/api': { target: 'http://news-at.zhihu.com', changeOrigin: true, pathRewrite: { '^/api': '/api/4' } }}</code></pre><p>此时请求<code>api/xxx</code>将会代理成<code>http://news-at.zhihu.com/api/4/xxx</code><br>这样就不会有跨域问题了,当然这只适用于开发环境。</p><h3 id="2-项目部署以及解决跨域问题(生产环境)"><a href="#2-项目部署以及解决跨域问题(生产环境)" class="headerlink" title="2.项目部署以及解决跨域问题(生产环境)"></a>2.项目部署以及解决跨域问题(生产环境)</h3><p>想要在生产环境里解决跨域问题,可以选择使用后台服务器中转API来完成跨域,具体可以选择Node或者Nginx来解决。</p><p>本项目已部署至阿里云服务器,使用Nginx进行代理,详情见<a href="http://www.chenyubo.me/2017/04/02/deploy-vue-project/" target="_blank" rel="noopener">阿里云服务器部署Vue项目总结</a></p><h3 id="3-图片防盗链问题"><a href="#3-图片防盗链问题" class="headerlink" title="3.图片防盗链问题"></a>3.图片防盗链问题</h3><p>知乎API返回的数据中的图片都是存储在知乎服务器上的url地址,直接请求会返回403,所以需要进行一些处理,这里我采用了<a href="https://github.com/yatessss" target="_blank" rel="noopener">yatessss</a>同学在<a href="http://www.yatessss.com/2016/07/08/%E4%BD%BF%E7%94%A8vue%E5%AE%8C%E6%88%90%E7%9F%A5%E4%B9%8E%E6%97%A5%E6%8A%A5web%E7%89%88.html" target="_blank" rel="noopener">使用vue完成知乎日报web版</a>的解决方案,使用<a href="https://images.weserv.nl" target="_blank" rel="noopener">Images.weserv.nl</a>进行缓存图片,并在需要使用图片url的地方进行相应的替换。</p><h3 id="…"><a href="#…" class="headerlink" title="…"></a>…</h3><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><blockquote><p>感谢<a href="https://github.com/izzyleung" target="_blank" rel="noopener">izzyleung</a> 整理的 <a href="https://github.com/izzyleung/ZhihuDailyPurify/wiki/%E7%9F%A5%E4%B9%8E%E6%97%A5%E6%8A%A5-API-%E5%88%86%E6%9E%90" target="_blank" rel="noopener">知乎日报API分析</a></p></blockquote><blockquote><p><a href="http://www.yatessss.com/2016/07/08/%E4%BD%BF%E7%94%A8vue%E5%AE%8C%E6%88%90%E7%9F%A5%E4%B9%8E%E6%97%A5%E6%8A%A5web%E7%89%88.html" target="_blank" rel="noopener">使用vue完成知乎日报web版</a> By <a href="https://github.com/yatessss" target="_blank" rel="noopener">yatessss</a> </p></blockquote><h2 id="License"><a href="#License" class="headerlink" title="License"></a>License</h2><p><a href="http://opensource.org/licenses/MIT" target="_blank" rel="noopener">MIT</a></p>]]></content>
<summary type="html">
<h1 id="vue-zhihu-daily"><a href="#vue-zhihu-daily" class="headerlink" title="vue-zhihu-daily"></a>vue-zhihu-daily</h1><p><a href="https://t
</summary>
<category term="Tutorials" scheme="https://chenyubo.me/categories/Tutorials/"/>
<category term="Vue" scheme="https://chenyubo.me/tags/Vue/"/>
<category term="WebApp" scheme="https://chenyubo.me/tags/WebApp/"/>
</entry>
<entry>
<title>《实战ES2015》读书笔记</title>
<link href="https://chenyubo.me/ES2015-read-note/"/>
<id>https://chenyubo.me/ES2015-read-note/</id>
<published>2017-03-03T04:46:25.000Z</published>
<updated>2019-02-02T10:07:57.251Z</updated>
<content type="html"><![CDATA[<p>最近这几天抽空看了一下脸谱书系列中的《实战ES2015》,但是还没看完(其实是懒,逃)。其中的第三章对ES2015中的一些新语法进行了详细的讲解,在这里顺便就参照着书里的知识点总结一下,写个笔记记录一下学习的内容,权当加深一下印象吧!</p><p>顺便推荐一下阮一峰老师的ES6教程<a href="http://es6.ruanyifeng.com/" target="_blank" rel="noopener">ECMAScript6入门</a></p><p>这本书更加详细的阐述了ES6的知识点,相较于《实战ES2015》来说更加偏向于理论,也更加详细,是一本值得学习的好书籍,推荐大家去看!喜欢看实体书的童鞋也可以去各大平台购买实体书,支持一下阮老师!!!</p><h2 id="本文章主要讲解的新语法有:"><a href="#本文章主要讲解的新语法有:" class="headerlink" title="本文章主要讲解的新语法有:"></a>本文章主要讲解的新语法有:</h2><ul><li>let、const和块级作用域</li><li>箭头函数(Arrow Function)</li><li>模板字符串(Template String)</li></ul><h2 id="let、const和块级作用域"><a href="#let、const和块级作用域" class="headerlink" title="let、const和块级作用域"></a>let、const和块级作用域</h2><h3 id="块级作用域"><a href="#块级作用域" class="headerlink" title="块级作用域"></a>块级作用域</h3><p><strong>作用域(Scope)</strong>是<code>ECMAScript</code>编程中非常重要的一个概念,虽然它在通报<code>ECMAScript</code>编程中并不能充分引起初学者的注意,但在异步编程中,良好的作用域控制技巧则成为了<code>ECMAScript</code>开发者的必备技能。</p><p>在<code>ES2015</code>之前的<code>ECMAScript</code>标准中,原本只有<strong>全局作用域</strong>和<strong>函数作用域</strong>。</p><h3 id="let定义变量"><a href="#let定义变量" class="headerlink" title="let定义变量"></a>let定义变量</h3><p>在<code>ES2015</code>中,<code>let</code>可以说是<code>var</code>的进行版本,<code>var</code>在绝大部分情况下可以被<code>let</code>替代。<code>let</code>与<code>var</code>的异同点大致如下表:</p><table><thead><tr><th></th><th>let</th><th>var</th></tr></thead><tbody><tr><td>定义变量</td><td>✅</td><td>✅</td></tr><tr><td>可被释放</td><td>✅</td><td>❌</td></tr><tr><td>可被提示(Hoist)</td><td>❌</td><td>✅</td></tr><tr><td>重复定义检查</td><td>✅</td><td>❌</td></tr><tr><td>可被用于块级作用域</td><td>✅</td><td>❌</td></tr></tbody></table><p><strong>重复定义检查</strong>可以用下面这段代码来说明:</p><pre><code class="javascript">// varvar foo = 'bar';var foo = 'abc';console.log(foo); //=> abc// letlet bar = 'foo';let bar = 'def'; //=> Uncaught SyntaxError: Identifier 'bar' has already been declared</code></pre><p><code>var</code>可以让同一个变量名在同一个作用域里被定义多次,而这种“特性”很可能会导致一些问题。而<code>let</code>则加入了代码审查(Code Review)制度,当同一个变量名在同一个作用域内被定义第二次时,便会抛出错误,以警示开发者修改代码。</p><p>此外,<code>let</code>可被用于<strong>块级作用域(Block Scope)</strong>。</p><p>使用<code>let</code>形成的块级作用域可以在大部分具有<code>{ ... }</code>的语句中使用,例如</p><ul><li><code>for () {}</code></li><li><code>do {} while()</code></li><li><code>while {}</code></li><li><code>switch() {}...</code></li></ul><pre><code class="js">switch(true) { default: let bar = 'foo'; break;}console.log(bar); //=> undifined</code></pre><h3 id="const定义常量"><a href="#const定义常量" class="headerlink" title="const定义常量"></a>const定义常量</h3><p><code>const</code>的引入是<code>ECMAScript</code>获得了真正的定义常量的能力。</p><pre><code class="javascript">// 定义一个常量const PI = 3.1415926;// 尝试对该常量进行重新赋值PI = 3.14; //=> Uncaught TypeError: Assignment to constant variable.</code></pre><p>变量与内存之间的关系由三个部分组成:</p><ul><li>变量名</li><li>内存绑定</li><li>内存(内存地址)</li></ul><p><code>ECMAScript</code>读取变量时,会从变量当前的内存地址所指想的内存空间中读取内容。当用户改变变量的值时,引擎会重新从内存中分配一个新的内存空间以存储新的值,并将新的内存地址与变量进行绑定。const的原理就是在变量名与内存地址之间建立<strong>不可变</strong>的绑定,当后面的程序尝试申请新的内存空间时,引擎便会抛出错误。</p><p>除了<code>let</code>会产生块级作用域以外,<code>const</code>同样可以产生块级作用域,其定义的常量也同样遵循变量在作用域中的生命周期。</p><h3 id="变量的生命周期"><a href="#变量的生命周期" class="headerlink" title="变量的生命周期"></a>变量的生命周期</h3><p>在<code>ECMAScript</code>中,一个变量(或常量)的生命周期(Life Cycle)模式是固定的,由两种因素决定:</p><ul><li>作用域</li><li>对其的引用</li></ul><p>绝大部分<code>ECMAScript</code>运行引擎对垃圾数据的收集方式都是基于对变量(或常量)的<strong>引用</strong>进行统计,当一个变量的引用被全部解除时,引擎便会将其认定为应该被清除的。简单表示便是:<strong>一个事物当为人所需要时,便永生不朽;但若被抛弃时,便悄离去。</strong></p><p>如果想延长的变量的生命周期,最为常用的方法便是闭包(Closure)。因为变量的生命周期由对其的引用所决定,二闭包的原理便是利用高阶函数来产生能够穿透作用域的引用。</p><p>在<code>ECMAScript</code>中,变量(或常量)的生命周期是从程序进入定义语句所在的作用域开始的,即便是在定义语句之前。例如下面这行代码:</p><pre><code class="javascript">var foo = 1;</code></pre><p>我们不妨将这一句拆分成两句,以便更好理解后面的内容。</p><pre><code class="javascript">var foo; // Declarationfoo = 1; // Assignment</code></pre><ol><li><code>ECMAScript</code>引擎在进入一个作用域时,会先扫描这个作用域内的变量(或常量)定义语句(<code>var</code>,<code>let</code>或<code>const</code>),然后在这个作用域内为扫描得到的变量名做准备,在当前作用域内被扫描到的变量名都会进入未声明<strong>(Undeclared)阶段</strong>。</li><li>进入声明语句时,<code>var foo;</code>,即前半句是<strong>声明部分(Declaration)</strong>,用于在<code>ECMAScript</code>引擎中产生一个变量名,当此时此刻变量名没有对应的绑定和内存空间,所以“值”为null。</li><li><code>=</code>的左右是作为变量的赋值语句,引擎执行至此处即为该变量的<strong>赋值部分(Assignment)</strong>,计算将要赋予变量名的值的物理长度(内存空间占用大小),向系统申请相应大小的内存空间,然后将数据存储到里面去,并在变量名和内存空间之间<strong>建立绑定(Binding)关系</strong>,此时变量(或常量)才得到了相应的值。</li><li>到当前作用域中的语句被执行完毕时,引擎便会检查该作用域中被定义的变量(或常量)的被引用情况,如果引用已被全部解除,引擎便会认为其应该被清除。</li><li>运行引擎会不断检查存在于运行时(Runtime)中的变量(或常量)的被引用情况,并重复第四步,直至程序结束。<br>ES2015标准中(一般情况下为严格模式)不允许变量(或常量)在被定义之前被其他语句所读取,以免出现逻辑性错误。</li></ol><h3 id="更佳体验"><a href="#更佳体验" class="headerlink" title="更佳体验"></a>更佳体验</h3><p>从工程化角度上看,我们应该在<code>ES2015</code>中遵循以下三条原则:</p><ul><li>一般情况下,使用<code>const</code>来定义值的存储容器(常量)。</li><li>只有在值容器明确地被确定将会被改变时才使用<code>let</code>来定义(变量)。</li><li>不再使用<code>var</code>。</li></ul><h2 id="箭头函数(Arrow-Function)"><a href="#箭头函数(Arrow-Function)" class="headerlink" title="箭头函数(Arrow Function)"></a>箭头函数(Arrow Function)</h2><p>除了<code>let</code>和<code>const</code>外,箭头函数是使用频率最高的新特性了。</p><h3 id="使用语法"><a href="#使用语法" class="headerlink" title="使用语法"></a>使用语法</h3><ol><li>单一参数的单行箭头函数</li></ol><pre><code class="javascript">// Systax: arg => statementconst fn = foo => `${foo} world` // means return `foo + 'world'`// 这是箭头函数最简洁的形式,常见于用作简单的处理函数,如过滤。let array = ['a', 'bc', 'def', 'ghij'];array = array.filter(item => item.length >= 2); //=> bc, def, ghij</code></pre><ol start="2"><li>多参数的单行箭头函数</li></ol><pre><code class="javascript">// Systax: (arg1, arg2) => statementconst fn = (foo, bar) => `${foo} world` // means return `foo + 'world'`</code></pre><p>在大多数情况下,函数都不会只有一个参数传入,在箭头函数中,多参数的语法跟普通函数一样,以括号来包裹参数列。这种形式常见于数组的处理,如排序。</p><pre><code class="javascript">let array = ['a', 'bc', 'def', 'ghij'];array = array.sort((a, b) => a.length < b.length); //=> ghij, def, bc, a</code></pre><ol start="3"><li>多行箭头函数</li></ol><pre><code class="javascript">// Systax: arg => { ... }// 单一参数foo => { return `${foo} world`;}// Systax: (arg1, arg2) => { ... }// 多参数(foo, bar) => { return foo + bar;}</code></pre><ol start="4"><li>无参数箭头函数</li></ol><p>如果一个箭头函数无参数传入,则需要用一对空的括号来表示空的参数列表</p><pre><code class="javascript">// Systax: () => statementconst greet = () => 'Hello World';</code></pre><h3 id="this穿透"><a href="#this穿透" class="headerlink" title="this穿透"></a>this穿透</h3><p>箭头函数就如同它在<code>CoffeeScript</code>中的定义一般,是用于将函数内部的<code>this</code>延伸至上一层作用域中,即上一层的上下文会穿透到内层的箭头函数中。</p><h3 id="程序逻辑注意事项"><a href="#程序逻辑注意事项" class="headerlink" title="程序逻辑注意事项"></a>程序逻辑注意事项</h3><ul><li>箭头函数对上下文的绑定是强制性的,无法通过<code>apply</code>或<code>call</code>方法改变。</li><li>因为箭头函数绑定上下文的特性,故不能随意在顶层作用域使用箭头函数。</li><li>同样地,在箭头函数中也没有<code>arguments</code>、<code>callee</code>甚至`caller等对象。</li><li>如果哟使用<code>arguments</code>的需求,可以使用后续参数<code>...set</code>来获得参数列表。</li></ul><h3 id="编写语法注意事项"><a href="#编写语法注意事项" class="headerlink" title="编写语法注意事项"></a>编写语法注意事项</h3><p><code>ES2015</code>提供了多行的箭头函数语法,所有在使用单行箭头函数时,请不要对单行的函数体做任何换行,以免出现语法错误。</p><pre><code class="javascript">const fn = x => x * 2; // SystaxErrorconst fn = x => x * 2; // OK</code></pre><p>参数列表的右括弧、箭头需要保持在同一行内。</p><pre><code class="javascript">const fn = (x, y) // SystaxError=> { return x * y;}const fn = (x, y) => { // OK return x * y;}const fn = (x, y) => { // OK return x * y;}</code></pre><p>单行箭头函数只能包含一条语句。但如果是错误抛出语句(throw)等非表达式的语句,则需要使用花括号包裹。</p><pre><code class="javascript">const fn1 = x => x * 2; // OKconst fn2 = x => x = x * 2; return x + 2; // SystaxErrorconst fn3 = x => { // OK x = x * 2; return x + 2; }const fn4 = x => { throw new Error('some error message'); } // OK</code></pre><p>若要使用单行箭头函数直接返回一个对象字面量,请使用一个括号包裹该对象字面量,而不是直接使用大括号,否则ECMAScript解析引擎会将其解析为一个多行箭头函数。</p><pre><code class="javascript">const ids = [ 1, 2, 3 ];const users = ids.map(id => { id: id});//=> Wrong: [ undefined, undefined, undefined ]const ids = [ 1, 2, 3 ];const users = ids.map(id => ({ id: id}));//=> Correct: [ { id: 1 }, { id: 2 }, { id: 3 } ]</code></pre><h2 id="模板字符串"><a href="#模板字符串" class="headerlink" title="模板字符串"></a>模板字符串</h2><h3 id="使用语法-1"><a href="#使用语法-1" class="headerlink" title="使用语法"></a>使用语法</h3><p>我们使用普通字符串时会用单引号或双引号阿里包裹字符串的内容。而<code>ES2015</code>的模板字符串则需要使用<strong>反勾号(backtick,`)</strong>。</p><pre><code class="javascript">// Systax: `string`const str = `something`</code></pre><p>支持字符串元素注入</p><pre><code class="javascript">// Systax: `before-${injectVariable}-after`const str = 'str'const num = 1;// ...const str1 = `String: ${str}` //=> String: strconst str2 = `Number: ${num}` //=> Number: 1// ...</code></pre><p>支持换行</p><pre><code class="javascript">/** * Systax: ` * content * */ const sql = ` SELECT * FROM Users WHERE FirstName = 'Mike' LIMIT 5; `</code></pre><p>有以下一些字符串字面量,通常用于非打印或特殊用途的字符,如下表所示:</p><table><thead><tr><th>字面量</th><th>含义</th></tr></thead><tbody><tr><td><code>\n</code></td><td>换行</td></tr><tr><td><code>\r</code></td><td>回车</td></tr><tr><td><code>\t</code></td><td>制表符</td></tr><tr><td><code>\b</code></td><td>空格</td></tr><tr><td><code>\f</code></td><td>进制</td></tr><tr><td><code>\\</code></td><td>用于打印<code>\</code></td></tr><tr><td><code>\'</code></td><td>用于打印<code></code>‘`</td></tr><tr><td><code>\"</code></td><td>用于打印<code>"</code></td></tr><tr><td><code>\xnn</code></td><td>以十六进制代码<code>nn</code> 表示一个字符(其中<code>n</code>为<code>0~F</code>)。例如<code>\x41</code>为<code>A</code></td></tr><tr><td><code>\unnnn</code></td><td>以十六进制代码<code>nnnn</code> 表示一个<code>Unicode</code>字符(其中<code>n</code>为<code>0~F</code>)。例如<code>\u03a3</code>为<code>∑</code></td></tr></tbody></table><p>多行模板字符串会在每一行的最后添加一个<code>\n</code>字面量,所以在读取多行字符串的长度时,除最后一行外,每一行的长度都会加1,即增加了<code>\n</code>的长度</p><pre><code class="javascript">const str = `ABCD` //=> A\nB\nC\nDconsole.log(str.length); //=> 7</code></pre><h3 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h3><p>与普通字符串不一样的是,多行字符串没有两种或两种以上的定义语法,这就意味着它无法向下面第一行代码中普通字符串那样,使用双引号嵌套单引号来表达字符串中的字符串,但可以使用反斜杠来讲需要显示的反勾号转义为普通的字符。</p><pre><code class="javascript">const str1 = "Here is the outter string. 'This is a string in another string'";const str2 = `Here is the outter string. \`This is a string in another string\``;</code></pre>]]></content>
<summary type="html">
<p>最近这几天抽空看了一下脸谱书系列中的《实战ES2015》,但是还没看完(其实是懒,逃)。其中的第三章对ES2015中的一些新语法进行了详细的讲解,在这里顺便就参照着书里的知识点总结一下,写个笔记记录一下学习的内容,权当加深一下印象吧!</p>
<p>顺便推荐一下阮一峰老师的
</summary>
<category term="Notes" scheme="https://chenyubo.me/categories/Notes/"/>
<category term="ES2105" scheme="https://chenyubo.me/tags/ES2105/"/>
<category term="ES6" scheme="https://chenyubo.me/tags/ES6/"/>
</entry>
<entry>
<title>Mac下MySQL5.7连接Navicat中文乱码解决方案</title>
<link href="https://chenyubo.me/mac-mysql57-navicat-chinese-messy/"/>
<id>https://chenyubo.me/mac-mysql57-navicat-chinese-messy/</id>
<published>2016-08-08T04:46:25.000Z</published>
<updated>2019-02-02T09:53:08.085Z</updated>
<content type="html"><![CDATA[<blockquote><p>前几天购入mbp不久,准备安装mysql和其他web服务进行web程序开发,结果安装了mysql后运行了以前的一个web程序,在网页里中文显示乱码,但是在navicat里显示中文确实正常的,于是,踩坑之旅由此开始。。。</p></blockquote><h2 id="分析原因"><a href="#分析原因" class="headerlink" title="分析原因"></a>分析原因</h2><p>首先,以前在Windows 10系统下,使用的<code>MySQL5.5</code>,<code>Navicat</code>导入<code>sql</code>文件后,程序运行没有问题,网页现在中文显示正常,于是可以确定程序源码和数据库sql文件没有问题,于是猜测问题可能出在IDE或MySQL上。</p><h2 id="寻找IDE-MyEclipse问题"><a href="#寻找IDE-MyEclipse问题" class="headerlink" title="寻找IDE MyEclipse问题"></a>寻找IDE MyEclipse问题</h2><ul><li><p>jsp页面</p><p>确认jsp页面头部已有</p></li></ul><pre><code class="java"><%@ page language="java" contentType="text/html; charset=UTF-8" import="java.util.*" pageEncoding="UTF-8"%></code></pre><p><meta>层已包含</p><pre><code class="java"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></code></pre><ul><li>jdbc dao层<br>确保数据库连接</li></ul><pre><code class="xml">String url = "jdbc:mysql://localhost:3306/exampleName?Unicode=true&characterEncoding=UTF-8"</code></pre><p>里包含Unicode=true&characterEncoding=UTF-8</p><p>保证以上两点都已修改完成后发现乱码问题还是存在,于是在service层调用dao层代码查询数据库数据后在console里输出,发现输出的乱码与网页上的一致,于是判断乱码问题出在MySQL,与IDE无关。</p><h2 id="寻找MySQL问题"><a href="#寻找MySQL问题" class="headerlink" title="寻找MySQL问题"></a>寻找MySQL问题</h2><p>百度发现网上解决办法已经非常详细,找到一个个人感觉比较详细的解决方案 <a href="http://www.ha97.com/5359.html" target="_blank" rel="noopener">http://www.ha97.com/5359.html</a> 链接里由于是在<code>Linux系统</code>,与<code>mac</code> 的os系统大同小异,所以只需改动少部分就行,其中第二步中的<code>my.cnf</code>文件在<code>MySQL5.7</code>下是没有的,需要在<code>/usr/local/mysql/support-files</code> 中找到<code>my-default.cnf</code>(而在<code>MySQL5.5/5.6</code>下在<code>/usr/local/mysql/support-files</code> 中任意找一个<code>.cnf</code>文件)复制到<code>/etc</code> 文件夹下,改成<code>my.cnf</code>,然后进行修改。</p><p>但是问题来了,修改完<code>my.cnf</code>文件,字符集全部变成<code>utf8</code>后!字符集全部变成<code>utf8</code>后!字符集全部变成<code>utf8</code>后!(重要的事情讲三遍)发现还是中文还是乱码。</p><p>于是在终端打开<code>mysql</code>,进行测试,执行查询结果中文还是乱码,百思不得其解。由于前面都是直接在<code>navicat</code>里直接建表,运行<code>sql</code>文件,突然想如果直接在终端里执行插入语句,是否能成功。说干就干,结果发现如果直接在终端里插入的中文数据在终端里查询显示正常,到<code>navicat</code>里查看结果是???后面直接在终端里运行<code>sql</code>文件,导入数据,最终发现在网页里中文显示已经正常,终端查询中文也正常。</p><p>最终发现是<code>navicat</code>出现了问题</p><h2 id="寻找navicat问题"><a href="#寻找navicat问题" class="headerlink" title="寻找navicat问题"></a>寻找navicat问题</h2><p>百度一波发现有说<code>mac</code>下<code>navicat</code>新建连接是编码选择<code>auto</code>而不是<code>utf</code>8即可,一试,果然可以,但是还是不清楚为什么<code>mac</code>下的<code>navicat</code>跟<code>Windows</code>下不一样,这个问题是比较奇葩。</p><p>至此,乱码问题已解决。</p>]]></content>
<summary type="html">
<blockquote>
<p>前几天购入mbp不久,准备安装mysql和其他web服务进行web程序开发,结果安装了mysql后运行了以前的一个web程序,在网页里中文显示乱码,但是在navicat里显示中文确实正常的,于是,踩坑之旅由此开始。。。</p>
</blockquo
</summary>
<category term="Notes" scheme="https://chenyubo.me/categories/Notes/"/>
<category term="Mac" scheme="https://chenyubo.me/tags/Mac/"/>
<category term="MySQL" scheme="https://chenyubo.me/tags/MySQL/"/>
</entry>
</feed>