-
Notifications
You must be signed in to change notification settings - Fork 1
/
atom.xml
298 lines (182 loc) · 180 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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>筑室因藏善本书</title>
<subtitle>随笔杂记</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://muxfe.github.io/"/>
<updated>2018-12-05T02:02:27.779Z</updated>
<id>http://muxfe.github.io/</id>
<author>
<name>萧暮Kyer</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>前端学习路线</title>
<link href="http://muxfe.github.io/2018/11/10/front-learning-roadmap/"/>
<id>http://muxfe.github.io/2018/11/10/front-learning-roadmap/</id>
<published>2018-11-10T02:03:20.000Z</published>
<updated>2018-12-05T02:02:27.779Z</updated>
<content type="html"><![CDATA[<p>转眼间已经研三了,从大二开始接触 Web 前端,到读研期间参与实验室大大小小的一些项目,再加上今年暑假的一些实习经历,想对前端的学习方法和路线记录一些自己的思考,作为沉淀。</p><a id="more"></a><h1 id="个人经历"><a href="#个人经历" class="headerlink" title="个人经历"></a>个人经历</h1><ul><li>大一学 C/C++,接触基本的编程和计算机知识,学习主要来源于课程和作业实践等。</li><li>大二开始接触 PHP 语言,学习 Web 开发,通过阅读 <a href="https://baike.baidu.com/item/cms%E7%B3%BB%E7%BB%9F/6089246" target="_blank" rel="noopener">CMS</a> 网站源码学习各种知识。</li><li>大三开始转型前端,后端学习 JavaWeb 开发,前端学习 jQuery 等。</li><li>大四在导师实验室做一些项目,主要负责前端,开始使用 Angular1,通过学习 Zepplin 源码。</li><li>研一开始学习 React,用 <a href="https://ant.design/index-cn" target="_blank" rel="noopener">Ant Design</a> 做项目。</li><li>研二开始学习 Vue,用 <a href="http://element-cn.eleme.io/#/zh-CN" target="_blank" rel="noopener">Element-UI</a> 做项目。</li><li>研二暑期在头条实习了三个月,接触 Webpack / Babel 插件等。</li></ul><h1 id="开发工具"><a href="#开发工具" class="headerlink" title="开发工具"></a>开发工具</h1><p>工欲善其事,必先利其器。下面是一些通用的开发/效率工具,在<a href="http://liqi.io/creators/" target="_blank" rel="noopener">利器</a>可以看其他人的工具箱。</p><h2 id="编辑器"><a href="#编辑器" class="headerlink" title="编辑器"></a>编辑器</h2><ul><li><a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a> - 最好的编辑器,没有之一,微软出品</li><li><a href="https://atom.io/" target="_blank" rel="noopener">Atom</a> - GitHub 出的编辑器,大项目卡顿明显</li><li><a href="https://www.sublimetext.com/" target="_blank" rel="noopener">Sublime Text</a> - 轻量级的单文件编辑器</li><li><a href="https://www.ultraedit.com/" target="_blank" rel="noopener">UltraEdit</a> - 打开超大文件(大于 1 GB)必备</li></ul><h2 id="版本管理"><a href="#版本管理" class="headerlink" title="版本管理"></a>版本管理</h2><ul><li><a href="https://git-scm.com/" target="_blank" rel="noopener">Git</a> - Linux 之父开发的大规模代码版本管理工具</li><li><a href="https://github.com/" target="_blank" rel="noopener">GitHub</a> - 最大的同性交友网站</li><li><a href="http://gitee.com/" target="_blank" rel="noopener">码云</a> - 国内的 Git 服务</li></ul><h2 id="浏览器及扩展"><a href="#浏览器及扩展" class="headerlink" title="浏览器及扩展"></a>浏览器及扩展</h2><ul><li><a href="https://www.google.com/chrome/" target="_blank" rel="noopener">Chrome</a> - 谷歌浏览器,不用多介绍了</li><li><a href="https://www.mozilla.org/en-US/firefox/" target="_blank" rel="noopener">Firefox</a> - 今年更新后性能大幅度提升</li><li><a href="https://www.getpostman.com/" target="_blank" rel="noopener">Postman</a> - 浏览器插件,用于测试 API</li><li><a href="https://github.com/FelisCatus/SwitchyOmega" target="_blank" rel="noopener">SwitchOmega</a> - 浏览器代理管理插件</li><li><a href="https://github.com/ovity/octotree" target="_blank" rel="noopener">OctoTree</a> - GitHub 辅助插件,方便浏览仓库目录</li></ul><h2 id="网络抓包工具"><a href="#网络抓包工具" class="headerlink" title="网络抓包工具"></a>网络抓包工具</h2><ul><li><a href="https://www.charlesproxy.com/" target="_blank" rel="noopener">Charles</a> - 抓包代理利器,可用于劫持特定域名测试</li><li><a href="https://www.wireshark.org/" target="_blank" rel="noopener">WireShark</a> - 著名抓包工具</li></ul><h2 id="搜索引擎-知识库"><a href="#搜索引擎-知识库" class="headerlink" title="搜索引擎/知识库"></a>搜索引擎/知识库</h2><p>排名分先后!</p><ul><li><a href="https://www.google.com/" target="_blank" rel="noopener">Google</a> - 自己搞定翻墙</li><li><a href="https://github.com/" target="_blank" rel="noopener">GitHub</a> - 搜开源库/最佳实践/issue 等</li><li><a href="https://stackoverflow.com/" target="_blank" rel="noopener">StackOverflow</a> - 解决各种疑难杂症</li><li><a href="https://cn.bing.com/" target="_blank" rel="noopener">Bing</a> - 如果实在没有翻墙的替代品</li><li><a href="https://segmentfault.com/" target="_blank" rel="noopener">SegmentFault</a> - 中文版 StackOverflow</li><li><a href="https://www.baidu.com/" target="_blank" rel="noopener">Baidu</a> - 对搜索结果擦亮眼睛</li></ul><p>其实 StackOverflow/SegmentFault/Github 的 SEO 都做得很好,所以优先用搜索引擎,注意组合关键词。</p><h2 id="其他工具"><a href="#其他工具" class="headerlink" title="其他工具"></a>其他工具</h2><ul><li><a href="https://shimo.im/" target="_blank" rel="noopener">石墨文档</a> - 在线文档工具,支持多人协作</li><li><a href="https://www.yuque.com/" target="_blank" rel="noopener">语雀</a> - 阿里的团队文档工具</li><li><a href="https://processon.com/" target="_blank" rel="noopener">ProcessOn</a> - 在线画图工具</li><li><a href="https://codesandbox.io" target="_blank" rel="noopener">CodeSandbox</a> - 在线代码编辑器,并可以运行,支持多种框架</li><li><a href="https://cli.im/" target="_blank" rel="noopener">草料二维码生成器</a> - 生成各种二维码的小工具</li></ul><h1 id="基础知识"><a href="#基础知识" class="headerlink" title="基础知识"></a>基础知识</h1><h2 id="HTML"><a href="#HTML" class="headerlink" title="HTML"></a>HTML</h2><p><a href="https://zh.wikipedia.org/wiki/HTML" target="_blank" rel="noopener">HTML</a> 是一种标记式语言,是 XML 的一个子集,最基础也最简单。</p><ul><li>常用的标签(或者叫元素)</li><li>表单的操作</li><li>多媒体</li></ul><h2 id="CSS"><a href="#CSS" class="headerlink" title="CSS"></a>CSS</h2><p><a href="https://zh.wikipedia.org/wiki/%E5%B1%82%E5%8F%A0%E6%A0%B7%E5%BC%8F%E8%A1%A8" target="_blank" rel="noopener">CSS</a> 是一种声明式语言,易学难精。</p><ul><li>元素选择器</li><li>引入方式和规则的优先级</li><li>盒模型</li><li>行级元素和块级元素</li><li>浮动和定位</li><li>常用布局</li></ul><h2 id="JavaScript"><a href="#JavaScript" class="headerlink" title="JavaScript"></a>JavaScript</h2><p><a href="https://zh.wikipedia.org/wiki/JavaScript" target="_blank" rel="noopener">JavaScript</a> 是一种解释型语言,主要为浏览器提供丰富的交互能力,也是易学难精。</p><ul><li>基础语法</li><li>变量和作用域</li><li>函数表达式</li><li>在 HTML 中如何使用</li><li>DOM</li><li>BOM</li><li>事件机制</li><li>表单处理</li><li>Ajax</li><li>JSON</li></ul><h2 id="Web"><a href="#Web" class="headerlink" title="Web"></a>Web</h2><ul><li><a href="https://github.com/skyline75489/what-happens-when-zh_CN" target="_blank" rel="noopener">当你在浏览器中输入 google.com 并且按下回车之后发生了什么</a></li><li><a href="http://www.ruanyifeng.com/blog/2012/05/internet_protocol_suite_part_i.html" target="_blank" rel="noopener">互联网协议入门</a></li><li><a href="http://www.ruanyifeng.com/blog/2016/06/dns.html" target="_blank" rel="noopener">DNS 原理入门</a></li></ul><h2 id="学习资源"><a href="#学习资源" class="headerlink" title="学习资源"></a>学习资源</h2><ul><li><a href="https://developer.mozilla.org/zh-CN/docs/Web" target="_blank" rel="noopener">MDN Web 技术文档</a></li><li><a href="http://www.w3school.com.cn/index.html" target="_blank" rel="noopener">W3School</a></li><li><a href="http://www.runoob.com/" target="_blank" rel="noopener">菜鸟教程</a></li><li><a href="http://javascript.ruanyifeng.com/" target="_blank" rel="noopener">JavaScript 标准参考教程(alpha)</a></li><li><a href="http://zh.learnlayout.com/" target="_blank" rel="noopener">学习 CSS 布局</a></li><li><a href="http://www.imooc.com/learn/36" target="_blank" rel="noopener">慕课网 JavaScript 入门篇</a></li></ul><h1 id="中级提升"><a href="#中级提升" class="headerlink" title="中级提升"></a>中级提升</h1><h2 id="HTML5-CSS3"><a href="#HTML5-CSS3" class="headerlink" title="HTML5/CSS3"></a>HTML5/CSS3</h2><p>主要是了解新特性和理解语义化。</p><ul><li><a href="http://www.runoob.com/css3/css3-tutorial.html" target="_blank" rel="noopener">CSS3 教程</a></li><li><a href="http://www.runoob.com/html/html5-intro.html" target="_blank" rel="noopener">HTML5 教程</a></li></ul><h2 id="ECMAScript6"><a href="#ECMAScript6" class="headerlink" title="ECMAScript6"></a><a href="https://en.wikipedia.org/wiki/ECMAScript" target="_blank" rel="noopener">ECMAScript</a>6</h2><p>主要了解 ES6 的新特性及其在工程实践中的用法,配合 Webpack/Babel 等。</p><ul><li><a href="http://es6-features.org" target="_blank" rel="noopener">ES6 的新特性</a></li><li><a href="https://kangax.github.io/compat-table/es6/" target="_blank" rel="noopener">ES6 的支持情况</a></li><li><a href="http://es6.ruanyifeng.com/" target="_blank" rel="noopener">ECMAScript 6 入门</a></li><li><a href="https://github.com/lukehoban/es6features" target="_blank" rel="noopener">lukehoban/es6features</a></li></ul><h2 id="模块化"><a href="#模块化" class="headerlink" title="模块化"></a>模块化</h2><p>主要了解为什么要模块化以及如何在浏览器和 Node 中使用,理解不同模块化的思想和适用场景。</p><ul><li><a href="http://www.ruanyifeng.com/blog/2012/10/javascript_module.html" target="_blank" rel="noopener">Javascript模块化编程</a></li><li><a href="https://segmentfault.com/a/1190000012464333" target="_blank" rel="noopener">JavaScript 模块讲解</a></li><li><a href="https://www.infoq.cn/article/es6-in-depth-modules" target="_blank" rel="noopener">深入浅出 ES6 模块</a></li><li><a href="https://zhuanlan.zhihu.com/p/22890374" target="_blank" rel="noopener">JavaScript 模块化入门</a></li><li><a href="http://xieyufei.com/2017/02/19/JS-Standard.html" target="_blank" rel="noopener">理解 JS 模块化</a></li><li><a href="https://www.zhihu.com/question/20351507" target="_blank" rel="noopener">AMD 和 CMD 的区别有哪些?</a></li></ul><h2 id="NodeJS"><a href="#NodeJS" class="headerlink" title="NodeJS"></a><a href="https://nodejs.org/" target="_blank" rel="noopener">NodeJS</a></h2><p>NodeJS 扩展了 JavaScript 的能力边界,使它可以用在桌面端和服务器端,用法很多,主要先了解什么是 NodeJS以及如何使用。</p><ul><li><a href="http://www.runoob.com/nodejs/nodejs-tutorial.html" target="_blank" rel="noopener">NodeJS 教程</a></li><li><a href="https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/001434501245426ad4b91f2b880464ba876a8e3043fc8ef000" target="_blank" rel="noopener">廖雪峰的 NodeJS 教程</a></li><li><a href="https://www.nodebeginner.org/index-zh-cn.html" target="_blank" rel="noopener">Node 入门</a></li><li><a href="https://www.zhihu.com/question/19793473" target="_blank" rel="noopener">怎样有效地学习 Node.js?</a></li><li><a href="https://nqdeng.github.io/7-days-nodejs/" target="_blank" rel="noopener">七天学会NodeJS</a></li><li><a href="https://github.com/i0natan/nodebestpractices" target="_blank" rel="noopener">NodeJS Best Practices</a></li></ul><h2 id="基础框架"><a href="#基础框架" class="headerlink" title="基础框架"></a>基础框架</h2><p>这些是今年比较主流的前端框架,不需要全部掌握,主要理解框架的用法和思想,适用的场景和解决的问题等。框架只是基础能力的最佳实践,变化很快,不要过于以来框架,而是驾驭框架。</p><ul><li><a href="https://jquery.com/" target="_blank" rel="noopener">jQuery</a><ul><li><a href="http://www.runoob.com/jquery/jquery-tutorial.html" target="_blank" rel="noopener">jQuery 教程</a></li><li><a href="https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000" target="_blank" rel="noopener">廖雪峰的 JS 教程</a></li><li><a href="https://www.zhihu.com/question/19667102" target="_blank" rel="noopener">新手如何学习 jQuery?</a></li></ul></li><li><a href="https://getbootstrap.com/" target="_blank" rel="noopener">BootStrap</a><ul><li><a href="http://www.runoob.com/bootstrap/bootstrap-tutorial.html" target="_blank" rel="noopener">BootStrap 教程</a></li><li><a href="https://www.zhihu.com/question/20221979" target="_blank" rel="noopener">如何学习 twitter bootstrap?</a></li></ul></li><li><a href="https://reactjs.org/" target="_blank" rel="noopener">React</a><ul><li><a href="http://www.runoob.com/react/react-tutorial.html" target="_blank" rel="noopener">React 教程</a></li><li><a href="http://www.ruanyifeng.com/blog/2015/03/react.html" target="_blank" rel="noopener">React 入门实例教程</a></li><li><a href="http://huziketang.mangojuice.top/books/react/" target="_blank" rel="noopener">React.js 小书</a></li><li><a href="https://react.docschina.org/tutorial/tutorial.html" target="_blank" rel="noopener">React 入门教程</a></li><li>组件库:<a href="https://ant.design/docs/react/introduce-cn" target="_blank" rel="noopener">Ant Design</a>/<a href="https://react.semantic-ui.com/" target="_blank" rel="noopener">SemanticUI</a>…</li></ul></li><li><a href="https://cn.vuejs.org/v2/guide/index.html" target="_blank" rel="noopener">Vue</a><ul><li><a href="http://www.runoob.com/vue2/vue-tutorial.html" target="_blank" rel="noopener">Vue 教程</a></li><li><a href="https://github.com/liangxiaojuan/vue-todos" target="_blank" rel="noopener">Vue Todos</a></li><li>组件库:<a href="http://element-cn.eleme.io/#/zh-CN" target="_blank" rel="noopener">ElementUI</a>/<a href="https://muse-ui.org/#/zh-CN" target="_blank" rel="noopener">MuseUI</a>/<a href="https://www.iviewui.com/" target="_blank" rel="noopener">iViewUI</a>…</li><li>移动端:<a href="http://mint-ui.github.io/#!/zh-cn" target="_blank" rel="noopener">MintUI</a>/<a href="https://vux.li/" target="_blank" rel="noopener">Vux</a>…</li></ul></li><li><a href="https://angular.io/" target="_blank" rel="noopener">Angular</a><ul><li><a href="http://www.runoob.com/angularjs/angularjs-tutorial.html" target="_blank" rel="noopener">AngularJS 教程</a></li><li><a href="https://angular.cn/guide/quickstart" target="_blank" rel="noopener">快速上手</a></li><li>组件库:<a href="https://ng-bootstrap.github.io/" target="_blank" rel="noopener">NgBootStrap</a>/<a href="https://material.angular.io/" target="_blank" rel="noopener">Material2</a>/<a href="https://www.primefaces.org/primeng/" target="_blank" rel="noopener">PrimeNg</a>…</li></ul></li></ul><h2 id="编码规范"><a href="#编码规范" class="headerlink" title="编码规范"></a>编码规范</h2><p>工程项目变大以后,规范就会显得尤为重要。良好的规范可以提升开发和协作效率,易扩展维护等。编码规范有些已经达成共识,有些则全凭团队/个人喜好,没有对错,只要遵守适应就可以。</p><ul><li><a href="http://alloyteam.github.io/CodeGuide/" target="_blank" rel="noopener">AlloyTeam 的团队编码规范</a></li><li><a href="https://guide.aotu.io/" target="_blank" rel="noopener">京东凹凸实验室的编码规范</a></li><li><a href="https://github.com/airbnb/javascript" target="_blank" rel="noopener">Airbnb 编码规范</a></li><li><a href="https://google.github.io/styleguide/jsguide.html" target="_blank" rel="noopener">Google JS 编码规范</a></li><li><a href="https://github.com/pablohpsilva/vuejs-component-style-guide" target="_blank" rel="noopener">Vue 组件编码规范</a></li></ul><p>可以用工具来强制团队所遵循的编码规范,如</p><ul><li><a href="https://eslint.org/" target="_blank" rel="noopener">ESLint</a></li><li><a href="https://github.com/prettier/prettier" target="_blank" rel="noopener">Prettier</a></li><li><a href="https://github.com/douglascrockford/JSLint" target="_blank" rel="noopener">JSLint</a></li></ul><h1 id="高级进阶"><a href="#高级进阶" class="headerlink" title="高级进阶"></a>高级进阶</h1><h2 id="标准规范"><a href="#标准规范" class="headerlink" title="标准规范"></a>标准规范</h2><p>标准规范是基石,可谓万变不离其宗。</p><ul><li><a href="https://www.w3.org/standards/" target="_blank" rel="noopener">W3C</a></li><li><a href="https://www.w3.org/Protocols/" target="_blank" rel="noopener">HTTP</a></li><li><a href="https://http2.github.io/" target="_blank" rel="noopener">HTTP/2</a></li><li><a href="https://github.com/tc39/ecma262" target="_blank" rel="noopener">ECMA-262</a></li></ul><h2 id="前端工程化"><a href="#前端工程化" class="headerlink" title="前端工程化"></a>前端工程化</h2><p>现在但凡带框架的前端项目已经离不开工程化了,从脚手架,Mock,Babel,CSS 预处理器,Webpack 大礼包,到测试,构建,ci,发布等。</p><ul><li><a href="https://gulpjs.com/" target="_blank" rel="noopener">Gulp</a></li><li><a href="https://webpack.js.org/" target="_blank" rel="noopener">Webpack</a></li><li>CSS 预处理器<ul><li><a href="http://lesscss.org/" target="_blank" rel="noopener">Less</a></li><li><a href="https://sass-lang.com/" target="_blank" rel="noopener">Sass</a></li></ul></li><li><a href="https://babeljs.io/" target="_blank" rel="noopener">Babel</a><ul><li><a href="http://www.ruanyifeng.com/blog/2016/01/babel.html" target="_blank" rel="noopener">Babel 入门教程</a></li></ul></li><li><a href="https://www.typescriptlang.org/" target="_blank" rel="noopener">TypeScript</a></li></ul><h2 id="设计模式"><a href="#设计模式" class="headerlink" title="设计模式"></a>设计模式</h2><p>设计模式是一些沉淀下来好的开发方式,不同的设计模式应用于不同的场景,在操作系统、数据库、开源框架中,设计模式几乎无处不在。前端中也包含很多设计模式,值得学习提高。</p><ul><li><a href="http://www.ruanyifeng.com/blog/2015/02/mvcmvp_mvvm.html" target="_blank" rel="noopener">MVC,MVP 和 MVVM 的图示</a></li><li><a href="https://juejin.im/post/593021272f301e0058273468" target="_blank" rel="noopener">浅析前端开发中的 MVC/MVP/MVVM 模式</a></li><li><a href="http://efe.baidu.com/blog/mvc-deformation/" target="_blank" rel="noopener">前端 MVC 变形记</a></li><li><a href="https://www.zhihu.com/question/20148405" target="_blank" rel="noopener">你对 MVC、MVP、MVVM 三种组合模式分别有什么样的理解?</a></li><li><a href="https://draveness.me/mvx" target="_blank" rel="noopener">浅谈 MVC、MVP 和 MVVM 架构模式</a></li><li><a href="https://github.com/TooBug/javascript.patterns" target="_blank" rel="noopener">JavaScript Patterns 中译本</a></li><li><a href="http://www.alloyteam.com/2012/10/common-javascript-design-patterns/" target="_blank" rel="noopener">AlloyTeam/JavaScript 设计模式</a></li></ul><h2 id="测试-CI"><a href="#测试-CI" class="headerlink" title="测试/CI"></a>测试/CI</h2><p>测试在大型软件开发中是很重要的,还有以测试为主的 <a href="https://en.wikipedia.org/wiki/Test-driven_development" target="_blank" rel="noopener">TDD</a> 软件开发模式。测试在开源项目中也是衡量其质量的关键。</p><ul><li>工具<ul><li><a href="https://mochajs.org/" target="_blank" rel="noopener">Mocha</a> - 测试框架</li><li><a href="https://jestjs.io/" target="_blank" rel="noopener">Jest</a> - 测试框架</li><li><a href="https://jasmine.github.io/" target="_blank" rel="noopener">Jasmine</a> - 测试框架</li><li><a href="https://www.chaijs.com/" target="_blank" rel="noopener">Chai</a> - 断言库</li><li><a href="https://shouldjs.github.io/" target="_blank" rel="noopener">Should.js</a> - 断言库</li><li><a href="https://www.seleniumhq.org/" target="_blank" rel="noopener">Selenium</a> - 仿真</li><li><a href="https://pptr.dev/" target="_blank" rel="noopener">Puppeteer</a> - 无头浏览器</li></ul></li><li><a href="http://www.ruanyifeng.com/blog/2015/12/a-mocha-tutorial-of-examples.html" target="_blank" rel="noopener">测试框架 Mocha 实例教程</a></li><li><a href="http://www.ruanyifeng.com/blog/2016/02/react-testing-tutorial.html" target="_blank" rel="noopener">React 测试入门教程</a></li><li><a href="http://javascript.ruanyifeng.com/tool/testing.html" target="_blank" rel="noopener">JavaScript 程序测试</a></li><li><a href="http://www.ruanyifeng.com/blog/2015/06/istanbul.html" target="_blank" rel="noopener">代码覆盖率工具 Istanbul 入门教程</a></li><li><a href="http://fex.baidu.com/blog/2015/07/front-end-test/" target="_blank" rel="noopener">FEX/前端自动化测试探索</a></li><li><a href="https://www.zhihu.com/question/29922082" target="_blank" rel="noopener">如何进行前端自动化测试?</a></li><li><a href="http://imweb.io/topic/579ddf3e93d9938132cc8d87" target="_blank" rel="noopener">IMWeb/测试用例的那一回事</a></li><li><a href="http://efe.baidu.com/blog/front-end-continuous-integration-tools/" target="_blank" rel="noopener">前端开源项目持续集成三剑客</a></li><li><a href="https://segmentfault.com/a/1190000007221668" target="_blank" rel="noopener">前端持续集成解决方案</a></li><li><a href="https://www.zhihu.com/question/60194439" target="_blank" rel="noopener">如何实现前端工程的持续集成与持续部署?</a></li><li><a href="https://segmentfault.com/a/1190000005859766" target="_blank" rel="noopener">一个靠谱的前端开源项目需要什么?</a></li></ul><h2 id="发布-部署"><a href="#发布-部署" class="headerlink" title="发布/部署"></a>发布/部署</h2><p>前端代码经过编译/转换/压缩等处理后就可以发布了,具体选择哪种发布方式取决于后端采用的技术。传统的方式是将前端代码放到后端工程中静态资源部署的位置,现在更流行的是前后端解耦的方式、容器化,如 Nginx 反向代理和 Docker 镜像。学习 Shell 脚本编程可以把很多过程脚本自动化。</p><ul><li><a href="https://juejin.im/post/5b01336af265da0b8a67e5c9" target="_blank" rel="noopener">Nginx 反向代理</a></li><li><a href="https://github.com/qinjx/30min_guides/blob/master/shell.md" target="_blank" rel="noopener">Shell 脚本编程 30 分钟入门</a></li><li><a href="https://www.docker.com/" target="_blank" rel="noopener">Docker</a></li><li><a href="http://www.ruanyifeng.com/blog/2018/02/docker-tutorial.html" target="_blank" rel="noopener">阮一峰/Docker 入门教程</a></li></ul><h2 id="其他方向"><a href="#其他方向" class="headerlink" title="其他方向"></a>其他方向</h2><p>前端现在变化和发展很快,甚至有一统客户端和桌面端之势,但是还要根据具体应用场景和技术要求来选择,软件开发没有银弹。</p><ul><li><a href="https://zh.wikipedia.org/wiki/%E5%93%8D%E5%BA%94%E5%BC%8F%E7%BD%91%E9%A1%B5%E8%AE%BE%E8%AE%A1" target="_blank" rel="noopener">响应式设计</a></li><li>移动端:<a href="https://facebook.github.io/react-native/" target="_blank" rel="noopener">RN</a>/<a href="https://weex.incubator.apache.org/" target="_blank" rel="noopener">Weex</a>/<a href="https://mp.weixin.qq.com/cgi-bin/wx" target="_blank" rel="noopener">小程序</a>…</li><li><a href="https://baike.baidu.com/item/%E6%B5%8F%E8%A7%88%E5%99%A8%E5%86%85%E6%A0%B8" target="_blank" rel="noopener">浏览器内核</a></li><li><a href="https://zh.wikipedia.org/wiki/JavaScript%E5%BC%95%E6%93%8E" target="_blank" rel="noopener">JavaScript 引擎</a></li><li>NodeJS 服务端框架:<a href="https://expressjs.com/" target="_blank" rel="noopener">Expressjs</a>/<a href="https://koajs.com/" target="_blank" rel="noopener">Koa</a>…</li><li><a href="https://electronjs.org/" target="_blank" rel="noopener">Electron</a></li><li><a href="https://webassembly.org/" target="_blank" rel="noopener">WebAssembly</a></li></ul><h1 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h1><p>下面是很多大牛总结收集的前端知识图谱,内容很多,可以根据自己的学习计划和兴趣来深入学习,同时要保持求知欲和一个良好的技术视野。</p><ul><li><a href="https://s3.cn-north-1.amazonaws.com.cn/static-documents/nd001/Front-End+Skills+Cheklist_ZH.pdf" target="_blank" rel="noopener">前端工程师技能清单</a></li><li><a href="https://leohxj.gitbooks.io/front-end-database/interview/skill-path.html" target="_blank" rel="noopener">前端技能图谱</a></li><li><a href="https://segmentfault.com/a/1190000010548504" target="_blank" rel="noopener">如何准备一份好的前端面试简历?</a></li><li><a href="https://github.com/JacksonTian/fks" target="_blank" rel="noopener">朴灵前端技能汇总</a></li><li><a href="https://www.zhihu.com/question/19637373" target="_blank" rel="noopener">零基础开始学 Web 前端开发,有什么建议吗?</a></li><li><a href="https://zhuanlan.zhihu.com/p/21935921" target="_blank" rel="noopener">前端学习路径</a></li><li><a href="https://juejin.im/post/5a5e28b2f265da3e355b1451" target="_blank" rel="noopener">2018 Web 开发者最佳学习路线(中文版)</a></li><li><a href="https://github.com/qiu-deqing/FE-learning" target="_blank" rel="noopener">qiu-deqing/FE-learning</a></li><li><a href="https://www.zhihu.com/question/22591993" target="_blank" rel="noopener">前端开发工程师必读书籍有哪些值得推荐?</a></li><li><a href="https://github.com/smyhvae/Web" target="_blank" rel="noopener">前端入门和进阶学习笔记</a></li><li><a href="https://github.com/RubyLouvre/newland/issues/6" target="_blank" rel="noopener">github上值得关注的前端项目</a></li><li><a href="https://www.zhihu.com/question/26886835" target="_blank" rel="noopener">在 GitHub 上有哪些适合前端初学者学习的开源项目?</a></li><li><a href="https://github.com/neal1991/articles-translator" target="_blank" rel="noopener">技术文章翻译</a></li><li><a href="https://www.zhihu.com/question/286700472" target="_blank" rel="noopener">前端未来几年的发展方向是什么?</a></li><li><a href="https://www.zhihu.com/question/286700472" target="_blank" rel="noopener">每个 JavaScript 工程师都应懂的33个概念</a></li></ul>]]></content>
<summary type="html">
<p>转眼间已经研三了,从大二开始接触 Web 前端,到读研期间参与实验室大大小小的一些项目,再加上今年暑假的一些实习经历,想对前端的学习方法和路线记录一些自己的思考,作为沉淀。</p>
</summary>
<category term="前端开发" scheme="http://muxfe.github.io/categories/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/"/>
<category term="前端" scheme="http://muxfe.github.io/tags/%E5%89%8D%E7%AB%AF/"/>
<category term="学习路线" scheme="http://muxfe.github.io/tags/%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF/"/>
<category term="新人" scheme="http://muxfe.github.io/tags/%E6%96%B0%E4%BA%BA/"/>
</entry>
<entry>
<title>追踪前端技术视野</title>
<link href="http://muxfe.github.io/2018/10/22/fe-news/"/>
<id>http://muxfe.github.io/2018/10/22/fe-news/</id>
<published>2018-10-22T08:15:20.000Z</published>
<updated>2018-10-24T07:03:28.248Z</updated>
<content type="html"><![CDATA[<p>在头条实习期间,每周都会有人负责分享前端技术视野,摘取近一周内的行业/技术动态,也不仅仅局限于前端,对于技术视野的扩展和提升非常有帮助。想写篇文章总结一下如何搜集这些信息。</p><a id="more"></a><h1 id="国内"><a href="#国内" class="headerlink" title="国内"></a>国内</h1><h2 id="前端团队"><a href="#前端团队" class="headerlink" title="前端团队"></a>前端团队</h2><p>一般像 BAT 等互联网大厂都有前端团队,他们会有技术输出、博客和周刊等。</p><ul><li><a href="http://taobaofed.org/" target="_blank" rel="noopener">淘宝前端团队</a></li><li><a href="http://www.aliued.com/" target="_blank" rel="noopener">阿里巴巴国际 UED 团队</a></li><li><a href="http://www.aliued.cn/" target="_blank" rel="noopener">阿里巴巴中文站 UED</a></li><li><a href="http://tmallfe.github.io/" target="_blank" rel="noopener">天猫前端团队</a></li><li><a href="https://antv.alipay.com/" target="_blank" rel="noopener">蚂蚁金服体验技术部</a></li><li><a href="http://www.alloyteam.com/" target="_blank" rel="noopener">腾讯 AlloyTeam 团队</a></li><li><a href="http://imweb.io/" target="_blank" rel="noopener">腾讯 IMWeb 团队</a></li><li><a href="https://isux.tencent.com/" target="_blank" rel="noopener">腾讯社交用户体验设计</a></li><li><a href="https://tgideas.qq.com/" target="_blank" rel="noopener">腾讯互娱 TGideas</a></li><li><a href="http://fex.baidu.com/" target="_blank" rel="noopener">百度 Web 前端研发部</a></li><li><a href="http://efe.baidu.com/" target="_blank" rel="noopener">百度前端团队</a></li><li><a href="https://75team.com/" target="_blank" rel="noopener">360 奇舞团</a></li><li><a href="https://aotu.io/" target="_blank" rel="noopener">京东凹凸实验室</a></li><li><a href="https://tech.meituan.com/" target="_blank" rel="noopener">美团点评技术团队</a></li><li><a href="https://github.com/elemefe/" target="_blank" rel="noopener">饿了么前端</a></li><li><a href="http://f2e.souche.com/blog/" target="_blank" rel="noopener">搜车大无线团队博客</a></li></ul><h2 id="大牛"><a href="#大牛" class="headerlink" title="大牛"></a>大牛</h2><p>很多大牛不仅技术厉害,而且还不断积累总结,进行技术输出和布道,活跃于各大网站。</p><ul><li><a href="http://www.ruanyifeng.com/blog/" target="_blank" rel="noopener">阮一峰</a> - 知名博主</li><li><a href="http://evanyou.me/" target="_blank" rel="noopener">尤雨溪</a> - Vue 作者</li><li><a href="http://johnhax.net/" target="_blank" rel="noopener">贺师俊</a> - 人称贺老,资深 Web 开发专家,信仰 Web 标准</li><li><a href="https://www.liaoxuefeng.com/" target="_blank" rel="noopener">廖雪峰</a> - 技术作家</li><li><a href="http://jiongks.name/" target="_blank" rel="noopener">勾三股四</a> - 阿里巴巴高级前端工程师</li><li><a href="https://www.zhangxinxu.com/" target="_blank" rel="noopener">张鑫旭</a> - CSS 大佬</li><li><a href="http://www.w3cplus.com/" target="_blank" rel="noopener">大漠</a> - W3CPlus创始人</li><li><a href="http://zhangwenli.com/" target="_blank" rel="noopener">羡辙</a> - 百度前端工程师,echarts 团队成员,《Three.js 入门指南》作者</li></ul><h2 id="资讯-社区"><a href="#资讯-社区" class="headerlink" title="资讯/社区"></a>资讯/社区</h2><p>列举几个活跃度比较高的网站。</p><ul><li><a href="https://juejin.im/" target="_blank" rel="noopener">掘金</a></li><li><a href="https://segmentfault.com/" target="_blank" rel="noopener">SegmentFault 思否</a></li><li><a href="https://www.v2ex.com/" target="_blank" rel="noopener">V2EX</a></li><li><a href="https://cnodejs.org/" target="_blank" rel="noopener">CNode</a></li><li><a href="https://div.io/#/welcome" target="_blank" rel="noopener">div.io</a></li><li><a href="http://web.jobbole.com/" target="_blank" rel="noopener">伯乐在线</a></li><li><a href="https://www.w3cways.com/" target="_blank" rel="noopener">W3CWays</a></li><li><a href="https://toutiao.io/c/fe" target="_blank" rel="noopener">开发者头条</a></li><li><a href="https://weekly.manong.io/" target="_blank" rel="noopener">码农周刊</a></li><li><a href="https://zhuanlan.zhihu.com/FrontendMagazine" target="_blank" rel="noopener">前端外刊评论</a></li></ul><h1 id="国外"><a href="#国外" class="headerlink" title="国外"></a>国外</h1><ul><li><a href="https://www.reddit.com/r/javascript" target="_blank" rel="noopener">Reddit:JavaScript</a></li><li><a href="https://github.com/trending" target="_blank" rel="noopener">GitHub Trending</a></li><li><a href="https://css-tricks.com/" target="_blank" rel="noopener">CSS Tricks</a></li><li><a href="https://webplatform.news/issues" target="_blank" rel="noopener">Open Web Platform Daily Digest</a></li><li><a href="https://www.w3.org/" target="_blank" rel="noopener">w3</a></li><li><a href="https://news.ycombinator.com/" target="_blank" rel="noopener">HackerNews</a></li><li><a href="https://stackoverflow.com/" target="_blank" rel="noopener">StackOverflow</a></li><li><a href="http://www.quora.com/" target="_blank" rel="noopener">Quora</a></li><li><a href="https://www.youtube.com/channel/UCzoVCacndDCfGDf41P-z0iA" target="_blank" rel="noopener">JSConf</a></li><li><a href="https://developer.mozilla.org/zh-CN/" target="_blank" rel="noopener">MDN</a></li></ul><h1 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h1><ul><li><a href="https://www.zhihu.com/question/29940477" target="_blank" rel="noopener">可以通过什么途径了解前端研发的最新资讯?</a></li><li><a href="https://github.com/whqet/Fed-Hobby" target="_blank" rel="noopener">whqet/Fed-Hobby</a></li><li><a href="http://www.alloyteam.com/nav/" target="_blank" rel="noopener">Web前端导航</a></li><li><a href="https://uptodate.frontendrescue.org/zh/" target="_blank" rel="noopener">如何跟上前端开发的最新前沿</a></li><li><a href="https://github.com/jsfront/src/blob/master/qq.md" target="_blank" rel="noopener">jsfront/src</a></li><li><a href="https://github.com/foru17/front-end-collect" target="_blank" rel="noopener">foru17/front-end-collect</a></li></ul>]]></content>
<summary type="html">
<p>在头条实习期间,每周都会有人负责分享前端技术视野,摘取近一周内的行业/技术动态,也不仅仅局限于前端,对于技术视野的扩展和提升非常有帮助。想写篇文章总结一下如何搜集这些信息。</p>
</summary>
<category term="前端开发" scheme="http://muxfe.github.io/categories/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/"/>
<category term="前端" scheme="http://muxfe.github.io/tags/%E5%89%8D%E7%AB%AF/"/>
<category term="技术视野" scheme="http://muxfe.github.io/tags/%E6%8A%80%E6%9C%AF%E8%A7%86%E9%87%8E/"/>
</entry>
<entry>
<title>2018 春招面试小记</title>
<link href="http://muxfe.github.io/2018/06/15/2018-spring-interview/"/>
<id>http://muxfe.github.io/2018/06/15/2018-spring-interview/</id>
<published>2018-06-15T02:03:20.000Z</published>
<updated>2018-11-02T07:18:41.444Z</updated>
<content type="html"><![CDATA[<p>转眼到了研二找实习工作的时候,因为项目的原因,并没有好好复习,从 3 月初开始准备投递简历到 5 月底入职实习公司,实在是非常累同时也收获很大的一段时间。</p><a id="more"></a><h2 id="春招历程"><a href="#春招历程" class="headerlink" title="春招历程"></a>春招历程</h2><table><thead><tr><th>公司名称</th><th>部门</th><th>方式</th><th>技术面次数</th><th>起止时间</th></tr></thead><tbody><tr><td>腾讯</td><td>腾讯云</td><td>电话</td><td>1</td><td>3-12</td></tr><tr><td>阿里</td><td>蚂蚁</td><td>电话</td><td>2</td><td>3-13/19</td></tr><tr><td>腾讯</td><td>TEG</td><td>电话</td><td>1</td><td>3-22</td></tr><tr><td>携程</td><td>旅游部</td><td>线下</td><td>1</td><td>3-24</td></tr><tr><td>搜狗</td><td>社区搜索</td><td>视频</td><td>1</td><td>3-27</td></tr><tr><td>链家</td><td>-</td><td>线下</td><td>2</td><td>3-28</td></tr><tr><td>腾讯</td><td>QQ 钱包</td><td>电话+线下</td><td>3</td><td>3-29/4-17</td></tr><tr><td>头条</td><td>PGC</td><td>视频</td><td>3</td><td>3-31</td></tr><tr><td>作业帮</td><td>未知</td><td>线下</td><td>1</td><td>4-4</td></tr><tr><td>京东</td><td>无界零售</td><td>线下</td><td>2</td><td>4-20</td></tr><tr><td>百度</td><td>-</td><td>视频</td><td>3</td><td>4-22</td></tr><tr><td>猿辅导</td><td>-</td><td>视频</td><td>1</td><td>4-25</td></tr><tr><td>阿里</td><td>-</td><td>视频</td><td>2</td><td>5-27</td></tr></tbody></table><h2 id="面试记录"><a href="#面试记录" class="headerlink" title="面试记录"></a>面试记录</h2><h3 id="腾讯一面(腾讯云)"><a href="#腾讯一面(腾讯云)" class="headerlink" title="腾讯一面(腾讯云)"></a>腾讯一面(腾讯云)</h3><ol><li>没有自我介绍,直接开始问基础</li><li>es6, <code>let</code> 和 <code>var</code> 的区别</li><li>箭头函数,<code>this</code> 指针</li><li><code>null</code> 和 <code>undefined</code> 的区别</li><li>把字符型数字转换成数字,都有哪些方法</li><li><code>call</code> 和 <code>apply</code> 的区别</li><li><code>Array</code> 都有哪些方法</li><li>如何复制对象,深拷贝/浅拷贝,如何复制数组</li><li>浏览器端都有什么实现异步的操作,nodejs 端又有哪些<ul><li><code>setTimeout</code>,<code>setInternal</code>,<code>Promise</code>,<code>async</code>/<code>await</code>,<strong>requestAnimation</strong>(原理)</li><li><strong>process.nextTick</strong>,…</li></ul></li><li><code>Promise</code> 和 <code>setTimeout</code> 的区别,执行优先级</li><li>html5 的新特性, perform</li><li>如何查询 dom 元素,如何添加 dom 元素</li><li>重绘和重排,如何避免重排</li><li>web 安全,sql 注入,xss,csrf,如何防止</li><li>css 都有哪些选择器,它们的优先级(id,类,tag…)</li><li><a href="https://www.renfei.org/blog/html5-introduction-3-history-api.html" target="_blank" rel="noopener">history</a>的实现方式</li><li>react 的生命周期</li><li>js 事件捕获和冒泡,如何阻止</li><li>如何阻止默认行为(<code>e.preventDefault</code>),IE 在这方面有何区别</li><li>跨域的实现方式,简述 jsonp、cors</li><li><strong>浏览器缓存机制</strong></li><li><strong>http2</strong> 的新特性</li><li>https 与 http 的区别</li><li>http 状态码,304,403</li><li>sql 查询的左连接和右连接有何区别</li><li>看过什么源码,学习前端的方式有哪些</li></ol><h3 id="阿里(蚂蚁金服)"><a href="#阿里(蚂蚁金服)" class="headerlink" title="阿里(蚂蚁金服)"></a>阿里(蚂蚁金服)</h3><h4 id="一面"><a href="#一面" class="headerlink" title="一面"></a>一面</h4><ol><li>自我介绍</li><li>挑一个印象最深的项目介绍一下</li><li>在其中负责什么角色</li><li>有什么技术难点</li><li>题目:npm 本地化,如给定 100 个 npm 包名,如何下载所有的依赖包(先解析依赖,缓存,并发 )</li><li>前后端数据交互的方法</li><li>Git <code>merge</code> 和 <code>rebase</code> 有什么区别,各自的适用场景,如果有一个主分支和两个 checkout 出的功能分支,一个先合并,另一个应该用 <code>merge</code> 还是 <a href="https://github.com/geeeeeeeeek/git-recipes/wiki/5.1-%E4%BB%A3%E7%A0%81%E5%90%88%E5%B9%B6%EF%BC%9AMerge%E3%80%81Rebase-%E7%9A%84%E9%80%89%E6%8B%A9" target="_blank" rel="noopener"><code>rebase</code></a></li><li>Webpack、Gulp、Grunt 的区别,为什么要用这些东西</li><li><code>call</code>,<code>bind</code>,<code>apply</code> 的区别及为什么要用这些</li><li>CSS <code>position</code> 的属性值及各自含义</li><li>React render 如果<code><A><B/></A></code>,<code>A</code> 的 <code>props</code> 发生变化,<code>B</code> 是否会 <code>rerender</code>,如何避免</li><li>开放性问题:如何看待前端,为什么选择前端</li><li>开放性问题:平时学习前端的方式</li></ol><h4 id="二面"><a href="#二面" class="headerlink" title="二面"></a>二面</h4><ol><li>自我介绍</li><li>项目技术栈</li><li>项目技术难点,如何解决的</li><li>dva 中为什么用 <code>generator</code>/<code>yield</code> 而不是 <code>async</code>/<code>await</code></li><li>vue / vuex 相关问题,有没有用过 vuex 插件</li><li>有没有写过自动化发布测试的代码</li><li>最近看的技术文章,详细说一下</li></ol><h3 id="腾讯一面(TEG)"><a href="#腾讯一面(TEG)" class="headerlink" title="腾讯一面(TEG)"></a>腾讯一面(TEG)</h3><ol><li>自我介绍</li><li>项目介绍</li><li>项目负责内容,技术难点,选型理由</li><li>Webpack、Gulp</li><li>React 自己封装过的组件</li><li>Web 安全问题及应对方法</li><li>Spring 相关</li><li>有没有看过 Spring 源码</li><li>Servlet + JSP 存在的问题</li><li>项目首页加载时间,太慢存在的问题,如何优化</li><li>跨域,JSONP,如何支持 PUT 方法(Spring 配置响应头)</li></ol><h3 id="搜狗一面(社区搜索)"><a href="#搜狗一面(社区搜索)" class="headerlink" title="搜狗一面(社区搜索)"></a>搜狗一面(社区搜索)</h3><ol><li>自我介绍</li><li>项目难点介绍</li><li>jQuery 链式调用</li><li><code>['1', '10', '100'].map(parseInt)</code></li><li>组合继承(<code>Animal<-Cat</code>, 主要考察普通原型继承 <code>constructor</code> 被覆盖)</li><li>React 和 Vue 的区别</li><li>Webpack 了解多少</li><li>React 和 Vue 是如何实现解析 <code>.jsx</code> 和 <code>.vue</code> 的</li></ol><h3 id="链家网"><a href="#链家网" class="headerlink" title="链家网"></a>链家网</h3><h4 id="一面-1"><a href="#一面-1" class="headerlink" title="一面"></a>一面</h4><ol><li>DOM0/1/2/3 的事件使用区别,捕获和冒泡</li><li>string 如何拼接</li><li>写一个事件代理</li><li>写一个布局的 css,实现水平和垂直居中</li><li>重绘和重排</li><li><code>arguments</code> 的 <code>callee</code> 和 <code>caller</code></li><li>简单说了项目用到的技术</li><li>url 的组成部分,并且改变是否会引起页面刷新</li><li>history 和 hashtag 在 SPA 中的应用</li><li>平时怎么学习 js 的</li></ol><h4 id="二面-1"><a href="#二面-1" class="headerlink" title="二面"></a>二面</h4><ol><li>项目中遇到的难点</li><li>移动端 h5 中如何识别手机设备信息,<a href="https://github.com/joyqi/mobile-device-js" target="_blank" rel="noopener">查到的一种方法</a></li><li>一个数组,找出其中重复次数大于 2 的元素的个数</li></ol><h3 id="腾讯(QQ-钱包)"><a href="#腾讯(QQ-钱包)" class="headerlink" title="腾讯(QQ 钱包)"></a>腾讯(QQ 钱包)</h3><h4 id="一面-2"><a href="#一面-2" class="headerlink" title="一面"></a>一面</h4><ol><li>自我介绍</li><li>聊项目</li><li>问基础</li><li>闭包</li><li>DOM 事件三个阶段</li><li>Web 安全,如何防范</li><li>前后端数据通讯方式</li><li>浏览器输入 url 之后…</li><li>如何突破浏览器请求并发限制</li><li><code>setTimeout</code> 和 <code>requestAnimationFrame</code> 的区别</li><li>Http 2 如何实现多路复用</li><li>es6 的 <code>let</code> 和 <code>const</code>,和 <code>var</code> 有什么区别</li><li>React 和 Vue 的异同点</li><li>如何实现事件代理</li><li>什么是执行上下文</li><li>算法:斐波那契数列</li><li>es6 箭头函数有何不同</li></ol><h4 id="二面(线下)"><a href="#二面(线下)" class="headerlink" title="二面(线下)"></a>二面(线下)</h4><ol><li>自我介绍</li><li><code>setTimeout</code> 和 <code>setInterval</code> 和 <code>requestAnimationFrame</code></li><li>重排/重绘,及如何避免</li><li>优化:动画掉帧/卡顿如何优化</li><li>优化:一个页面全是图片,有很多,如何优化</li><li>优化:页面加载如何优化</li><li>了解 Service Worker 吗,和 PWA 有什么关系</li><li>脚本加载方式 <code>async</code> 和 <code>defer</code> 的区别</li><li>Web Worker 使用场景</li><li>双向绑定是如何实现的</li><li>看过 React 和 Vue 源码吗,哪部分</li><li>写博客吗</li><li>有没有开源的东西</li></ol><h4 id="三面(线下)"><a href="#三面(线下)" class="headerlink" title="三面(线下)"></a>三面(线下)</h4><ol><li>自我介绍</li><li>项目介绍,技术难点,解决方案</li><li>闭包</li><li>Webpack、Gulp、Grunt 区别</li><li>最近学习的技术</li><li>Linux 了解吗,bash</li><li>zookeeper 一致性怎么实现的</li><li>为什么用 Oracle / Mysql / Mongodb 等数据库</li><li>mongodb 数据太大内存放不下怎么办</li><li>Web 安全及在项目中如何实践的</li><li>移动端如何适配</li><li>开发过微信小程序吗</li><li>React / Vue 在项目中的实践</li><li>Nodejs 了解吗</li><li>解决过浏览器兼容性问题吗</li><li>大数据/高并发等场景下的性能优化(这块很弱)</li><li>开放性问题:淘宝和京东是如何盈利的</li><li>开放性问题:如果一个城市要建加油站,会如何考虑</li><li>开发性问题:全世界人喝的啤酒能否灌满青海湖</li></ol><h3 id="今日头条"><a href="#今日头条" class="headerlink" title="今日头条"></a>今日头条</h3><h4 id="一面-3"><a href="#一面-3" class="headerlink" title="一面"></a>一面</h4><ol><li>实现一个左边定宽。右边自适应的布局</li><li>原生 <code>XMLHttpRequest</code> 怎么使用</li><li><code>x => x</code>,<code>x => {x}</code>,<code>x => ({x})</code>,分别以参数 1 调用,输出是什么</li><li><strong>算法:求一个二叉树的深度</strong></li><li>纯 CSS 实现一个三角形</li><li>上传文件 <code>FormData</code>,还有什么 MIME 类型</li><li>事件代理</li><li>捕获、冒泡</li><li>项目中的难点</li><li><code>async</code>/<code>defer</code> 的区别</li><li>微信网页版登录如何实现的</li></ol><h4 id="二面-2"><a href="#二面-2" class="headerlink" title="二面"></a>二面</h4><ol><li>自我介绍</li><li>项目难点</li><li>React v-dom</li><li><strong>算法:驼峰命名的字符串转换为一个连字符命名的字符串</strong></li><li><code>cookie</code> 和 <code>session</code> 的区别,<code>http-only</code></li><li>React 组件生命周期</li><li>Layout(reflow) 和 Paint(repaint),分别如何优化</li><li>前后端通信方式</li><li>DNS 解析过程</li><li>项目部署方式</li><li><strong>算法:实现一个图的 <code>getDepth(start, depth)</code>,找出起点开始深度为 <code>depth</code> 的点集合</strong></li></ol><h4 id="三面"><a href="#三面" class="headerlink" title="三面"></a>三面</h4><ol><li>自我介绍</li><li><strong>算法:dijkstra</strong></li><li>业务逻辑 / 业务抽象 / 现有技术实现,从这三个层面说一下自己的经验</li><li>有什么让你自豪的项目</li><li>写过 webpack 插件吗</li></ol><h3 id="作业帮一面"><a href="#作业帮一面" class="headerlink" title="作业帮一面"></a>作业帮一面</h3><ol><li>画一个布局: <code><div class="A"><div class="B"></div></div></code>, <code>.A {width: 100px; height: 100px; margin: 50px;} .B {width: 50px; height: 50px; margin: 100px;}</code></li><li>左右定宽,中间自适应的布局</li><li><code>alert(a); var a = 12; function a() { return a; }</code> 的输出结果</li><li>JSON 对象转 JSON 字符串</li><li>两个有序数组,不使用循环实现归并</li><li>两个数组,找出其中交集的唯一元素,如<code>[1,1,2,3],[1,2]</code> => <code>[1,2]</code></li></ol><h3 id="京东(无界零售)一二面"><a href="#京东(无界零售)一二面" class="headerlink" title="京东(无界零售)一二面"></a>京东(无界零售)一二面</h3><ol><li>项目介绍</li><li>画项目页面示意图并介绍</li><li>jQuery 和 React、Vue 的区别</li><li>Vue 组件的生命周期</li><li>Vue <code>computed</code> 和 <code>watch</code> 的区别</li><li><code>computed</code> 是如何实现的</li><li>Webpack、Gulp、Grunt 的区别</li><li>如何实现一个树形组件(懒加载/性能)</li><li>CSS 如何实现三角形</li><li>React/Vue DOM-diff 算法</li><li>React 和 Vue 是如何实现的,有何优点</li><li>缓存</li><li>如何使 CDN 上的缓存失效</li></ol><h3 id="百度"><a href="#百度" class="headerlink" title="百度"></a>百度</h3><h4 id="一面-4"><a href="#一面-4" class="headerlink" title="一面"></a>一面</h4><ol><li>http 常用状态</li><li><code>get</code> <code>post</code> 的区别</li><li>前端存储</li><li><code>localStorage</code> 能存储对象数据吗</li><li>语义化标签/好处</li><li>如何阻止 <code>a</code> 标签跳转</li><li>隐藏页面元素的方法</li><li>css 实现三角形</li><li>数组添加、删除、替换元素</li><li>事件代理</li><li>同源策略</li><li>跨域解决方案</li><li><code>jsonp</code> 原理</li><li>js 原生动画</li><li>es6 语法用过哪些</li><li><code>const</code> 和 <code>var</code> 区别</li><li>箭头函数的 <code>this</code></li><li>如何避免嵌套回调</li><li><code>Promise.all</code> (参数是什么,返回和参数一致吗)</li><li>编写函数检验是否为数组</li><li>写个正则校验 <a href="mailto:`xx@baidu.com" target="_blank" rel="noopener">`xx@baidu.com</a>`</li><li>nodejs 用过吗</li><li><code>require</code> 是如何找模块的</li><li>nodejs 子进程是什么原理</li><li>了解的前端框架、类库,优缺点</li><li>react 中父子/同级组件传递数据</li><li>diff 策略</li><li>生命周期</li><li>发请求在哪个周期</li><li>工程化工具</li><li>百度开源 FIS 了解吗</li><li>项目周期一般多久/多少人参与</li><li>开发过 SPA 吗,好处是什么</li><li>代码调试思路</li><li>学习新技术的途径</li></ol><h4 id="二面-3"><a href="#二面-3" class="headerlink" title="二面"></a>二面</h4><ol><li>自我介绍</li><li>项目介绍</li><li>Vue 的 <code>vue-loader</code> 是做什么的</li><li><code>computed</code> 是如何实现的</li><li>编程:实现一个函数 <code>getTop3Tag</code> 获取当前页面内出现次数最多的 <code>3</code> 个标签名称</li><li>编程:实现一个函数 <code>getQuery</code> 获取并解析当前页面的查询字符串</li><li>编程:实现一个函数 <code>log</code>,能够在控制台输出内容时在前面加一个 <code>'mylog:'</code></li><li>读程:各种循环 + <code>setTimeout</code> 的输出,就是考察循环中异步的闭包,最后一个加了 <code>Promise</code>,有一段答错了(见下面的代码块)</li><li>了解移动端开发吗(说不了解,只做过微信公众号里的页面开发)</li><li><code>weui</code> 的 <code>checkbox</code> 那种开关按钮是如何实现的</li><li>平时开发用什么操作系统(Window/Linux)</li><li>了解 Linux 系统吗,都知道什么</li><li>两列布局如何实现,左侧定宽,右侧自适应(双飞翼和圣杯)</li><li>CSS 常用选择器及其优先级</li></ol><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < <span class="number">5</span>; i++) {</span><br><span class="line"> setTimeout(</span><br><span class="line"> (<span class="function"><span class="keyword">function</span>(<span class="params">i</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(i);</span><br><span class="line"> })(i),</span><br><span class="line"> i * <span class="number">1000</span>,</span><br><span class="line"> );</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="三面-1"><a href="#三面-1" class="headerlink" title="三面"></a>三面</h4><ol><li>介绍一个项目</li><li>项目难点及如何解决的</li><li>如何看待前端</li><li>如何学习新技术</li><li>最近有了解到什么新技术</li><li>有什么兴趣爱好,如何平衡工作和生活</li><li>如何看待 <code>native</code> 开发和 <code>hybrid</code> 开发</li></ol><h3 id="猿辅导一面"><a href="#猿辅导一面" class="headerlink" title="猿辅导一面"></a>猿辅导一面</h3><ol><li>自我介绍</li><li>项目介绍,难点</li><li>React、Vue、Angular 的区别</li><li>Vue 双向绑定如何实现的</li><li>Spring Boot Data Rest 权限是如何控制的</li><li>编程:<code>"a bc d"</code> -> <code>"a1bc2d"</code></li><li>编程:<code>"todAY baR"</code> -> <code>"rab YadoA"</code></li><li>编程:已有<code>fetchUrl(url, callback)</code>,编写<code>batchFetchUrl(urlList, callback)</code></li></ol><h3 id="阿里一面"><a href="#阿里一面" class="headerlink" title="阿里一面"></a>阿里一面</h3><ol><li>自我介绍</li><li>Promise</li><li><code>async</code>/<code>await</code></li><li>阿里的前端开源产品有哪些了解</li><li>飞冰</li><li>浏览器工作原理</li><li>rn 的架构</li><li>weex 中支持 rn 的原理</li></ol><h2 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h2><p>问题偏好一般也会跟简历内容有关,尤其是项目,要注意从背景、问题、对比方案、解决方案、选择理由、使用效果等几方面来说。</p><h3 id="腾讯"><a href="#腾讯" class="headerlink" title="腾讯"></a>腾讯</h3><p>特别喜欢问优化,尤其是 Web 图片优化。需要对缓存,http2,cdn 等特别了解。熟悉前端优化的常用手段等。</p><h3 id="阿里"><a href="#阿里" class="headerlink" title="阿里"></a>阿里</h3><p>偏向问工程化,工具链,项目难度和解决方案等。</p><h3 id="百度-1"><a href="#百度-1" class="headerlink" title="百度"></a>百度</h3><p>非常注重基础,问的很细。</p><h3 id="今日头条-1"><a href="#今日头条-1" class="headerlink" title="今日头条"></a>今日头条</h3><p>每面都有两个算法题,前端的算法到简单 dp 已经封顶了,不会特别难。大多是跟数据结构有关,尤其是二叉树。</p><h2 id="学习参考链接"><a href="#学习参考链接" class="headerlink" title="学习参考链接"></a>学习参考链接</h2><ul><li><a href="https://segmentfault.com/a/1190000012001017" target="_blank" rel="noopener">鸟瞰前端 , 再论性能优化</a></li><li><a href="http://sheilacat.github.io/repaint-and-reflow/" target="_blank" rel="noopener">重绘与重排</a></li><li><a href="http://www.ruanyifeng.com/blog/2015/09/web-page-performance-in-depth.html" target="_blank" rel="noopener">网页性能管理详解</a></li><li><a href="https://juejin.im/post/5aa7d82c6fb9a028c522de43" target="_blank" rel="noopener">几道JS代码手写题以及JavaScript数据结构与算法资源分享</a></li><li><a href="https://h5bp.github.io/Front-end-Developer-Interview-Questions/" target="_blank" rel="noopener">前端面试问题集锦</a></li><li><a href="https://github.com/parro-it/awesome-micro-npm-packages" target="_blank" rel="noopener">awesome-micro-npm-packages</a></li><li><a href="https://github.com/tc39/ecma262" target="_blank" rel="noopener">ecma262</a></li><li><a href="https://www.jianshu.com/p/1f32120a503b" target="_blank" rel="noopener">CSS实现三角形</a></li><li><a href="https://github.com/markyun/My-blog/tree/master/Front-end-Developer-Questions/Questions-and-Answers" target="_blank" rel="noopener">前端开发面试题</a></li><li><a href="https://leohxj.gitbooks.io/front-end-database/content/" target="_blank" rel="noopener">前端工程师手册</a></li><li><a href="https://segmentfault.com/a/1190000008595101" target="_blank" rel="noopener">js 异步方法的优先级</a></li><li><a href="https://github.com/camsong/blog/issues/9" target="_blank" rel="noopener">JavaScript 浮点数陷阱及解法</a></li><li><a href="http://imweb.io/topic/55c6f9bac222e3af6ce235b9" target="_blank" rel="noopener">缓存策略</a></li><li><a href="http://harttle.land/2015/07/31/javascript-event.html" target="_blank" rel="noopener">DOM 事件</a></li><li><a href="http://huang-jerryc.com/2017/02/28/gulp-base/" target="_blank" rel="noopener">Gulp 基础与原理</a></li></ul>]]></content>
<summary type="html">
<p>转眼到了研二找实习工作的时候,因为项目的原因,并没有好好复习,从 3 月初开始准备投递简历到 5 月底入职实习公司,实在是非常累同时也收获很大的一段时间。</p>
</summary>
<category term="随笔" scheme="http://muxfe.github.io/categories/%E9%9A%8F%E7%AC%94/"/>
<category term="interview" scheme="http://muxfe.github.io/tags/interview/"/>
<category term="面试" scheme="http://muxfe.github.io/tags/%E9%9D%A2%E8%AF%95/"/>
<category term="春招" scheme="http://muxfe.github.io/tags/%E6%98%A5%E6%8B%9B/"/>
<category term="实习" scheme="http://muxfe.github.io/tags/%E5%AE%9E%E4%B9%A0/"/>
</entry>
<entry>
<title>2017 年终总结</title>
<link href="http://muxfe.github.io/2018/01/01/2017-review/"/>
<id>http://muxfe.github.io/2018/01/01/2017-review/</id>
<published>2018-01-01T03:03:20.000Z</published>
<updated>2018-09-27T12:20:48.921Z</updated>
<content type="html"><![CDATA[<p>转眼研究生学业过半,马上就要去找实习、找工作,回想两年前也是这个时候,觉得自己技术能力一片空白,只有一些玩具性质的学习项目,没有竞赛等亮眼的简历条目。</p><p>而今又过了两年,有成长也有思考,自身能力提升的速度跟技术发展速度相比还是小巫见大巫。负责开发的项目多了,框架使用多了,也做了一些技术之外的事情,总体还是对自己的改变感到欣慰。</p><a id="more"></a><h2 id="项目"><a href="#项目" class="headerlink" title="项目"></a>项目</h2><p>个人导师项目比较多,研一到研二的变化就是从做部分项目到负责自己的项目。年初的三车项目,年中的警务大数据重构及文档格式检查工具的收尾,年末的桥梁检测系统,每一次都在更进一步。</p><h3 id="三车系统"><a href="#三车系统" class="headerlink" title="三车系统"></a>三车系统</h3><p>三车项目在实验室已经做了超过 3 年,年初时已基本上线第二版,只包含后端部分。由于甲方前端调整,年初移交了前端网页及 SpringMVC 部分,需要快速上手修改及添加新功能。在这个项目中经验式地学到了 SpringMVC 风格的 JavaEE 写法,没有从书本或官网文档学习,直接从项目源码学习并修改。总体来说,接过来的前端代码比较粗放,亟需重构和简化,然而由于项目过于庞大、甲方需求过于急促,所以直到年底这一需求才被提上日程,重构方案应该会写在明年的年终总结里吧。</p><h3 id="警务大数据"><a href="#警务大数据" class="headerlink" title="警务大数据"></a>警务大数据</h3><p>已经做了一年的项目,类似三车,我在其中主要做了前端部分的重构,从 Servelet + JSP 技术栈转为 SpringBoot + React。重构过程中学习了 React 技术栈。我的前端学习路线是 <code>jQuery -> Angular1 -> React -> Vue</code>,初次接触 React 着实花了很长时间理解和适应。组件生命周期,Redux 单向数据流,跟 Angular1 相比没有了双向绑定和自由使用第三方库,初期还是很痛苦的。但随着整体技术栈的其他优点,渐渐地也喜欢上了这样的方式。热替换、ES6 语法糖、以及 Webpack 的按需打包等等,要比 Angular1 混合 jQuery,再加 gulp、grunt 打包便利得多。</p><h3 id="文档格式检查工具"><a href="#文档格式检查工具" class="headerlink" title="文档格式检查工具"></a>文档格式检查工具</h3><p>研一开始中途接的项目,已经进行了一大半,是一个用 C# 程序自动检测并报告 Word 文档中的错误及自动修复错误的工具,我在其中帮助修改其 Web 端服务,主要面向 C# 端做用户交互接口和 Oracle 存储、统计。使用了 JavaEE + Angular1 技术栈,JavaEE 部分纯用 Servlet + MVC 模式,没有使用其他框架,这让我的开发繁琐之余也学到了一些代码重构的思路,基于 DRY 原则,在项目中几乎每次重新开始都需要重构一次。这个项目终于在 17 年验收成功结束了。</p><h3 id="桥梁检测系统"><a href="#桥梁检测系统" class="headerlink" title="桥梁检测系统"></a>桥梁检测系统</h3><p>年底实验室接的一个新项目,我在其中做 Team Leader。老实说,这是个很难的工作,需要设计整体架构,做技术攻关,协调沟通等等,对我来说是个挑战。这个项目涉及很多桥梁领域知识,难度不大,但工作繁重,有很大的专业知识壁垒,涉及大量不同桥型、构件及评估统计信息。</p><p>有了以前的项目经验积累,直接使用了 SpringBoot + Jpa + Vue + Element-UI 的技术栈,前后端分离开发,后端工作量骤减,前端得益于于 Vue 及 Vuex 的便利,在实现上没有遇到什么大难题。这个项目还包含一个运行在平板上的安卓端 app,有两个同学开发安卓,由于一开始没有使用 MVVM 模式的框架,虽然界面开发速度很快,但在需要集成时就变得捉襟见肘。</p><p>为了跟进安卓端进度,我简单学习了一周的安卓开发,跟大家商定选择了一个相对容易上手的开发脚手架,<a href="https://github.com/goldze/MVVMHabit" target="_blank" rel="noopener">MVVMHabit</a>,主要集成了网络请求和 Data Binding,联调和集成比较方便。在 app 端遇到一个技术难题,是关于甲方提出的一个绘制病害示意图(矢量图)的需求。为了实现坐标轴的缩放和按比例绘制图形的两方面需求,我找了一个基于安卓端的可视化库,<a href="https://github.com/PhilJay/MPAndroidChart" target="_blank" rel="noopener">MPAndroidChart</a>。使用中还遇到很多问题,按下不表。目前这个项目仍处于开发阶段。</p><h3 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h3><p>参与上述项目之余,我还大大小小参与了一些其他项目,属于中途做技术实现工作,仅负责其中一小部分,有些也学到不少东西。</p><p>其中之一就是百度地图 Web 端的离线化,实现普通地图和卫星地图 + 路网的瓦片图离线化及相关功能(信息窗口,绘图等)。关于实现还新开了一个 <a href="https://github.com/muxfe/bmap-offline-for-web" target="_blank" rel="noopener">repo</a> 记录这项工作,以及用<a href="https://github.com/muxfe/BaiduMap_tiles" target="_blank" rel="noopener">爬虫</a> 快速下载百度瓦片图。</p><p>在微信小程序刚发布的时候,也趁热学习了一下小程序开发。当时小程序尚不允许个人开发者,所以仅在本地调试预览过效果。小程序刚出来时争论很大,但是开放十分缓慢,一开始几乎什么都不支持,入口很谨慎,生态非常封闭,这也是导致小程序开始备受争议的原因之一。现在小程序经过一年多时间的发展,感觉成熟和开放得多了,也在游戏、工具等方面获得了真正的便利。甚至支付宝跟风,还出现了一个“抄袭”事件。最近在做一个小程序的个人项目,类似 <a href="https://readhub.me/" target="_blank" rel="noopener">Readhub</a>,主要阅读关注的技术博客。</p><h2 id="参与比赛"><a href="#参与比赛" class="headerlink" title="参与比赛"></a>参与比赛</h2><p>本科的学业经历让我学到了竞赛的重要性,研究生便了解并参加了一些或大或小的比赛。</p><h3 id="华为算法大赛"><a href="#华为算法大赛" class="headerlink" title="华为算法大赛"></a>华为算法大赛</h3><p>第一个就是 5 月份华为举办的算法大赛,题目是一道综合性最优化问题,<a href="http://codecraft.huawei.com/home/detail" target="_blank" rel="noopener">大视频时代·布局</a>,关于服务器配置及满足低成本且满足所有终端用户的需求。由于实验室项目和其他个人原因,一个月的比赛时间一直拖到月底才开始查资料和写代码,用了遗传算法、蚁群、粒子群等等一言以蔽之的算法:瞎 JB 搜算法。主要分两步:第一步选择服务器个数;第二步:用最小费用最大流找出最优的服务器放置位置;第三步:不断重复前两步。结果当然是 GG。</p><h3 id="ThoughtWorks-结对编程"><a href="#ThoughtWorks-结对编程" class="headerlink" title="ThoughtWorks 结对编程"></a>ThoughtWorks 结对编程</h3><p>第二次是西安 ThoughtWorks 为了校招宣传而举办的一次小型结对编程比赛。大约 40 人随机组队,要求限时完成一个<a href="https://www.baidu.com/s?ie=UTF-8&wd=%E7%94%9F%E5%91%BD%E6%B8%B8%E6%88%8F" target="_blank" rel="noopener">生命游戏</a>的实现。由于刚学习了 React,就用了 Dva + React + Antd 的实现方案,实现过程中遇到了一个组件状态更新问题,向 ThoughtWorks 的工程师求助未果,最后勉强完成了。结果是一个纪念奖,因为使用了一套前端工程化的东西。最后反思一下,这个游戏没有交互,核心是生命演化的规则和逻辑,应该用简单的 React 状态组件就可以了,完全用不上 Redux 和 Stateless 组件。</p><h3 id="百度之星-·-AI"><a href="#百度之星-·-AI" class="headerlink" title="百度之星 · AI"></a>百度之星 · AI</h3><p>第三次是百度举办的<a href="http://star.baidu.com/index/developer" target="_blank" rel="noopener">百度之星开发者大赛</a>,用百度的交互理解平台实现一个特定应用场景的对话机器人,做出产品成果。一开始花了比较长的时间理解百度出的<a href="http://ai.baidu.com/docs#/UNIT-guide/top" target="_blank" rel="noopener">这个产品</a>的使用方法和设计思路,根据示例构建对话样本,训练和验证样本。终于得到一个和官方给的差不多的结果,过了预选赛。决赛需要做出产品,让我们非常纠结,处于 idea 枯竭状态,最后决定就用预选赛训练的电影场景示例做产品,产品形式用了相对 app 更简单的微信公众号,在公众号的对话框里进行交互,结果虽然成功了,但是这个产品实在是太草率了,毫无疑问地 GG。</p><h2 id="技术之外"><a href="#技术之外" class="headerlink" title="技术之外"></a>技术之外</h2><p>回顾 2017 年,写下上面那些文字,乍看之下,我觉得做得事情还蛮多的,但是还有很多其他时间被我用在编程之外,让我觉得我自己还有“压榨”空间。首先就是健身,年初换了居住环境后,从 Keep 到健身房,花的时间变少了,不过健身效率更高,还能解决洗澡问题。健身的目的之一就是希望自己以后不需要买《程序员颈椎康复指南》之类的书。下半年跟实验室的同学开始热衷于报团登山,登山的过程非常有意思,累并快乐着,尤其是登顶之后的感觉,非常开心。</p><p>读书明显减少,感觉自己读书太较真,不会速读。但是也读了几本觉得可以推荐的好书,如吴晓波老师的《跌荡一百年》系列,之前就看过他的《激荡三十年》系列,作为经济企业史通俗读物来看,是十分不错的。技术书籍读了《代码整洁之道》觉得不错,内容虽然是基于 Java 的,但是思想可以推及其他编程语言。终于在 Kindle 上读完了 《1984》,乌托邦三部曲第二部,令人细思极恐,不寒而栗的一本小说。</p><p>编程之余总是喜欢用第三个屏刷剧,很少看国产剧的我在 2017 看了不少优秀的国产剧,网剧如《毛骗》、《白夜追凶》,影视剧如《大明王朝 1566》,《人民的名义》。电影也是如此,《羞羞的铁拳》、《战狼 2》都是口碑票房双赢之作。</p><p>旅行去了贵州和重庆,出差去了南京,对这些城市感受都很不错。“山水公园省,多彩贵州风。” 黄果树瀑布,西江苗寨,镇远古镇,少数民族风很浓厚,商业化相比其他古镇还可以接受。重庆是一座有味道的城市,不管是从影视剧里,还是舌尖上的中国,都有股麻辣火锅味,真正吃过之后让人难以忘怀。南京的鸭肠、粉丝汤也都很不错。南方城市空气质量相对较高,蓝天白云,青山绿水,令人心驰神往。</p><h3 id="2017-小计"><a href="#2017-小计" class="headerlink" title="2017 小计"></a>2017 小计</h3><ul><li>读书:7 本</li><li>刷剧:79 部</li><li>GitHub:9 个新 repo</li><li>Keep:4300 分钟</li><li>扇贝单词:358 天</li><li>健身:105 次</li></ul><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>2017 感觉还是比较充实的,马上就要实习、找工作了,预感 2018 会更加忙碌和充实。希望找到不错的实习和工作。</p><p>以上。</p>]]></content>
<summary type="html">
<p>转眼研究生学业过半,马上就要去找实习、找工作,回想两年前也是这个时候,觉得自己技术能力一片空白,只有一些玩具性质的学习项目,没有竞赛等亮眼的简历条目。</p>
<p>而今又过了两年,有成长也有思考,自身能力提升的速度跟技术发展速度相比还是小巫见大巫。负责开发的项目多了,框架使用多了,也做了一些技术之外的事情,总体还是对自己的改变感到欣慰。</p>
</summary>
<category term="随笔" scheme="http://muxfe.github.io/categories/%E9%9A%8F%E7%AC%94/"/>
<category term="review" scheme="http://muxfe.github.io/tags/review/"/>
</entry>
<entry>
<title>百度地图 Web 端离线方案</title>
<link href="http://muxfe.github.io/2017/11/13/bmap-offline/"/>
<id>http://muxfe.github.io/2017/11/13/bmap-offline/</id>
<published>2017-11-13T03:03:20.000Z</published>
<updated>2018-12-05T02:13:26.651Z</updated>
<content type="html"><![CDATA[<p>今年实验室几个 web 项目都用到了百度地图服务,但部署环境无法访问外网,必须要对百度地图进行离线化处理。百度地图没有官方的 web 端离线方案,只能自己动手,丰衣足食。地图离线化不仅包含普通地图的瓦片图,还要求包括卫星图 + 路网,绘制图形等独立的 Library。</p><p>看了一下百度地图 js 压缩处理后的源码,可以说是非常不友好了,为了快速实现这个需求,尽可能少的修改百度 js 代码,方便以后升级或者禁用离线版,一个简单的思路是修改原始瓦片图请求为本地的离线地图库。</p><a id="more"></a><h2 id="背景知识"><a href="#背景知识" class="headerlink" title="背景知识"></a>背景知识</h2><p>电子地图主要是基于图层叠加进行绘制,从真实世界的物理建模到路网、建筑,再到服务标注。目前大多数互联网地图服务提供商都使用瓦片图的拼接来实现地理信息展示,每个缩放层级分辨率都不同,即不同的缩放层级,会把图层分成大小相同、数量不等的瓦片图。</p><p>地理位置信息使用经纬度坐标来描述,原理是对椭球型的地球进行墨卡托投影,这种投影是将三维地球空间映射到二维空间,且能保持任意两点间的夹角不变。</p><h3 id="经纬度坐标"><a href="#经纬度坐标" class="headerlink" title="经纬度坐标"></a>经纬度坐标</h3><p>国际标准的经纬度坐标是 <a href="http://gisgeography.com/wgs84-world-geodetic-system/" target="_blank" rel="noopener"><code>WGS84</code></a>,国内提供地理位置信息服务的公司使用的坐标体系都不尽相同。网上都存在不同坐标体系之间的相互转化,如 GoogleMap -> BaiduMap 等。</p><h2 id="核心库源码分析"><a href="#核心库源码分析" class="headerlink" title="核心库源码分析"></a>核心库源码分析</h2><p>Web 端百度地图的核心代码在 <code>BaiduApi_2.0.js</code> 中,主要实现了将 BMap 挂在 window 下,并添加一系列方法,和 AMD 模块加载。</p><p>绘图的核心代码在 <code>DrawingManager_1.4.js</code>,主要实现了绘制多边形、区域选择等功能。</p><h2 id="离线化"><a href="#离线化" class="headerlink" title="离线化"></a>离线化</h2><p>可选方案:</p><ol><li>leaflet + 百度/高德数据源</li><li>浏览器缓存</li><li>劫持请求到本地,缓存瓦片图【选用方案】</li></ol><p>其中 leaflet 方案需要较高的开发成本,而浏览器缓存在无网络的环境下又不可行,所以选用了劫持百度核心库请求的方案。</p><h3 id="瓦片图离线化"><a href="#瓦片图离线化" class="headerlink" title="瓦片图离线化"></a>瓦片图离线化</h3><p><a href="https://github.com/muxfe/BaiduMap_tiles" target="_blank" rel="noopener">瓦片图下载</a>工具在 fork 仓库的基础上加了下载卫星图和多线程模式,修改了下载路径和文件名等,为了和劫持的请求进行适配。</p><p>百度的瓦片图存储在多个 CDN 上,在核心代码里有一个简单的负载均衡策略,统一劫持改为离线模式。</p><h3 id="百度地图模块离线化"><a href="#百度地图模块离线化" class="headerlink" title="百度地图模块离线化"></a>百度地图模块离线化</h3><p>百度地图除核心库外,还有很多以模块化加载的代码,放在 try-catch 里进行 eval。包括版本声明、InfoWidnow、Marker 等等。</p><p>这部分直接下载相应模块代码保存在 getmodules。</p><p>其中有一个点是百度设计的模块会并行加载,如有时候是 <code>mapclick,marker...</code> 加载,有时候是单个文件加载,而且顺序不定。这里我用了一个对象保存下载时的模块名称,然后进行匹配当时的模块请求,发现只要包括一项就加载多模块文件,缺少的再单独加载。</p><h2 id="参考连接"><a href="#参考连接" class="headerlink" title="参考连接"></a>参考连接</h2><ul><li><a href="https://www.wikiwand.com/zh-hans/%E5%9C%B0%E7%90%86%E4%BF%A1%E6%81%AF%E7%B3%BB%E7%BB%9F" target="_blank" rel="noopener">地理信息系统</a></li><li><a href="http://cntchen.github.io/2016/05/09/%E5%9B%BD%E5%86%85%E4%B8%BB%E8%A6%81%E5%9C%B0%E5%9B%BE%E7%93%A6%E7%89%87%E5%9D%90%E6%A0%87%E7%B3%BB%E5%AE%9A%E4%B9%89%E5%8F%8A%E8%AE%A1%E7%AE%97%E5%8E%9F%E7%90%86/" target="_blank" rel="noopener">国内主要地图瓦片坐标系定义及计算原理</a></li><li><a href="https://github.com/CntChen/tile-lnglat-transform" target="_blank" rel="noopener">高德、百度、谷歌和腾讯地图的经纬度坐标与瓦片坐标的相互转换</a></li><li><a href="https://www.zhihu.com/question/21530085" target="_blank" rel="noopener">百度地图、高德地图的数据从哪里得到的?</a></li><li><a href="http://api.map.baidu.com/lbsapi/getpoint/index.html" target="_blank" rel="noopener">百度地图拾取坐标系统</a></li><li><a href="http://lbsyun.baidu.com/" target="_blank" rel="noopener">百度地图开放平台</a></li></ul>]]></content>
<summary type="html">
<p>今年实验室几个 web 项目都用到了百度地图服务,但部署环境无法访问外网,必须要对百度地图进行离线化处理。百度地图没有官方的 web 端离线方案,只能自己动手,丰衣足食。地图离线化不仅包含普通地图的瓦片图,还要求包括卫星图 + 路网,绘制图形等独立的 Library。</p>
<p>看了一下百度地图 js 压缩处理后的源码,可以说是非常不友好了,为了快速实现这个需求,尽可能少的修改百度 js 代码,方便以后升级或者禁用离线版,一个简单的思路是修改原始瓦片图请求为本地的离线地图库。</p>
</summary>
<category term="前端开发" scheme="http://muxfe.github.io/categories/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/"/>
<category term="前端" scheme="http://muxfe.github.io/tags/%E5%89%8D%E7%AB%AF/"/>
<category term="web" scheme="http://muxfe.github.io/tags/web/"/>
<category term="javascript" scheme="http://muxfe.github.io/tags/javascript/"/>
</entry>
<entry>
<title>hexo + fexo 搭建 GitHub-Pages 静态博客</title>
<link href="http://muxfe.github.io/2016/07/19/hexo-blog/"/>
<id>http://muxfe.github.io/2016/07/19/hexo-blog/</id>
<published>2016-07-19T05:50:00.000Z</published>
<updated>2018-09-27T09:01:19.212Z</updated>
<content type="html"><![CDATA[<h2 id="hexo-介绍"><a href="#hexo-介绍" class="headerlink" title="hexo 介绍"></a>hexo 介绍</h2><p>hexo 是一个使用 markdown 解析生成静态网页的框架,这样的框架还有 jekyll,前者基于 nodejs,后者基于 Ruby。但都使用 <code>.yml</code> 作为配置文件。之前用过 jekyll 搭建静态博客,但是在入门难易程度,包管理器生态环境和速度方面,貌似 hexo 更好一些。</p><p>hexo 默认使用 <a href="http://www.embeddedjs.com/" target="_blank" rel="noopener">ejs</a> 作为解析模板,默认 markdown 解析也与 GitHub 最为相似。书写,本地预览和部署到 GitHub repo 都非常方便。</p><a id="more"></a><h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><h3 id="安装-Git-Bash"><a href="#安装-Git-Bash" class="headerlink" title="安装 Git-Bash"></a>安装 Git-Bash</h3><ul><li>Win - <a href="https://git-scm.com/download/win" target="_blank" rel="noopener">download</a></li><li>Linux - <code>sudo apt-get install git</code></li></ul><p>在 Linux 上配置 Git 参考<a href="http://x-web.github.io/2015/11/21/using-git-on-ubuntu14/" target="_blank" rel="noopener">这里</a>.</p><h3 id="安装-Node"><a href="#安装-Node" class="headerlink" title="安装 Node"></a>安装 Node</h3><ul><li>Win - <a href="https://nodejs.org/en/download/" target="_blank" rel="noopener">download</a></li><li>Linux - <code>sudo apt-get install nodejs</code> or install <a href="https://github.com/creationix/nvm" target="_blank" rel="noopener">nvm</a></li></ul><p>查看 nodejs 和 npm 版本<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">node -v</span><br><span class="line">npm -v</span><br></pre></td></tr></table></figure></p><h3 id="安装-hexo"><a href="#安装-hexo" class="headerlink" title="安装 hexo"></a>安装 hexo</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> my-hexo-blog</span><br><span class="line">npm install hexo --save</span><br></pre></td></tr></table></figure><p>由于网络环境的原因,现在 npm 安装也非常慢,可以使用淘宝的 npm 镜像 - cnpm 来更快地安装包。参考<a href="https://npm.taobao.org/" target="_blank" rel="noopener">这里</a>.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm install -g cnpm --registry=https://registry.npm.taobao.org</span><br><span class="line">cnpm install hexo</span><br></pre></td></tr></table></figure><h2 id="测试运行-hexo"><a href="#测试运行-hexo" class="headerlink" title="测试运行 hexo"></a>测试运行 hexo</h2><h3 id="设置-hexo-运行脚本"><a href="#设置-hexo-运行脚本" class="headerlink" title="设置 hexo 运行脚本"></a>设置 hexo 运行脚本</h3><p>本人不太喜欢全局安装 npm 包,所以想要使用局部安装的 hexo,需要运行 <code>./node_modules/.bin/hexo</code>,但是这样很麻烦,可以在项目根目录中写相应的脚本来更好的使用 hexo 命令。</p><h4 id="BAT"><a href="#BAT" class="headerlink" title="BAT"></a>BAT</h4><p>在项目根目录下创建 <code>hexo.bat</code> 文件,内容如下:</p><figure class="highlight bat"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">@<span class="built_in">ECHO</span> off</span><br><span class="line"><span class="built_in">SET</span> PARAM=</span><br><span class="line">:LOOP</span><br><span class="line"> <span class="keyword">IF</span> [%<span class="number">1</span>]==[] <span class="keyword">GOTO</span> END</span><br><span class="line"> <span class="built_in">SET</span> PARAM=<span class="variable">%PARAM%</span> "%<span class="number">1</span>"</span><br><span class="line"> <span class="built_in">shift</span></span><br><span class="line"> <span class="keyword">GOTO</span> LOOP</span><br><span class="line">:END</span><br><span class="line">node_modules\.bin\hexo <span class="variable">%PARAM%</span></span><br></pre></td></tr></table></figure><h4 id="BASH"><a href="#BASH" class="headerlink" title="BASH"></a>BASH</h4><p>在项目根目录下创建 <code>hexo</code> 文件,内容如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"node/node"</span> <span class="string">"./node_modules/.bin/hexo"</span> <span class="string">"<span class="variable">$@</span>"</span></span><br></pre></td></tr></table></figure><p>这样就可以在项目根目录下使用局部 hexo 命令了。</p><h3 id="初始化项目"><a href="#初始化项目" class="headerlink" title="初始化项目"></a>初始化项目</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo init</span><br></pre></td></tr></table></figure><p>初始化完成后,会形成下面的 hexo 项目结构:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">./</span><br><span class="line">├─ public/ - 生成静态页面存放目录</span><br><span class="line">├─ source/ - md/css 等其他源文件</span><br><span class="line">│ ├─ _drafts/ - 草稿 hexo new draft <title></span><br><span class="line">│ ├─ _post/ - 文章 hexo new <title></span><br><span class="line">│ └─ .../</span><br><span class="line">├─ scaffolds/ - 脚手架,即新建文章(或其他类型)时初始化的模板</span><br><span class="line">├─ themes/</span><br><span class="line">│ ├─ landscape/ - 3.2.2 默认主题</span><br><span class="line">│ └─ .../</span><br><span class="line">├─ node_modules/</span><br><span class="line">├─ .deploy_git/ - 部署临时文件夹 hexo deploy</span><br><span class="line">├─ db.json - 本地 web 服务器使用的临时文件</span><br><span class="line">├─ _config.yml - hexo 配置文件</span><br><span class="line">└─ package.json - npm 包依赖描述文件</span><br></pre></td></tr></table></figure><h3 id="生成静态页面"><a href="#生成静态页面" class="headerlink" title="生成静态页面"></a>生成静态页面</h3><p>其中 public 目录存放 hexo 生成的静态页面。运行</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo generate</span><br></pre></td></tr></table></figure><p>会创建 public 目录并生成所有静态页面。</p><p>为了在本地预览,hexo 还提供了一个本地 web 服务器环境。运行</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo server</span><br></pre></td></tr></table></figure><p>运行成功后,通过访问 <a href="http://localhost:4000" target="_blank" rel="noopener">localhost:4000</a> 即可预览。</p><h2 id="使用-fexo-主题"><a href="#使用-fexo-主题" class="headerlink" title="使用 fexo 主题"></a>使用 fexo 主题</h2><h3 id="安装-fexo-主题"><a href="#安装-fexo-主题" class="headerlink" title="安装 fexo 主题"></a>安装 fexo 主题</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> my-hexo-blog/themes/</span><br><span class="line">git <span class="built_in">clone</span> https://github.com/forsigner/fexo.git</span><br></pre></td></tr></table></figure><h3 id="修改配置文件"><a href="#修改配置文件" class="headerlink" title="修改配置文件"></a>修改配置文件</h3><p>修改博客根目录下的 <code>_config.yml</code> 中的 <code>theme</code> 为 <code>fexo</code>.</p><p>配置 <code>themes/fexo/_config.yml</code> 参考<a href="http://forsigner.com/2016/03/10/fexo-doc-zh-cn/" target="_blank" rel="noopener">这里</a>.</p><h3 id="安装插件"><a href="#安装插件" class="headerlink" title="安装插件"></a>安装插件</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># rss 支持</span></span><br><span class="line">npm install hexo-generator-feed --save</span><br><span class="line"><span class="comment"># sitemap 支持</span></span><br><span class="line">npm install hexo-generator-sitemap --save</span><br><span class="line"><span class="comment"># search 支持</span></span><br><span class="line">npm install hexo-generator-search --save</span><br></pre></td></tr></table></figure><h3 id="在-fexo-中自定义样式"><a href="#在-fexo-中自定义样式" class="headerlink" title="在 fexo 中自定义样式"></a>在 fexo 中自定义样式</h3><p>fexo 的自定义样式由其配置文件 <code>fexo/_config.yml</code> 中的 <code>personal_style:</code> 设置。对应值的路径相对与 <code>my-hexo-blog/source/</code>,如设置 <code>personal_style: /css/custom.css</code>,则应该创建 <code>my-hexo-blog/source/css/custom.css</code> 文件,并在其中设置样式。</p><h3 id="其他不错的主题"><a href="#其他不错的主题" class="headerlink" title="其他不错的主题"></a>其他不错的主题</h3><ul><li><a href="https://github.com/steven5538/hexo-theme-athena" target="_blank" rel="noopener">athena</a> - <em><a href="http://steven5538.tw/" target="_blank" rel="noopener">demo</a></em></li><li><a href="https://github.com/iissnan/hexo-theme-next" target="_blank" rel="noopener">next</a> - <em><a href="http://heroicyang.com/" target="_blank" rel="noopener">demo</a></em></li><li><a href="https://github.com/lenbo-ma/hexo-theme-vno" target="_blank" rel="noopener">vno</a> - <em><a href="http://mlongbo.com/" target="_blank" rel="noopener">demo</a></em></li></ul><h2 id="第三方服务"><a href="#第三方服务" class="headerlink" title="第三方服务"></a>第三方服务</h2><h3 id="使用百度统计"><a href="#使用百度统计" class="headerlink" title="使用百度统计"></a>使用百度统计</h3><p>在<a href="http://tongji.baidu.com/" target="_blank" rel="noopener">百度统计</a>申请账号,拿到自己的 token,并将其填入 <code>fexo/_config.yml</code> 中的 <code>baidu_analytics:</code> 属性值。</p><h3 id="使用-Disqus-评论"><a href="#使用-Disqus-评论" class="headerlink" title="使用 Disqus 评论"></a>使用 Disqus 评论</h3><p>在<a href="https://disqus.com/" target="_blank" rel="noopener">DISQUS</a>注册,并申请自己的二级域名。在个人账户页面,<code>Setting -> Add Disqus To Site -> GET STARTED</code>,然后填写相应信息。将自己申请的 Disqus 二级域名填如 <code>fexo/_config.yml</code> 中的 <code>disqus_shortname:</code> 属性值。</p><p>也可以使用<a href="http://duoshuo.com/" target="_blank" rel="noopener">多说</a>评论,修改 <code>duoshuo_shortname:</code> 并注释 Disqus 即可。</p><h2 id="使用-GitHub-Pages-部署网站"><a href="#使用-GitHub-Pages-部署网站" class="headerlink" title="使用 GitHub Pages 部署网站"></a>使用 <a href="https://pages.github.com/" target="_blank" rel="noopener">GitHub Pages</a> 部署网站</h2><p>GitHub 提供免费的 300M 网站空间,使得开发者可以静态展示自己的项目或网站。要使用 GitHub Pages 功能,首先申请 GitHub 账号,然后创建一个公开项目 <code>[yourname].github.io</code>。</p><p>修改 <code>my-hexo-blog/_config.yml</code> 中的 <code>deploy</code> 属性;</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">deploy:</span></span><br><span class="line"><span class="attr"> type:</span> <span class="string">git</span></span><br><span class="line"><span class="attr"> repo:</span> <span class="attr">https://github.com/[yourname]/[yourname].github.io.git</span></span><br><span class="line"><span class="attr"> branch:</span> <span class="string">master</span></span><br><span class="line"><span class="attr"> message:</span> <span class="string">'update blog'</span></span><br></pre></td></tr></table></figure><p>设置好后,在根目录运行</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo deploy</span><br></pre></td></tr></table></figure><p>如果没有配置 ssh-key,需要输入 GitHub 的账号密码。</p><p>若不想使用 <code>hexo deploy</code> 命令,还可以自己 push <code>public/</code> 中的静态页面到 <code>[yourname].github.io.git</code> 代码仓库。可以先 clone 仓库到本地,然后拷贝其中的 <code>.git</code> 文件夹到 <code>my-hexo-blog/public/</code> 中,再使用 <code>git</code> 同步到远端库。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git add -A</span><br><span class="line">git commit -m <span class="string">"update my blog"</span></span><br><span class="line">git push</span><br></pre></td></tr></table></figure><h2 id="性能优化"><a href="#性能优化" class="headerlink" title="性能优化"></a>性能优化</h2><h3 id="gulp-压缩"><a href="#gulp-压缩" class="headerlink" title="gulp 压缩"></a>gulp 压缩</h3><p>安装 gulp 相关依赖包</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">npm install gulp --save</span><br><span class="line">npm install gulp-htmlclean --save</span><br><span class="line">npm install gulp-htmlmin --save</span><br><span class="line">npm install gulp-imagemin --save</span><br><span class="line">npm install gulp-minify-css --save</span><br><span class="line">npm install gulp-uglify --save</span><br></pre></td></tr></table></figure><p>编写 gulpfile.js 文件</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> gulp = <span class="built_in">require</span>(<span class="string">'gulp'</span>);</span><br><span class="line"><span class="keyword">var</span> minifycss = <span class="built_in">require</span>(<span class="string">'gulp-minify-css'</span>);</span><br><span class="line"><span class="keyword">var</span> uglify = <span class="built_in">require</span>(<span class="string">'gulp-uglify'</span>);</span><br><span class="line"><span class="keyword">var</span> htmlmin = <span class="built_in">require</span>(<span class="string">'gulp-htmlmin'</span>);</span><br><span class="line"><span class="keyword">var</span> htmlclean = <span class="built_in">require</span>(<span class="string">'gulp-htmlclean'</span>);</span><br><span class="line"><span class="keyword">var</span> imagemin = <span class="built_in">require</span>(<span class="string">'gulp-imagemin'</span>)</span><br><span class="line"><span class="comment">// 压缩 css</span></span><br><span class="line">gulp.task(<span class="string">'minify-css'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> gulp.src(<span class="string">'./public/**/*.css'</span>)</span><br><span class="line"> .pipe(minifycss())</span><br><span class="line"> .pipe(gulp.dest(<span class="string">'./public'</span>));</span><br><span class="line">});</span><br><span class="line"><span class="comment">// 压缩 html</span></span><br><span class="line">gulp.task(<span class="string">'minify-html'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> gulp.src(<span class="string">'./public/**/*.html'</span>)</span><br><span class="line"> .pipe(htmlclean())</span><br><span class="line"> .pipe(htmlmin({</span><br><span class="line"> removeComments: <span class="literal">true</span>,</span><br><span class="line"> minifyJS: <span class="literal">true</span>,</span><br><span class="line"> minifyCSS: <span class="literal">true</span>,</span><br><span class="line"> minifyURLs: <span class="literal">true</span>,</span><br><span class="line"> }))</span><br><span class="line"> .pipe(gulp.dest(<span class="string">'./public'</span>))</span><br><span class="line">});</span><br><span class="line"><span class="comment">// 压缩 js</span></span><br><span class="line">gulp.task(<span class="string">'minify-js'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> gulp.src(<span class="string">'./public/**/*.js'</span>)</span><br><span class="line"> .pipe(uglify())</span><br><span class="line"> .pipe(gulp.dest(<span class="string">'./public'</span>));</span><br><span class="line">});</span><br><span class="line"><span class="comment">// 压缩图片</span></span><br><span class="line">gulp.task(<span class="string">'images'</span>, <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> gulp.src(<span class="string">'./public/images/*.*'</span>)</span><br><span class="line"> .pipe(imagemin({</span><br><span class="line"> progressive: <span class="literal">true</span></span><br><span class="line"> }))</span><br><span class="line"> .pipe(gulp.dest(<span class="string">'./public'</span>))</span><br><span class="line">});</span><br><span class="line"><span class="comment">// 执行 gulp 命令时执行的任务</span></span><br><span class="line">gulp.task(<span class="string">'default'</span>, [</span><br><span class="line"> <span class="string">'minify-html'</span>,<span class="string">'minify-css'</span>,<span class="string">'minify-js'</span>,<span class="string">'images'</span></span><br><span class="line">]);</span><br></pre></td></tr></table></figure><p>新建 gulp.bat</p><figure class="highlight bat"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">@<span class="built_in">ECHO</span> off</span><br><span class="line"><span class="built_in">SET</span> PARAM=</span><br><span class="line">:LOOP</span><br><span class="line"> <span class="keyword">IF</span> [%<span class="number">1</span>]==[] <span class="keyword">GOTO</span> END</span><br><span class="line"> <span class="built_in">SET</span> PARAM=<span class="variable">%PARAM%</span> "%<span class="number">1</span>"</span><br><span class="line"> <span class="built_in">shift</span></span><br><span class="line"> <span class="keyword">GOTO</span> LOOP</span><br><span class="line">:END</span><br><span class="line">node_modules\.bin\gulp <span class="variable">%PARAM%</span></span><br></pre></td></tr></table></figure><p>压缩 <code>public/</code> 下的静态页面</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gulp <task></span><br></pre></td></tr></table></figure><p>p.s. 之前一直用 Grunt 做压缩,花了较长时间学习,积累经验,但是感觉理解还是不够,这次折腾发现 gulp 更容易上手和使用,<code>gulpfile.js</code> 可读性很高,简直相见恨晚。</p><h3 id="CDN-优化"><a href="#CDN-优化" class="headerlink" title="CDN 优化"></a>CDN 优化</h3><p>GitHub 提供的 web 服务是很好的,但是国内的网络环境使得访问 GitHub Pages 的速度惨不忍睹,提高访问速度的方法无外乎压缩源码、使用 CDN 等手段。上节试了压缩源码,但是性能提升十分有限。如果能把所需的所有 js/css/image 等文件以 CDN 方法部署,就能大大提高访问速度。hexo 目前还没有集成的方案,这方面还需要学习和研究,使用 CDN 优化网站访问速度。</p><h3 id="SEO-优化"><a href="#SEO-优化" class="headerlink" title="SEO 优化"></a>SEO 优化</h3><p>GitHub Pages 在 SEO 方面先天不足,由于百度不对其做索引,导致网站流量仅能通过有限的渠道被访问,也导致搭在 GitHub 上的博客大都无人问津。应该从两方面来提高网站流量,最主要的是提高内容质量,再一方面做好 SEO 优化。hexo 可以就有 seo 插件,生成 sitemap。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-generator-sitemap --save</span><br><span class="line">npm install hexo-generator-baidu-sitemap --save</span><br><span class="line">npm install hexo-generator-seo-friendly-sitemap --save</span><br></pre></td></tr></table></figure><h2 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h2><ul><li><a href="http://www.jianshu.com/p/465830080ea9" target="_blank" rel="noopener">HEXO + Github,搭建属于自己的博客</a></li><li><a href="http://x-web.github.io/2015/11/21/using-git-on-ubuntu14/" target="_blank" rel="noopener">在 Ubuntu 14 上使用 Git</a></li><li><a href="http://forsigner.com/2016/03/10/fexo-doc-zh-cn/" target="_blank" rel="noopener">fexo-doc</a></li><li><a href="http://www.tuicool.com/articles/rUrYfeB" target="_blank" rel="noopener">搭建 Hexo 博客–增强篇</a></li><li><a href="https://yq.aliyun.com/articles/8608" target="_blank" rel="noopener">Hexo折腾记——性能优化篇</a></li></ul>]]></content>
<summary type="html">
<h2 id="hexo-介绍"><a href="#hexo-介绍" class="headerlink" title="hexo 介绍"></a>hexo 介绍</h2><p>hexo 是一个使用 markdown 解析生成静态网页的框架,这样的框架还有 jekyll,前者基于 nodejs,后者基于 Ruby。但都使用 <code>.yml</code> 作为配置文件。之前用过 jekyll 搭建静态博客,但是在入门难易程度,包管理器生态环境和速度方面,貌似 hexo 更好一些。</p>
<p>hexo 默认使用 <a href="http://www.embeddedjs.com/" target="_blank" rel="noopener">ejs</a> 作为解析模板,默认 markdown 解析也与 GitHub 最为相似。书写,本地预览和部署到 GitHub repo 都非常方便。</p>
</summary>
<category term="前端开发" scheme="http://muxfe.github.io/categories/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/"/>
<category term="web" scheme="http://muxfe.github.io/tags/web/"/>
<category term="hexo" scheme="http://muxfe.github.io/tags/hexo/"/>
</entry>
<entry>
<title>Single Page Application - AngularJS</title>
<link href="http://muxfe.github.io/2016/07/13/spa-angularjs/"/>
<id>http://muxfe.github.io/2016/07/13/spa-angularjs/</id>
<published>2016-07-13T08:03:20.000Z</published>
<updated>2018-09-27T12:20:21.761Z</updated>
<content type="html"><![CDATA[<h1 id="Single-Page-Application-AngularJS"><a href="#Single-Page-Application-AngularJS" class="headerlink" title="Single Page Application - AngularJS"></a>Single Page Application - AngularJS</h1><p>最近半年做了不少单页面网站的开发,有静态也有动态的,主要基于 AngularJS(偶尔在我的 <a href="https://github.com/x-web/x-web.github.io" target="_blank" rel="noopener">blog</a> 中<br>用了 <a href="http://www.ractivejs.org/" target="_blank" rel="noopener">ractive</a>)。对这种重前端应用就着迷了,优点是前后端分工明确,高效(异步请求数据)且用户体验较好(没有频繁的页面跳转)。</p><p>没有任何框架能够适应一切场景。SPA 也有缺点,比如应用复杂代码量增加时,单页面应用就会有内存泄露等棘手问题,还有 SEO 优化等等问题。<br>SPA 适应的场景,如小型静态应用,与后台频繁交互(但不涉及重大安全问题)的应用等,我认为都是适合单页面应用的。</p><p>SPA 与 RESTful API 非常合适,只要确定接口规范,前后端开发就能较为独立地进行,前端通过 mock 异步数据,后端则直接测试接口,在前期不用集成前后端一起调试。</p><p>在此总结一下自己在基于 AngualrJS 搭建 SPA 应用的过程中学到的东西。仅限于 AngularJS 1.x。</p><a id="more"></a><h2 id="项目结构"><a href="#项目结构" class="headerlink" title="项目结构"></a>项目结构</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">./</span><br><span class="line">├─ src/</span><br><span class="line">│ ├─ app/</span><br><span class="line">│ │ ├─ [controller]/[.html, .controller.js, .css]</span><br><span class="line">│ │ ├─ app.js</span><br><span class="line">│ │ └─ app.controller.js</span><br><span class="line">│ ├─ component/[controller]/[.html, .controller.js*, .css*]</span><br><span class="line">│ ├─ fonts</span><br><span class="line">│ ├─ index.html</span><br><span class="line">│ ├─ 404.html</span><br><span class="line">│ ├─ favicon.ico</span><br><span class="line">│ └─ assets/[images, styles]</span><br><span class="line">├─ dist/</span><br><span class="line">├─ test/</span><br><span class="line">├─ Gruntfile.js</span><br><span class="line">├─ package.json</span><br><span class="line">└─ README.md</span><br></pre></td></tr></table></figure><h2 id="应用框架"><a href="#应用框架" class="headerlink" title="应用框架"></a>应用框架</h2><h3 id="入口-index-html"><a href="#入口-index-html" class="headerlink" title="入口 - index.html"></a>入口 - index.html</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><!doctype html></span></span><br><span class="line"><span class="tag"><<span class="name">html</span> <span class="attr">ng-app</span>=<span class="string">"simpleApp"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">"X-UA-Compatible"</span> <span class="attr">content</span>=<span class="string">"IE=edge"</span> /></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span> /></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span><span class="tag"></<span class="name">title</span>></span></span><br><span class="line"> <span class="comment"><!-- disable caches for all browser --></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">"cache-control"</span> <span class="attr">content</span>=<span class="string">"max-age=0"</span> /></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">"cache-control"</span> <span class="attr">content</span>=<span class="string">"no-cache"</span> /></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">"cache-control"</span> <span class="attr">content</span>=<span class="string">"no-store"</span> /></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">"expires"</span> <span class="attr">content</span>=<span class="string">"0"</span> /></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">"expires"</span> <span class="attr">content</span>=<span class="string">"Tue, 01 Jan 1980 1:00:00 GMT"</span> /></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">"pragma"</span> <span class="attr">content</span>=<span class="string">"no-cache"</span> /></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">name</span>=<span class="string">"viewport"</span> <span class="attr">content</span>=<span class="string">"width=device-width"</span> /></span></span><br><span class="line"> <span class="comment"><!-- stylesheets start --></span></span><br><span class="line"> <span class="comment"><!-- stylesheets end --></span></span><br><span class="line"> <span class="tag"></<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">body</span> <span class="attr">ng-controller</span>=<span class="string">"MainCtrl"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"container"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">ng-view</span>></span><span class="tag"></<span class="name">div</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">div</span>></span></span><br><span class="line"> <span class="comment"><!-- scripts start --></span></span><br><span class="line"> <span class="comment"><!-- scripts end --></span></span><br><span class="line"> <span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><h3 id="初始化-app-app-js"><a href="#初始化-app-app-js" class="headerlink" title="初始化 - app/app.js"></a>初始化 - app/app.js</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">'use strict'</span>;</span><br><span class="line">(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> app = angular</span><br><span class="line"> .module(<span class="string">'simpleApp'</span>, [<span class="string">'ngRoute'</span>])</span><br><span class="line"> .filter(<span class="string">'breakFilter'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params">text</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (!!text) {</span><br><span class="line"> <span class="keyword">return</span> text.replace(<span class="regexp">/\n/g</span>, <span class="string">'<br />'</span>);</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> })</span><br><span class="line"> .config(<span class="function"><span class="keyword">function</span>(<span class="params">$routeProvider, $compileProvider</span>) </span>{</span><br><span class="line"> $routeProvider</span><br><span class="line"> .when(<span class="string">'home'</span>, {</span><br><span class="line"> templateUrl: <span class="string">'app/home/home.html'</span>,</span><br><span class="line"> })</span><br><span class="line"> .when(<span class="string">'somepage/somepath/:someparam?'</span>, {</span><br><span class="line"> templateUrl: <span class="string">'app/somepage/somepage.html'</span>,</span><br><span class="line"> })</span><br><span class="line"> .otherwise({</span><br><span class="line"> redirectTo: <span class="string">'/home'</span>,</span><br><span class="line"> });</span><br><span class="line"> <span class="comment">// 数据绑定写入 a.href 时的白名单过滤</span></span><br><span class="line"> $compileProvider.aHrefSanitizationWhitelist(<span class="regexp">/^(http|https|file|tel):/</span>);</span><br><span class="line"> });</span><br><span class="line">})();</span><br></pre></td></tr></table></figure><p>上面在初始化应用时添加了依赖 ngRoute ,这不是 AngularJS 原生自带的,需要单独引入 angular-route.js 文件,且必须保持与 angular.js 版本一致,否则会报错。</p><h3 id="控制器-controller-js"><a href="#控制器-controller-js" class="headerlink" title="控制器 - *.controller.js"></a>控制器 - *.controller.js</h3><p>以 MainCtrl 为例</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">'use strict'</span>;</span><br><span class="line">angular.module(<span class="string">'simpleApp'</span>).controller(<span class="string">'MainCtrl'</span>, <span class="function"><span class="keyword">function</span>(<span class="params">$scope, $http</span>) </span>{</span><br><span class="line"> <span class="comment">// do something</span></span><br><span class="line">});</span><br></pre></td></tr></table></figure><h2 id="常用命令"><a href="#常用命令" class="headerlink" title="常用命令"></a>常用命令</h2><h3 id="ng-repeat"><a href="#ng-repeat" class="headerlink" title="ng-repeat"></a>ng-repeat</h3><p>ng-repeat 是一个非常好用的命令,类似 forEach,能够遍历数组或对象属性,循环创建 DOM 元素。<br>一个简单的例子:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">app.controller(<span class="string">'SomeCtrl'</span>, <span class="function"><span class="keyword">function</span>(<span class="params">$scope</span>) </span>{</span><br><span class="line"> $scope.items = [{ <span class="attr">name</span>: <span class="string">'xm'</span> }, { <span class="attr">name</span>: <span class="string">'kyer'</span> }];</span><br><span class="line">});</span><br></pre></td></tr></table></figure><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">p</span> <span class="attr">ng-repeat</span>=<span class="string">"item in items"</span>></span>{{item.name}}<span class="tag"></<span class="name">p</span>></span></span><br></pre></td></tr></table></figure><h3 id="ng-if-ng-show"><a href="#ng-if-ng-show" class="headerlink" title="ng-if/ng-show"></a>ng-if/ng-show</h3><p>这两个命令的用法看起来很像,都是根据属性值的真假来决定是否显示该 DOM 元素,但是有一点很重要的区别。<br><code>ng-if</code> 值为 false 时,不会创建该 DOM 元素,而 <code>ng-show</code> 值为 false 时,该元素依然会被创建,只是通过设置 css 属性 <code>display: none;</code> 使其不显示而已。</p><h3 id="ng-src-ng-href"><a href="#ng-src-ng-href" class="headerlink" title="ng-src/ng-href"></a>ng-src/ng-href</h3><p>由于 AngularJS 的数据替换是在脚本加载完成以后进行的,所以如果写了类似</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">"{{data.image}}"</span> /></span></span><br></pre></td></tr></table></figure><p>其中 img 标签的 src 值会在被替换前无法正确显示图片,因为根本不存在 <code>data.image</code> 路径的图片文件,这时候就需要 ng-src 命令了,它会在 AngularJS<br>替换完数据后为 img 标签添加 src 属性,这时候就是正确的值了。</p><p>同理,ng-href 也是解决在数据替换前,a 标签的不正确行为。</p><h2 id="一些问题的解决方法"><a href="#一些问题的解决方法" class="headerlink" title="一些问题的解决方法"></a>一些问题的解决方法</h2><h3 id="输出-html-标签"><a href="#输出-html-标签" class="headerlink" title="输出 html 标签"></a>输出 html 标签</h3><p>使用 <code>\{\{someHtmlStr\}\}</code>(注:双花括号与 hexo 模板解析冲突,故在此加<code>\</code>) 或 <code>ng-bind="someHtmlStr"</code> 输出带有 html 标签的字符串时,<br>AngularJS 默认对其中的 html 标签做实体化转义,即将 <code><p>Hi</p></code> 变成 <code>&lt;p&gt;Hi&lt;/p&gt;Hi</code>,然后浏览器上看到的就是<code><p>Hi<p></code>.</p><p>AngualrJS 出于安全考虑对字符串做了过滤,但有时候我们希望输出没有实体化的 html 标签,这时候需要做一些工作。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> someHtmlStr = <span class="string">'<p>Hi</p>'</span>;</span><br><span class="line">$scope.someHtmlStr = $sce.trustAsHtml(someHtmlStr);</span><br></pre></td></tr></table></figure><p>$sce 服务中的 sce 是 ‘Stric Contextual Escaping’ 的缩写,即’严格的上下文模式’。</p><p>除了上面的方式,还可以写成自定义的 filter。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">app.filter(<span class="string">'html2trusted'</span>, [<span class="string">'$sce'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">$sce</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params">text</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> $sce.trustAsHtml(text);</span><br><span class="line"> };</span><br><span class="line">});</span><br></pre></td></tr></table></figure><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">p</span> <span class="attr">ng-bind-html</span>=<span class="string">"someHtmlStr | html2trusted"</span>></span><span class="tag"></<span class="name">p</span>></span></span><br></pre></td></tr></table></figure><h3 id="ng-repeat-渲染完成事件监听"><a href="#ng-repeat-渲染完成事件监听" class="headerlink" title="ng-repeat 渲染完成事件监听"></a>ng-repeat 渲染完成事件监听</h3><p>有时候在一些第三方库时,会要求所需的 DOMContent 已经渲染完成,但 ng-repeat 命令渲染 DOM 和后续 js 代码执行时并行的,<br>我们必须监听 ng-repeat 完成时的事件,然后再对相应的 DOM 初始化第三方库。</p><p>一个比较容易理解的例子就是轮播组件,轮播内容用 ng-repeat 命令输出,但是初始化轮播时都要计算一些元素的 width/height 属性等,<br>由于代码是异步执行的,一旦进行了数据绑定,ng-repeat 渲染就会开始,而往往我们执行 <code>$("#slide").slide({})</code> 时渲染还未完成,<br>就会得到不正确的显示结果。所以,轮播初始化必须在 ng-repeat 渲染完成后执行。使用 AngularJS 自定义的属性标签可以实现监听 ngRepeatFinished 事件。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">app</span><br><span class="line"> .controller(<span class="string">'SomeCtrl'</span>, <span class="function"><span class="keyword">function</span>(<span class="params">$scope</span>) </span>{</span><br><span class="line"> $scope.items = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];</span><br><span class="line"></span><br><span class="line"> $scope.$on(<span class="string">'ngRepeatFinished'</span>, <span class="function"><span class="keyword">function</span>(<span class="params">ngRepeatFinishedEvent</span>) </span>{</span><br><span class="line"> <span class="comment">// do something</span></span><br><span class="line"> });</span><br><span class="line"> })</span><br><span class="line"> .directive(<span class="string">'onFinishRender'</span>, <span class="function"><span class="keyword">function</span>(<span class="params">$timeout</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> restrict: <span class="string">'A'</span>,</span><br><span class="line"> link: <span class="function"><span class="keyword">function</span>(<span class="params">scope, element, attr</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (scope.$last === <span class="literal">true</span>) {</span><br><span class="line"> <span class="comment">// $timeout 将触发事件的操作放到事件队列的最后,以保证已全部渲染完成</span></span><br><span class="line"> $timeout(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> scope.$emit(attr.onFinishRender);</span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"> };</span><br><span class="line"> });</span><br></pre></td></tr></table></figure><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">p</span> <span class="attr">ng-repeat</span>=<span class="string">"item in items"</span> <span class="attr">on-finish-render</span>=<span class="string">"ngRepeatFinished"</span>></span>{{item}}<span class="tag"></<span class="name">p</span>></span></span><br></pre></td></tr></table></figure><h3 id="lazy-loading"><a href="#lazy-loading" class="headerlink" title="lazy-loading"></a>lazy-loading</h3><p>在 ng-view 中渲染的 DOM 是不会解释其中包含的 script 标签的。这时候就需要用到写一个可以正常加载其中包含的 script 标签的指令。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">app.directive(<span class="string">'script'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> restrict: <span class="string">'E'</span>,</span><br><span class="line"> scope: <span class="literal">false</span>,</span><br><span class="line"> link: <span class="function"><span class="keyword">function</span>(<span class="params">scope, elem, attr</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (attr.type === <span class="string">'text/javascript-lazy'</span>) {</span><br><span class="line"> <span class="keyword">var</span> s = <span class="built_in">document</span>.createElement(<span class="string">'script'</span>);</span><br><span class="line"> s.type = <span class="string">'text/javascript'</span>;</span><br><span class="line"> <span class="keyword">var</span> src = elem.attr(<span class="string">'src'</span>);</span><br><span class="line"> <span class="keyword">if</span> (src !== <span class="literal">undefined</span>) {</span><br><span class="line"> s.src = src;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">var</span> code = elem.text();</span><br><span class="line"> s.text = code;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">document</span>.body.appendChild(s);</span><br><span class="line"> elem.remove();</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"> };</span><br><span class="line">});</span><br></pre></td></tr></table></figure><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript-lazy"</span> <span class="attr">src</span>=<span class="string">"somefile.js"</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br></pre></td></tr></table></figure><p>这样即使在模板中写 script 标签引入外部文件,就可以正常执行了。再查了一下,发现除了 script 标签,view, controller 等都可以 lazy loading,而且这个概念也不仅局限于 AngularJS.</p><h2 id="概念理解"><a href="#概念理解" class="headerlink" title="概念理解"></a>概念理解</h2><h3 id="依赖注入"><a href="#依赖注入" class="headerlink" title="依赖注入"></a>依赖注入</h3><p>AngularJS 使用依赖注入提高控制器代码的灵活性,通过参数名匹配注入相应的功能或服务。比如一直写的</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">app.controller(<span class="string">'SomeCtrl'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">$scope, $http, ...</span>) </span>{</span><br><span class="line"> <span class="comment">// some code</span></span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>参数列表中的 $scope, $http 等都是 AngularJS 原生的(前面有 <code>$</code>),参数列表的顺序可以是任意的,也不用列出所有可用的参数,只需选择自己用到的即可。</p><p>自己也可以定义服务、工厂函数等,AngularJS 的依赖注入机制提供了多种类型,包括</p><ul><li>值 - value</li><li>工厂 - factory</li><li>服务 - service</li><li>提供者 - $provide</li><li>常量 - constant</li></ul><p>目前还没用过这些类型,都是自己在控制器里写相应的代码。看过一点前端的 MVC,即使用自定义工厂映射 RESTful API 对应的资源,通过对这些对象的修改,会直接 ajax 请求更新到后台,非常方便,值得学习使用。</p><h3 id="数据绑定"><a href="#数据绑定" class="headerlink" title="数据绑定"></a>数据绑定</h3><p>AngularJS 最让人惊喜莫过于数据双向绑定了,对于表单的验证与提交,动态数据渲染 DOM 方面不能更好用了。对它的实现没有深入了解过多,<br>应该是用到了脏数据检查,将数据与 DOM 元素属性绑定,一旦数据修改了就更新,而且这种更新是双向的,DOM 内容可以直接修改 js 对象,js 对象值的修改也会直接反映到 DOM 中。 这块还要深入学习。</p><h3 id="作用域"><a href="#作用域" class="headerlink" title="作用域"></a>作用域</h3><p>不论是前后端模板,在生成 html 内容时都有作用域的概念,如 JSP 中,通过将 <code><% %></code> 标签外的 html 代码变成字符串,标签内容代码生成 Java 代码,从而使得 JSP 页面内拥有了对应 Servlet 变量的作用域。</p><p>AngularJS 则通过 <code>$scope</code> 为页面模板绑定作用域,所有挂在 <code>$scope</code> 上的属性,可以直接在页面中使用。其中对于非 AngularJS 属性,如 <code>href</code>,<code>src</code>等要使用 AngularJS 模板需要使用花括号包起变量,而对于 AngularJS 的属性,则直接使用,如 <code>ng-if="someBoolean"</code>.</p><p>AngularJS 的作用域还可以嵌套,在父作用域中定义的属性,可以在子作用域中访问。</p><h3 id="视图"><a href="#视图" class="headerlink" title="视图"></a>视图</h3><p>ng-view 属性用于在页面的 hashtag 发生变化时,将对应的模板渲染到该属性对应的 DOM 容器中。视图可以嵌套,不过我还没遇到过这样的开发场景。</p><h3 id="directive"><a href="#directive" class="headerlink" title="directive"></a>directive</h3><p>这个可能是 AngularJS 最难学的部分了,属于高手进阶关卡。在开发中遇到问题时,总是能搜到各种各样的 directive 解决方案,然而并看不懂。</p><p>首先 directive 非常强大,可以做出自定义的一套标签库,还包括自定义属性等等。而 directive 就提供了解析和处理这些自定义标签/属性等的操作。</p><h2 id="我的相关项目"><a href="#我的相关项目" class="headerlink" title="我的相关项目"></a>我的相关项目</h2><ul><li><a href="https://github.com/xdsselab/sselab.org" target="_blank" rel="noopener">sselab</a></li><li><a href="http://rosenjx.com" target="_blank" rel="noopener">罗森光电科技</a></li><li><a href="http://git.oschina.net/x-web/document-check-tool-web" target="_blank" rel="noopener">文档格式检查工具</a></li><li><a href="http://git.oschina.net/x-web/pingpangke" target="_blank" rel="noopener">乒乓客</a></li></ul><h2 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h2><ul><li><a href="https://segmentfault.com/a/1190000000639561" target="_blank" rel="noopener">angular 中的 ng-bind-html 指令和$sce 服务</a></li><li><a href="http://stackoverflow.com/questions/15207788/calling-a-function-when-ng-repeat-has-finished" target="_blank" rel="noopener">Calling a function when ng-repeat has finished</a></li><li><a href="http://stackoverflow.com/questions/19917774/why-ng-scope-is-added-to-javascript-inline-of-my-partial-view-and-makes-alert-no/22476888#22476888" target="_blank" rel="noopener">Why ng-scope is added to javascript inline of my partial view and makes alert not working?</a></li></ul>]]></content>
<summary type="html">
<h1 id="Single-Page-Application-AngularJS"><a href="#Single-Page-Application-AngularJS" class="headerlink" title="Single Page Application - AngularJS"></a>Single Page Application - AngularJS</h1><p>最近半年做了不少单页面网站的开发,有静态也有动态的,主要基于 AngularJS(偶尔在我的 <a href="https://github.com/x-web/x-web.github.io" target="_blank" rel="noopener">blog</a> 中<br>用了 <a href="http://www.ractivejs.org/" target="_blank" rel="noopener">ractive</a>)。对这种重前端应用就着迷了,优点是前后端分工明确,高效(异步请求数据)且用户体验较好(没有频繁的页面跳转)。</p>
<p>没有任何框架能够适应一切场景。SPA 也有缺点,比如应用复杂代码量增加时,单页面应用就会有内存泄露等棘手问题,还有 SEO 优化等等问题。<br>SPA 适应的场景,如小型静态应用,与后台频繁交互(但不涉及重大安全问题)的应用等,我认为都是适合单页面应用的。</p>
<p>SPA 与 RESTful API 非常合适,只要确定接口规范,前后端开发就能较为独立地进行,前端通过 mock 异步数据,后端则直接测试接口,在前期不用集成前后端一起调试。</p>
<p>在此总结一下自己在基于 AngualrJS 搭建 SPA 应用的过程中学到的东西。仅限于 AngularJS 1.x。</p>
</summary>
<category term="前端开发" scheme="http://muxfe.github.io/categories/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/"/>
<category term="javascript" scheme="http://muxfe.github.io/tags/javascript/"/>
<category term="angularjs" scheme="http://muxfe.github.io/tags/angularjs/"/>
</entry>
<entry>
<title>2015 年终总结</title>
<link href="http://muxfe.github.io/2016/01/01/2015-review/"/>
<id>http://muxfe.github.io/2016/01/01/2015-review/</id>
<published>2016-01-01T03:03:20.000Z</published>
<updated>2018-09-27T12:20:30.907Z</updated>
<content type="html"><![CDATA[<h1 id="回顾-2015"><a href="#回顾-2015" class="headerlink" title="回顾 2015"></a>回顾 2015</h1><h2 id="学业"><a href="#学业" class="headerlink" title="学业"></a>学业</h2><p>从大三开始转向学习准备保研开始,终于在 2015 年如愿以偿.</p><p>之前一直在找工作和上研中纠结,最后还是打算上研,除了获得专业技能的提高之外,还需要更全面地学习和更好的发展.</p><p>在此回顾一下自己的 2015.</p><a id="more"></a><h2 id="技术"><a href="#技术" class="headerlink" title="技术"></a>技术</h2><h3 id="前端"><a href="#前端" class="headerlink" title="前端"></a>前端</h3><p>3 月份有面试阿里的实习生,第一次面试到二面被刷,感觉还是很不爽的.发现自己的能力和亮点还是不够突出,通过小一年时间的学习和开发实践,可以说进步了很多.</p><p>从不了解 nodejs, AMD/CMD 等等,到现在已经用 nodejs 做了一个课程项目, 不仅了解了 AMD/CMD, 还对前端业界一些新框架和新技术也有所了解,尝试了 Angular. 其他如前端的工程化,测试,组件化等非常多的东西可以去”玩”.</p><p>前端技术的变化真的非常快,框架类库层出不穷,学习起来有时候也让人感到迷茫.多学习标准和思想,不变的东西,经得起时间考验的东西才最有价值.</p><h3 id="算法"><a href="#算法" class="headerlink" title="算法"></a>算法</h3><p>大三下学习了算法导论,对一些经典算法和算法分析有了基本的认识,但是因为很久没有刷题了,算法实现能力下降很多.上个月开始坚持刷 leetcode, 然后用 github 打卡, 感觉想要每天坚持一件事真的很难.</p><h3 id="Java"><a href="#Java" class="headerlink" title="Java"></a>Java</h3><p>我所在的实验室主要使用 Java 语言,需要把它作为后端开发的主力.今年做了几个 Java Web 的项目练手,对 Java 只能说不喜欢也不讨厌.Java 的跨平台特性确实很诱人,现在把开发平台转到 Linux 上,所有 Java 项目都能无缝衔接.当然前端的东西本来就是平台无关的~2333.</p><h3 id="Nodejs"><a href="#Nodejs" class="headerlink" title="Nodejs"></a>Nodejs</h3><p>看完<a href="https://github.com/JacksonTian" target="_blank" rel="noopener">朴灵</a>大大的 <深入浅出 Nodejs> 后,对 Nodejs 开发更是深深地痴迷.js 语言的灵活配合 Node 的异步 IO 和事件驱动简直完美.大四上的项目管理课需要开发一个类似淘宝的电商网站,我用 Nodejs + Express + Mongodb 完成了开发,感觉很好.12 月份还看了桑大的 <a href="https://github.com/base-n/koa-generator-examples" target="_blank" rel="noopener">koa-generator-examples</a>.发现有这么多方法来保持异步编程的优雅,缩小与同步编程的差异,感觉又要学习一波了.</p><h3 id="可视化-D3-与-mxGraph"><a href="#可视化-D3-与-mxGraph" class="headerlink" title="可视化: D3 与 mxGraph"></a>可视化: D3 与 mxGraph</h3><p>1 月份在实验室实习的时候,因为项目需要学习了一点 <a href="https://www.jgraph.com/javascript-graph-visualization-library.html" target="_blank" rel="noopener">mxGraph</a>,但是只接触了皮毛,不够深入.</p><p>8 月份实习时,学习了 <a href="https://github.com/mbostock/d3" target="_blank" rel="noopener">D3</a>,一个更强大的可视化 js 库,支持各种图表.主要学习和使用了饼图,引力图.也对 <a href="http://www.w3.org/TR/SVG/" target="_blank" rel="noopener">SVG</a> 有了些许了解.</p><h3 id="GitHub"><a href="#GitHub" class="headerlink" title="GitHub"></a>GitHub</h3><p>Git 是一个出色的分布式版本控制工具,GitHub 则是一个神奇的网站,各大开源项目聚集地,GitHub Pages , Git Book 等等.2015 年在 GitHub 上连击了 40 天,是做项目管理那个项目的,想要坚持提交代码,无奈没有成功.2016 要好好使用它.</p><h2 id="读书"><a href="#读书" class="headerlink" title="读书"></a>读书</h2><ol><li><a href="http://book.douban.com/subject/3590768/" target="_blank" rel="noopener">JavaScript 语言精粹</a></li><li><a href="http://book.douban.com/subject/25892704/" target="_blank" rel="noopener">Nodejs 权威指南</a></li><li><a href="http://book.douban.com/subject/2368647/" target="_blank" rel="noopener">jQuery in Action</a></li><li><a href="http://book.douban.com/subject/1102259/" target="_blank" rel="noopener">人月神话</a></li><li><a href="http://book.douban.com/subject/6709809/" target="_blank" rel="noopener">暗时间</a></li><li><a href="http://book.douban.com/subject/25768396/" target="_blank" rel="noopener">深入浅出 Nodejs</a></li><li><a href="http://book.douban.com/subject/26256865/" target="_blank" rel="noopener">D3 数据可视化实战手册</a></li><li>Nodejs 实战</li><li><a href="http://book.douban.com/subject/19977785/" target="_blank" rel="noopener">MongoDB 权威指南</a></li></ol><h2 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h2><h3 id="常去的网站"><a href="#常去的网站" class="headerlink" title="常去的网站"></a>常去的网站</h3><ol><li><a href="https://www.zhihu.com/people/darkdream" target="_blank" rel="noopener">知乎</a></li><li><a href="https://cnodejs.org/user/x-web" target="_blank" rel="noopener">CNode</a></li><li><a href="https://github.com/x-web" target="_blank" rel="noopener">GitHub</a></li><li><a href="http://v2ex.com/member/kyer" target="_blank" rel="noopener">V2EX</a></li><li><a href="https://www.google.com" target="_blank" rel="noopener">Google</a></li><li><a href="http://www.ruanyifeng.com/blog/" target="_blank" rel="noopener">阮一峰的网络日志</a></li><li><a href="https://leetcode.com/" target="_blank" rel="noopener">Leetcode</a></li></ol><h3 id="理财"><a href="#理财" class="headerlink" title="理财"></a>理财</h3><p>考了证券从业资格基础知识和交易两门.</p>]]></content>
<summary type="html">
<h1 id="回顾-2015"><a href="#回顾-2015" class="headerlink" title="回顾 2015"></a>回顾 2015</h1><h2 id="学业"><a href="#学业" class="headerlink" title="学业"></a>学业</h2><p>从大三开始转向学习准备保研开始,终于在 2015 年如愿以偿.</p>
<p>之前一直在找工作和上研中纠结,最后还是打算上研,除了获得专业技能的提高之外,还需要更全面地学习和更好的发展.</p>
<p>在此回顾一下自己的 2015.</p>
</summary>
<category term="随笔" scheme="http://muxfe.github.io/categories/%E9%9A%8F%E7%AC%94/"/>
<category term="review" scheme="http://muxfe.github.io/tags/review/"/>
</entry>
<entry>
<title>最长回文子串</title>
<link href="http://muxfe.github.io/2015/12/15/longest-palindrome/"/>
<id>http://muxfe.github.io/2015/12/15/longest-palindrome/</id>
<published>2015-12-15T04:03:20.000Z</published>
<updated>2018-09-27T09:01:19.209Z</updated>
<content type="html"><![CDATA[<h2 id="最长回文子串"><a href="#最长回文子串" class="headerlink" title="最长回文子串"></a>最长回文子串</h2><p>最近在 leetcode 上刷算法题,重温一下 ACM 和 javascript 练手,发现了一道有趣的题目,最长回文子串。</p><p>开始的想法是反转字符串然后找出最大公共子串(LCS),但是 TLE 了。觉得可能是 js 本身效率太低,然后找了 leetcode 上别人写的算法分析,发现反转后找 LCS 是错误的,而且分析写得非常好,觉得应该好好学习下,记录在此。</p><h3 id="回文"><a href="#回文" class="headerlink" title="回文"></a>回文</h3><p>回文字符串就是指无论从那个方向读都是一样的,如<code>'aba'</code>就是一个简单的回文串。</p><p>开始的想法是先将字符串反转,然后找出它们的最长公共子串,即是要找最长回文串。</p><p><strong>然而这是错误的!!!</strong></p><a id="more"></a><p>比如 <code>'abadfcdaba'</code> 反转后是 <code>'abadcfdaba'</code>,它们的 LCS 是 <code>'abad'</code>,这显然不是一个回文串。</p><p>而它存在的原因就是原字符串中出现了两个一样的回文串,且有额外相同的部分分别出现在这两个回文串的前后。导致反转后的字符串除了回文部分相同外,还有非回文串也相同。</p><p>下面介绍几种不同的方法来计算 LPS。</p><h3 id="暴力搜索"><a href="#暴力搜索" class="headerlink" title="暴力搜索"></a>暴力搜索</h3><p>最简单的办法是找出字符串中的所有子串,判断其是否为回文串,然后记录下其中最大的回文子串即可。</p><p>暴搜无例外的话效率都很低,这个算法是 <code>O(N^3)</code> 的。首先找出所有子串 是 <code>O(N^2)</code> 的,然后判断其是否为回文是 <code>O(N)</code> 的。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> longestPalindrome_bf = <span class="function"><span class="keyword">function</span>(<span class="params">s</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (!s) <span class="keyword">return</span> <span class="string">''</span>;</span><br><span class="line"> <span class="keyword">var</span> longest = s[<span class="number">0</span>], str, i, j, len;</span><br><span class="line"> <span class="keyword">var</span> isPalindrom = <span class="function"><span class="keyword">function</span> (<span class="params">left, right</span>) </span>{</span><br><span class="line"> <span class="keyword">while</span> (left < right && s[left] === s[right]) {</span><br><span class="line"> left++;</span><br><span class="line"> right--;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> left >= right;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (len = <span class="number">2</span>; len <= s.length; len++) {</span><br><span class="line"> <span class="keyword">for</span> (i = <span class="number">0</span>; i < s.length; i++) {</span><br><span class="line"> j = i + len - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> (isPalindrom(i, j)) {</span><br><span class="line"> str = s.slice(i, j + <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">if</span> (longest.length < str.length) longest = str;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> longest;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="动态规划"><a href="#动态规划" class="headerlink" title="动态规划"></a>动态规划</h3><p>DP可能是解这个问题的一个好方法,然而算法复杂度依然是 O(N^2) 的,而且空间复杂度也是 O(N^2)。</p><p>我们假设用 <code>P[i][j]</code> 来表示 <code>s[i..j]</code> 是否是一个回文子串。</p><p>它的计算公式长这样:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">P[i][j] = s[i] === s[j] && P[i + <span class="number">1</span>][j - <span class="number">1</span>] ? <span class="literal">true</span> : <span class="literal">false</span>;</span><br></pre></td></tr></table></figure><p>算法实现如下:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> longestPalindrome_dp = <span class="function"><span class="keyword">function</span>(<span class="params">s</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> i, j, len;</span><br><span class="line"> <span class="comment">// isPalindrom[i][j] represent s[i..j] is a parlindrom string or not.</span></span><br><span class="line"> <span class="keyword">var</span> isPalindrom = <span class="keyword">new</span> <span class="built_in">Array</span>(s.length);</span><br><span class="line"> <span class="keyword">for</span> (i = <span class="number">0</span>; i < s.length; i++) {</span><br><span class="line"> isPalindrom[i] = <span class="keyword">new</span> <span class="built_in">Array</span>(s.length).fill(<span class="literal">false</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">var</span> maxLen = <span class="number">1</span>, longestBegin = <span class="number">0</span>;</span><br><span class="line"> <span class="comment">// initialize</span></span><br><span class="line"> <span class="keyword">for</span> (i = <span class="number">0</span>; i < s.length; i++) {</span><br><span class="line"> isPalindrom[i][i] = <span class="literal">true</span>;</span><br><span class="line"> <span class="keyword">if</span> (i < s.length - <span class="number">1</span> && s[i] === s[i + <span class="number">1</span>]) {</span><br><span class="line"> isPalindrom[i][i + <span class="number">1</span>] = <span class="literal">true</span>;</span><br><span class="line"> maxLen = <span class="number">2</span>;</span><br><span class="line"> longestBegin = i;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// compute</span></span><br><span class="line"> <span class="keyword">for</span> (len = <span class="number">3</span>; len <= s.length; len++) {</span><br><span class="line"> <span class="keyword">for</span> (i = <span class="number">0</span>; i < s.length; i++) {</span><br><span class="line"> j = len + i - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> (s[i] === s[j] && isPalindrom[i + <span class="number">1</span>][j - <span class="number">1</span>]) {</span><br><span class="line"> isPalindrom[i][j] = <span class="literal">true</span>;</span><br><span class="line"> maxLen = len;</span><br><span class="line"> longestBegin = i;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> s.slice(longestBegin, longestBegin + maxLen);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>这个实现在 leetcode 上 TLE 了。几乎跟暴搜一样慢。</p><p>ps. 我觉得跟 js 的数组对象有关。在 js 中处理二维数组比静态语言处理要慢的多。</p><h2 id="继续优化"><a href="#继续优化" class="headerlink" title="继续优化"></a>继续优化</h2><h3 id="降低空间复杂度"><a href="#降低空间复杂度" class="headerlink" title="降低空间复杂度"></a>降低空间复杂度</h3><p>DP 的空间复杂度是 <code>O(N^2)</code> 的,主要用来保存二维数组 <code>P[i][j]</code>,而且只用了一半。</p><p>我们可以把空间复杂度降到 <code>O(1)</code>,只存找到的最长回文串即可。枚举轴心位置,并进行扩展。如果是回文,则轴心两边的字符应该对称相等。</p><p>需要考虑到长度奇偶情况的不同,如果是奇数长度,轴心就是一个字符;如果是偶数长度,轴心则不在字符串中。</p><p>实现如下:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> longestPalindrome_enum = <span class="function"><span class="keyword">function</span>(<span class="params">s</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (!s) <span class="keyword">return</span> <span class="string">''</span>;</span><br><span class="line"> <span class="keyword">var</span> longest = s[<span class="number">0</span>];</span><br><span class="line"> <span class="keyword">var</span> expandAroundCenter = <span class="function"><span class="keyword">function</span> (<span class="params">left, right</span>) </span>{</span><br><span class="line"> <span class="keyword">while</span> (left >= <span class="number">0</span> && right < s.length && s[left] === s[right]) {</span><br><span class="line"> left--;</span><br><span class="line"> right++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> s.slice(left + <span class="number">1</span>, right);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < s.length; i++) {</span><br><span class="line"> <span class="comment">// 奇数</span></span><br><span class="line"> <span class="keyword">var</span> odd = expandAroundCenter(i, i);</span><br><span class="line"> <span class="keyword">if</span> (odd.length > longest.length) longest = odd;</span><br><span class="line"> <span class="comment">// 偶数</span></span><br><span class="line"> <span class="keyword">var</span> even = expandAroundCenter(i, i + <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">if</span> (longest.length < even.length) longest = even;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> longest;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>这个实现在 leetcode 上 AC 了,用了 <code>236ms</code>。</p><h3 id="降低时间复杂度"><a href="#降低时间复杂度" class="headerlink" title="降低时间复杂度"></a>降低时间复杂度</h3><p>相比降低空间复杂度,降低时间复杂度要难得多。这里有一个 <code>O(N)</code> 时间复杂度的算法,叫做 <a href="https://en.wikipedia.org/wiki/Longest_palindromic_substring#Manacher.27s_algorithm" target="_blank" rel="noopener">Manacher</a> 算法。</p><p>能够从 <code>O(N^2)</code> 降到 <code>O(N)</code>,这个算法很巧妙。它首先解决了长度奇偶不同的问题。</p><p>通过向字符串中加入一些特殊字符来使长度均为<strong>奇数</strong>。特殊字符即为原字符串的字符集中没有的字符。如 <code>'aba'</code> 中插入 <code>'#'</code>,变成<code>'#a#b#a#'</code>。</p><p>然后提出了一个<strong>回文半径</strong>(P)的概念:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">T = # a # b # a # a # b # a #</span><br><span class="line">P = 0 1 0 3 0 1 6 1 0 3 0 1 0</span><br></pre></td></tr></table></figure><p>它代表了以该字符为轴心的回文串对折后的长度。由于插入了特殊字符,如果最长回文字符串的长度为偶数,则轴心会出现在 <code>'#'</code> 上。</p><p>容易看出上面的例子中,最大回文子串的轴心就是 <code>P</code> 为 6 的字符。最大回文子串为 <code>'abaaba'</code> ,长度刚好为 6.</p><p>这显然不是巧合,接下来就是要计算 <code>P</code>,记下其最大值及对应下标,即可。目标时间复杂度 <code>O(N)</code>。当然,这个算法最难的部分,就是计算 <code>P</code>。</p><p>正常计算 <code>P</code> 的话,时间复杂度依然是 <code>O(N^2)</code>,但是如果利用回文串的对称特性,减少搜索,就可以将复杂度降至 <code>O(N)</code>。</p><p>计算 <code>P</code> 就是以每一个字符为轴心计算回文半径,也就是从每一个字符开始向两边搜索,那么右边必然会搜索到尚未遍历到的字符,如果我们记下最大能搜索到的右边界 <code>R</code><br>。在后面的遍历搜索中,如果当前 <code>T[i]</code> 在边界内,即比最大右边界小,那么也就是在一个已搜索的回文子串中,假设 <code>i'</code> 是 <code>i</code> 对应当前最大 <code>R</code> 的轴心 <code>C</code> 的对称位置(即 <code>T[i] == T[i']</code>), 可以做出下面的结论:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">if P[i'] < R-i</span><br><span class="line">then P[i] = P[i']</span><br><span class="line">else P[i] >= P[i'] (需要进一步扩展搜索得出)</span><br></pre></td></tr></table></figure><p>另一种情况,如果当前字符 <code>T[i]</code> 不在边界内,即我们不能得出任何结论,所以 <code>P[i] = 0</code>。</p><p>js 实现:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> longestPalindrome_manacher = <span class="function"><span class="keyword">function</span>(<span class="params">s</span>) </span>{</span><br><span class="line"> s = <span class="string">'^#'</span> + s.split(<span class="string">''</span>).join(<span class="string">'#'</span>) + <span class="string">'#$'</span>;</span><br><span class="line"> <span class="keyword">var</span> radius = <span class="keyword">new</span> <span class="built_in">Array</span>(s.length).fill(<span class="number">0</span>);</span><br><span class="line"> <span class="keyword">var</span> C = <span class="number">0</span>, centerIndex = <span class="number">0</span>, maxRight = <span class="number">0</span>, maxLen = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">1</span>; i < s.length - <span class="number">1</span>; i++) {</span><br><span class="line"> <span class="comment">// 计算初始回文半径, i' = 2 * C - i</span></span><br><span class="line"> radius[i] = (maxRight > i) ? <span class="built_in">Math</span>.min(maxRight - i, radius[<span class="number">2</span> * C - i]) : <span class="number">0</span>;</span><br><span class="line"> <span class="comment">// 扩展半径</span></span><br><span class="line"> <span class="keyword">while</span> (s[i + <span class="number">1</span> + radius[i]] && s[i - <span class="number">1</span> - radius[i]] && s[i + <span class="number">1</span> + radius[i]] === s[i - <span class="number">1</span> - radius[i]]) radius[i]++;</span><br><span class="line"> <span class="comment">// 更新当前搜索的最大右边界和位置</span></span><br><span class="line"> <span class="keyword">if</span> (i + radius[i] > maxRight) {</span><br><span class="line"> C = i;</span><br><span class="line"> maxRight = i + radius[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// 更新最大回文串长度及位置</span></span><br><span class="line"> <span class="keyword">if</span> (maxLen < radius[i]) {</span><br><span class="line"> maxLen = radius[i];</span><br><span class="line"> centerIndex = i;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> s.slice((centerIndex - maxLen), (centerIndex + maxLen + <span class="number">1</span>)).split(<span class="string">'#'</span>).join(<span class="string">''</span>);</span><br><span class="line">};</span><br></pre></td></tr></table></figure><p>算法效果很好,在 leetcode 上运行时间是 <code>160ms</code>。</p><p>以上。</p><h2 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h2><ul><li><a href="http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-i.html" target="_blank" rel="noopener">Longest Palindromic Substring Part I</a></li><li><a href="http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html" target="_blank" rel="noopener">Longest Palindromic Substring Part II</a></li><li><a href="https://en.wikipedia.org/wiki/Longest_palindromic_substring#Manacher.27s_algorithm" target="_blank" rel="noopener">Wiki:Longest palindromic substring</a></li><li><a href="http://www.felix021.com/blog/read.php?2040" target="_blank" rel="noopener">Manacher’s ALGORITHM: O(n)时间求字符串的最长回文子串</a></li></ul>]]></content>
<summary type="html">
<h2 id="最长回文子串"><a href="#最长回文子串" class="headerlink" title="最长回文子串"></a>最长回文子串</h2><p>最近在 leetcode 上刷算法题,重温一下 ACM 和 javascript 练手,发现了一道有趣的题目,最长回文子串。</p>
<p>开始的想法是反转字符串然后找出最大公共子串(LCS),但是 TLE 了。觉得可能是 js 本身效率太低,然后找了 leetcode 上别人写的算法分析,发现反转后找 LCS 是错误的,而且分析写得非常好,觉得应该好好学习下,记录在此。</p>
<h3 id="回文"><a href="#回文" class="headerlink" title="回文"></a>回文</h3><p>回文字符串就是指无论从那个方向读都是一样的,如<code>&#39;aba&#39;</code>就是一个简单的回文串。</p>
<p>开始的想法是先将字符串反转,然后找出它们的最长公共子串,即是要找最长回文串。</p>
<p><strong>然而这是错误的!!!</strong></p>
</summary>
<category term="算法" scheme="http://muxfe.github.io/categories/%E7%AE%97%E6%B3%95/"/>
<category term="algorithm" scheme="http://muxfe.github.io/tags/algorithm/"/>
</entry>
<entry>
<title>在 Ubuntu 14 上使用 Git</title>
<link href="http://muxfe.github.io/2015/11/21/using-git-on-ubuntu14/"/>
<id>http://muxfe.github.io/2015/11/21/using-git-on-ubuntu14/</id>
<published>2015-11-21T02:03:20.000Z</published>
<updated>2018-09-27T09:01:19.211Z</updated>
<content type="html"><![CDATA[<h1 id="在-Ubuntu-14-上使用-Git"><a href="#在-Ubuntu-14-上使用-Git" class="headerlink" title="在 Ubuntu 14 上使用 Git"></a>在 Ubuntu 14 上使用 Git</h1><p>之前一直用 GitHub for Windows , GUI 帮我搞定了一切,不用关心背后发生了什么,就可以随意的 commit 和 push 代码。现在换到 Linux 环境之后发现没有那么方便了,全都要自己搞,虽然麻烦,但是学到不少东西。技术的事情还是偷不得懒的。</p><a id="more"></a><h2 id="安装-Git"><a href="#安装-Git" class="headerlink" title="安装 Git"></a>安装 Git</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ sudo apt-get install git</span><br></pre></td></tr></table></figure><p>安装很简单,用 Ubuntu 的 apt-get 就可以了。</p><h2 id="身份认证"><a href="#身份认证" class="headerlink" title="身份认证"></a>身份认证</h2><p>安装了 git 还是不能将代码 push 到自己的 GitHub 上面,因为还没有认证。GitHub 提供了两种主要安全的连接方式,ssh 和 https 。<a href="https://help.github.com/articles/which-remote-url-should-i-use/" target="_blank" rel="noopener">GitHub 官方推荐使用 https</a>.</p><ul><li><strong>ssh</strong> 设置 ssh-key 比较麻烦,但后面使用就方便了</li><li><strong>https</strong> 使用用户名和密码进行身份认证, 每次 push 都要输入</li></ul><h3 id="SSH-认证"><a href="#SSH-认证" class="headerlink" title="SSH 认证"></a>SSH 认证</h3><p>SSH 使用 RSA 非对称加密算法来加密信息,下面生成与 GitHub 服务器通信认证所需的密钥。<br><a href="https://help.github.com/articles/generating-ssh-keys/" target="_blank" rel="noopener">Generateing SSH key</a><br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ ssh-keygen -t rsa -b 4096 -C <span class="string">"grzpjdyc1653@126.com"</span></span><br></pre></td></tr></table></figure></p><p>保存 key 的位置选择默认位置 ( <code>~/.ssh/</code> ) 即可,直接按 Enter 。 然后需要为这个 key 设置一个passphrase(密码),后面会用到。最后就得到一个 key 了。</p><p>加入 key 到 ssh-agent<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh-add ~/.ssh/id_rsa</span><br></pre></td></tr></table></figure></p><p>加入 key 到 GitHub 账户</p><p>首先复制 key<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ sudo apt-get install xclip</span><br><span class="line">$ xclip -sel clip < ~/.ssh/id_rsa.pub</span><br></pre></td></tr></table></figure></p><p>然后找到 GitHub -> Profile -> Settings -> SSH keys -> Add SSH key , 将剪贴板的内容复制到 key 里。保存即可。</p><p>验证是否添加成功<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ ssh -T git@github.com</span><br></pre></td></tr></table></figure></p><p>出现 Hi, username! 字样就是认证成功了。</p><h3 id="使用-SSH-连接-push-代码"><a href="#使用-SSH-连接-push-代码" class="headerlink" title="使用 SSH 连接 push 代码"></a>使用 SSH 连接 push 代码</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> repo</span><br><span class="line">$ git remote <span class="built_in">set</span>-url origin git+ssh://git@github.com/[username]/[repo].git</span><br></pre></td></tr></table></figure><p>这样就不用每次 push 都要输入用户名和密码了。</p><h2 id="提交和同步"><a href="#提交和同步" class="headerlink" title="提交和同步"></a>提交和同步</h2><p>将所有修改的文件加入缓存区<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ git add -A</span><br></pre></td></tr></table></figure></p><p>提交修改<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ git commit -m <span class="string">'message'</span></span><br></pre></td></tr></table></figure></p><p>推送到远程版本库<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ git push</span><br></pre></td></tr></table></figure></p><p>设置 push.default<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ git config --global push.default matching</span><br><span class="line">$ git config --global push.default simple</span><br></pre></td></tr></table></figure></p><ul><li><strong>matching</strong> All branches</li><li><strong>simple</strong> Only the current branch</li></ul><p>从远程版本库同步</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ git pull</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h1 id="在-Ubuntu-14-上使用-Git"><a href="#在-Ubuntu-14-上使用-Git" class="headerlink" title="在 Ubuntu 14 上使用 Git"></a>在 Ubuntu 14 上使用 Git</h1><p>之前一直用 GitHub for Windows , GUI 帮我搞定了一切,不用关心背后发生了什么,就可以随意的 commit 和 push 代码。现在换到 Linux 环境之后发现没有那么方便了,全都要自己搞,虽然麻烦,但是学到不少东西。技术的事情还是偷不得懒的。</p>
</summary>
<category term="工具使用" scheme="http://muxfe.github.io/categories/%E5%B7%A5%E5%85%B7%E4%BD%BF%E7%94%A8/"/>
<category term="ubuntu" scheme="http://muxfe.github.io/tags/ubuntu/"/>
<category term="git" scheme="http://muxfe.github.io/tags/git/"/>
</entry>
<entry>
<title>百度前端面试小记</title>
<link href="http://muxfe.github.io/2015/09/17/baidu-interview/"/>
<id>http://muxfe.github.io/2015/09/17/baidu-interview/</id>
<published>2015-09-17T02:03:20.000Z</published>
<updated>2018-09-27T09:01:19.210Z</updated>
<content type="html"><![CDATA[<p><img src="https://cloud.githubusercontent.com/assets/12498412/9929637/a3beaee0-5d60-11e5-8f8b-3ad2a675778c.jpg" alt="web_interview"></p><h1 id="百度前端面试(一面)"><a href="#百度前端面试(一面)" class="headerlink" title="百度前端面试(一面)"></a>百度前端面试(一面)</h1><p>尽管上周末百度的在线笔试非常不顺,这周一还是被通知第二天参加面试。面试直接安排在面试官所在的宾馆房间里,单独面试,由于只参加了一面,所以只能谈谈一面的感受。</p><p>百度是个比较崇尚技术的公司,一面全程都是技术基础知识和一个编程测试,没有问任何项目经验相关的东西,感觉有点像线下笔试了。</p><p>整个面试持续了一个小时。面试内容整理如下:</p><a id="more"></a><h2 id="自我介绍"><a href="#自我介绍" class="headerlink" title="自我介绍"></a>自我介绍</h2><p>必须的</p><h1 id="HTML相关"><a href="#HTML相关" class="headerlink" title="HTML相关"></a>HTML相关</h1><h3 id="一些标签"><a href="#一些标签" class="headerlink" title="一些标签"></a>一些标签</h3><ul><li>加粗</li><li>上/下标</li><li>pre</li></ul><h3 id="块级元素和行内元素举例及其区别"><a href="#块级元素和行内元素举例及其区别" class="headerlink" title="块级元素和行内元素举例及其区别"></a>块级元素和行内元素举例及其区别</h3><h3 id="DOCTYPE的作用"><a href="#DOCTYPE的作用" class="headerlink" title="DOCTYPE的作用"></a>DOCTYPE的作用</h3><h2 id="CSS布局相关"><a href="#CSS布局相关" class="headerlink" title="CSS布局相关"></a>CSS布局相关</h2><h3 id="元素居中的几种方法"><a href="#元素居中的几种方法" class="headerlink" title="元素居中的几种方法"></a>元素居中的几种方法</h3><h3 id="display分别可以取哪几个值及其相关含义"><a href="#display分别可以取哪几个值及其相关含义" class="headerlink" title="display分别可以取哪几个值及其相关含义"></a>display分别可以取哪几个值及其相关含义</h3><h3 id="bfc-block-formatting-context"><a href="#bfc-block-formatting-context" class="headerlink" title="bfc ( block formatting context )"></a>bfc ( block formatting context )</h3><h3 id="选择器优先级"><a href="#选择器优先级" class="headerlink" title="选择器优先级"></a>选择器优先级</h3><h3 id="盒模型"><a href="#盒模型" class="headerlink" title="盒模型"></a>盒模型</h3><h3 id="CSS预处理"><a href="#CSS预处理" class="headerlink" title="CSS预处理"></a>CSS预处理</h3><h2 id="JavaScript相关"><a href="#JavaScript相关" class="headerlink" title="JavaScript相关"></a>JavaScript相关</h2><h3 id="5个基本类型"><a href="#5个基本类型" class="headerlink" title="5个基本类型"></a>5个基本类型</h3><h3 id="原型链与继承"><a href="#原型链与继承" class="headerlink" title="原型链与继承"></a>原型链与继承</h3><h3 id="判断变量的类型"><a href="#判断变量的类型" class="headerlink" title="判断变量的类型"></a>判断变量的类型</h3><h3 id="setTimeout和setInterval"><a href="#setTimeout和setInterval" class="headerlink" title="setTimeout和setInterval"></a>setTimeout和setInterval</h3><h3 id="事件模型"><a href="#事件模型" class="headerlink" title="事件模型"></a>事件模型</h3><h3 id="ajax跨域"><a href="#ajax跨域" class="headerlink" title="ajax跨域"></a>ajax跨域</h3><h3 id="this指针和改变this指针的几种方法"><a href="#this指针和改变this指针的几种方法" class="headerlink" title="this指针和改变this指针的几种方法"></a>this指针和改变this指针的几种方法</h3><h3 id="一个编程题"><a href="#一个编程题" class="headerlink" title="一个编程题"></a>一个编程题</h3><p>写一个js函数,功能是将一段英文句子的所有单词首字母变成大写。</p><h2 id="HTTP相关"><a href="#HTTP相关" class="headerlink" title="HTTP相关"></a>HTTP相关</h2><h3 id="基本方法"><a href="#基本方法" class="headerlink" title="基本方法"></a>基本方法</h3><h3 id="状态码及其含义"><a href="#状态码及其含义" class="headerlink" title="状态码及其含义"></a>状态码及其含义</h3><h2 id="js库"><a href="#js库" class="headerlink" title="js库"></a>js库</h2><h3 id="jQuery"><a href="#jQuery" class="headerlink" title="jQuery"></a>jQuery</h3><h3 id="d3"><a href="#d3" class="headerlink" title="d3"></a>d3</h3><h3 id="svg和canvas"><a href="#svg和canvas" class="headerlink" title="svg和canvas"></a>svg和canvas</h3><h2 id="提问面试官"><a href="#提问面试官" class="headerlink" title="提问面试官"></a>提问面试官</h2><p>在前端如何选择技术方向深入学习</p><p>答曰:项目实践</p><h2 id="经验教训"><a href="#经验教训" class="headerlink" title="经验教训"></a>经验教训</h2><h3 id="状态"><a href="#状态" class="headerlink" title="状态"></a>状态</h3><p>要自信。</p><h3 id="编程"><a href="#编程" class="headerlink" title="编程"></a>编程</h3><p>编程能力应该是面试官非常看重的一点,这方面我在js的算法上并不十分熟练,导致编程题答得一塌糊涂。非常遗憾。</p><h3 id="沟通"><a href="#沟通" class="headerlink" title="沟通"></a>沟通</h3><p>每个问题应该仔细沟通然后理解,再作答。</p><h3 id="基础"><a href="#基础" class="headerlink" title="基础"></a>基础</h3><p>一定要扎实。</p><p>一定要扎实。</p><p>一定要扎实。</p><p>(重要的话说三遍)</p><h3 id="简历"><a href="#简历" class="headerlink" title="简历"></a>简历</h3><p>我的简历上并无十分突出的东西,但是简洁、一目了然。还写上了GitHub的地址,虽然发现自己在GitHub上很水,我想面试官应该看了,这是一把双刃剑啊。</p><h2 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h2><p>总体来说,我答得有些问题并不十分准备,甚至是错误的,反映出我在项目实践方面的欠缺和基本功的不扎实。在平时项目中,对于很多知识或者问题,仅仅通过百度/google出答案然后就不再深究,也没有积累,是非常不好的。</p><p>相比今年7月份参加的阿里校招实习生的面试,我觉得自己已经进步了很多,从之前的方向不定和迷茫中渐渐找到了自己真正喜欢的东西。缺点是没有持续的学习和编码练习。</p><p>以此自勉。</p>]]></content>
<summary type="html">
<p><img src="https://cloud.githubusercontent.com/assets/12498412/9929637/a3beaee0-5d60-11e5-8f8b-3ad2a675778c.jpg" alt="web_interview"></p>
<h1 id="百度前端面试(一面)"><a href="#百度前端面试(一面)" class="headerlink" title="百度前端面试(一面)"></a>百度前端面试(一面)</h1><p>尽管上周末百度的在线笔试非常不顺,这周一还是被通知第二天参加面试。面试直接安排在面试官所在的宾馆房间里,单独面试,由于只参加了一面,所以只能谈谈一面的感受。</p>
<p>百度是个比较崇尚技术的公司,一面全程都是技术基础知识和一个编程测试,没有问任何项目经验相关的东西,感觉有点像线下笔试了。</p>
<p>整个面试持续了一个小时。面试内容整理如下:</p>
</summary>
<category term="随笔" scheme="http://muxfe.github.io/categories/%E9%9A%8F%E7%AC%94/"/>
<category term="interview" scheme="http://muxfe.github.io/tags/interview/"/>
</entry>
</feed>