├── .gitignore ├── README.md ├── 安卓设备scrolltop方法无法正常工作.md ├── package.json ├── 关于chrome报错netERR_INCOMPLETE_CHUNKED_ENCODING的解决方案.md ├── 前端兼容性问题汇总.md ├── 从极客公园视频感慨每个产品的背后.md ├── iOS不兼容position-fixed属性.md ├── 某只程序猿的扇贝英语打卡500天有感.md ├── 使用clip-path制作简单的动画效果.md ├── ssh_exchange_identification: Connection closed by remote host 报错问题.md ├── 微信手机调试服务.md ├── 2016.11 - Do whatever you do intensely.md ├── type-number非法值的一些探究及拓展.md ├── 【译】使用 currentColor 属性写出更好的 CSS 代码.md ├── 毕业六个月后回顾我的前端路暨2015总结2016新年祈愿.md ├── 2016.10 - 往日的伤秋情怀也在这短暂的秋天里变得没影了.md ├── 我的 2016 总结暨 2017 新年祈愿.md ├── 【译】如何编写避免垃圾开销的实时 Javascript 代码.md ├── 微信内置浏览器不支持gzip压缩及gzip模块配置简述.md ├── 【译】JavaScript 变量的生命周期:为什么 let 不存在变量提升.md ├── 【译】UI 的黑暗面!暗色背景的优势.md ├── 【个人总结】正则表达式语法及常用正则.md ├── 【原创翻译】有哪些信号能让我知道我在一家『没落的』公司工作.md ├── npm left-pad模块删除事件始末梳理及看法及应对依赖风险处理方法.md ├── Git日常使用提交信息参考规范及总结梳理.md ├── 由一次浏览器控件重绘问题详谈浏览器重排、重绘机制.md ├── 360 & 美团前端社招面经及部分面试题.md ├── 【译】JSON Web Tokens (JWT) 与 Sessions.md ├── 【译】对一行混淆 JS 代码的逆向分析过程.md ├── githug游戏推介及参考答案『55关版』.md ├── 使用npm scripts构建项目.md ├── 【译】基于 Meteor1.3 和 React 创建简单 App.md └── 某前端群题目答案参考.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # articles 2 | blog articles with md version 3 | -------------------------------------------------------------------------------- /安卓设备scrolltop方法无法正常工作.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 安卓设备 scrolltop 方法无法正常执行 3 | date: 2015-10-09 14:37:26 4 | categories: 兼容性 5 | tags: [兼容性,移动端,Android] 6 | --- 7 | 8 | ### 问题情况 9 | 今天遇到一个问题,在 Android 设备下 `scrollTop()` 方法无法正常执行。 10 | 11 | ### 解决办法 12 | 相关参考了一些解决办法之后,解决办法大致如下: 13 | 14 | - CSS + JS: 15 | 原理在于这个问题发生在 `overflow` 属性为 `scroll` 时 16 | 17 | ``` css 18 | .androidFix { 19 | overflow:hidden !important; 20 | overflow-y:hidden !important; 21 | overflow-x:hidden !important; 22 | } 23 | 24 | ``` 25 | 26 | ``` js 27 | $(yourSelector).addClass("androidFix").scrollTop(0).removeClass("androidFix"); 28 | ``` 29 | 30 | ### 相关参考 31 | 一篇不错的各浏览器内核使用 `scrollTop` 方法介绍:[如何正确的获取scrollTop/scrollLeft的值](http://bbs.csdn.net/topics/340198399) 32 | 33 | 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "articles", 3 | "version": "1.0.0", 4 | "description": "articles in qcyoung.com", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/yangzj1992/articles.git" 12 | }, 13 | "author": "yangzj1992", 14 | "license": "ISC", 15 | "bugs": { 16 | "url": "https://github.com/yangzj1992/articles/issues" 17 | }, 18 | "homepage": "https://github.com/yangzj1992/articles#readme", 19 | "devDependencies": { 20 | "cz-conventional-changelog": "^1.1.6" 21 | }, 22 | "config": { 23 | "commitizen": { 24 | "path": "./node_modules/cz-conventional-changelog" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /关于chrome报错netERR_INCOMPLETE_CHUNKED_ENCODING的解决方案.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 关于 Chrome 报错 net::ERR_INCOMPLETE_CHUNKED_ENCODING 的解决方案 3 | date: 2015-09-11 22:55:11 4 | categories: bug 5 | tags: [Chrome,JSON,Debug] 6 | --- 7 | 8 | ## 背景 9 | 今天遇到一个 bug ,这个 bug 很神奇,在 Chrome 下刷新项目页时会报错 `net::ERR_INCOMPLETE_CHUNKED_ENCODING` 而显示不出网页,在 Safari 和 Firefox 下正常。查了一下这个错误的网上的解决方案。众说纷纭比较多,由于这个 bug 着实查着改了很久..这里进行一个总结,来帮助可能被坑的后来人。 10 | 11 | ## bug 描述及解决办法 12 | 在某项目页中,后台传给我了一串比较长的 json 数据,我在处理这些数据,刷新页面时 Chrome 意外报错 `net::ERR_INCOMPLETE_CHUNKED_ENCODING`。页面加载不了 DOM 结构。在 Firefox 及 Safari 上加载正常。 13 | 14 | 在调试后发现,报错原因在于 json 数据在 Chrome 接收的过程中会被随机截断,不能加载完全的 json 数据。导致 json 结构报错。 15 | 16 | ![报错提示](http://qcyoung.qiniudn.com/qcyoung/关于chrome报错netERR_INCOMPLETE_CHUNKED_ENCODING的解决方案/chromeERR_INCOMPLETE_CHUNKED_ENCODING.png) 17 | 18 | 这里参考我的尝试步骤以及网上的部分可行的办法来推荐尝试: 19 | 20 | 1.关闭杀毒软件 21 | 22 | 2.关闭 Chrome 高级设置里的 “预提取资源,以便更快速的加载网页” 23 | 24 | 3.关闭 Chrome 扩展程序或停用代理类扩展 25 | 26 | 4.设置 header 报表头 content-length 27 | 28 | ``` php 29 | 32 | ``` 33 | 34 | 5.nginx fastcgi buffer 的设置 35 | 36 | 6.nginx 打开 gzip 37 | 38 | -------------------------------------------------------------------------------- /前端兼容性问题汇总.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 前端兼容性问题汇总 3 | date: 2015-10-15 12:35:23 4 | categories: 兼容性 5 | tags: [前端知识,兼容性] 6 | --- 7 | 8 | ## 简述 9 | 作为前端一名晚辈,很遗憾没有赶上调试 IE6 的日子 `~\(≧▽≦)/~` 奈何各浏览器大佬毕竟现在还是不肯一起干,非自己搞标准,浏览器各个版本还d都自己搞内讧。所以前端兼容性问题注定还是一场长期艰苦的抗战。。所以这里自己记一下遇到的一些兼容性问题等等,供大家参考。 10 | 11 | 从浏览器内核的角度 来看,浏览器兼容性问题可分为以下三类: 12 | 13 | 1. 渲染相关:和样式相关的问题,即体现在布局效果上的问题。 14 | 2. 脚本相关:和脚本相关的问题,包括 JavaScript 和 DOM、BOM 方面的问题。对于某些浏览器的功能方面的特性,也属于这一类。 15 | 3. 其他类别:除以上两类问题外的功能性问题,一般是浏览器自身提供的功能,在内核层之上的。 16 | 17 | 尽管各位浏览器大佬对于这个问题有不可推卸的责任,然而确实作为一名前端程序员,保证自己的代码足够规范是更为重要的。 18 | 19 | **不够规范的代码会使不兼容现象更加突出,一个优秀的前端工程师不应该写出不规范的代码** 20 | **不够规范的代码会使不兼容现象更加突出,一个优秀的前端工程师不应该写出不规范的代码** 21 | **不够规范的代码会使不兼容现象更加突出,一个优秀的前端工程师不应该写出不规范的代码** 22 | 23 | **我们应当做的就是尽量了解标准,熟悉各浏览器的Bug和特性,灵活设计页面功能,这样才可以最大程度有效的避免各浏览器兼容性问题。** 24 | 25 | ## PC-WEB 26 | 27 | ## 移动端 28 | 29 | ### Android 30 | 31 | - [安卓设备scrolltop()方法无法正常执行](http://qcyoung.com/2015/10/09/%E5%AE%89%E5%8D%93%E8%AE%BE%E5%A4%87scrolltop%E6%96%B9%E6%B3%95%E6%97%A0%E6%B3%95%E6%AD%A3%E5%B8%B8%E5%B7%A5%E4%BD%9C/) 32 | 33 | ### iOS 34 | 35 | - [iOS不兼容position:fixed属性](http://qcyoung.com/2015/10/17/iOS%E4%B8%8D%E5%85%BC%E5%AE%B9position-fixed%E5%B1%9E%E6%80%A7/) -------------------------------------------------------------------------------- /从极客公园视频感慨每个产品的背后.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 从极客公园视频感慨每个产品的背后 3 | date: 2016-09-19 12:55:18 4 | categories: 产品 5 | tags: [产品,team,我的生活,个人感受] 6 | --- 7 | 8 | ## 视频 9 | 10 | ### 2011年极客公园创新大会 11 | 12 | 13 | ### 2013年极客公园创新大会 14 | 15 | 16 | ## 感慨 17 | 前两天不经意间又看到了极客公园几年前发布的创新大会的宣传视频。不禁还是有些感慨。 18 | 19 | 当时我还在读大学,看到的是 2013 年版的极客公园宣传视频,后来又看到了 2011 年版的。这两个视频里各个团队所展现的青春与活力一直是我当时很向往的。在当时,这些产品也或多或少算是一时风头的新兴人气产品。然而随着时间的流逝,也正如视频里所说的那样:很少有产品能一直流行。 20 | 21 | 这里面的一些产品,可能有的也真的只是昙花一现,能坚持到现在还绽放傲人成绩的并不多。在工作之后也是更深刻的懂得了每个产品的背后真的是许多研发产品运营团队的同事们的共同努力和支撑所维系的。做好一个让公司满意、让用户满意的产品真的很不容易。 22 | 23 | 不管它们最终的结局时怎样,是犯了哪些错误导致了产品的落幕,然而在当时那几年,它们确实是同类产品中的佼佼者,我们的世界也确实因为它们的存在而与众不同过。 24 | 25 | 刚实习时,老大也曾对我说过,一个优秀的工程师一定要对自己手上的产品负责。在这里也再次勉励自己,希望在自己的研发生涯里能尽可能的让自己所负责的产品尽可能的更优秀。 26 | 27 | ## 附注 28 | 29 | 这里也晒一张我所在的团队的照片,但也是去年12月的照片了。之后团队因为公司和个人的原因也换组、调离、出出入入了不少人。但觉得至少这张照片很能展现当时我们团队阳光、青春的模样,也以此作纪念。 30 | 31 | ![团队合照](http://qcyoung.qiniudn.com/qcyoung/weixin_mall_20151203.jpg) 32 | 33 | 最后,两个视频的 BGM 也很不错,很喜欢它们的歌词和旋律。分别是在格莱美获奖的 Rascal Flatts -《Bless The Broken Road》和 Taylor Swift -《Long Live》 34 | -------------------------------------------------------------------------------- /iOS不兼容position-fixed属性.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: iOS不兼容position:fixed属性 3 | date: 2015-10-17 17:33:32 4 | categories: 兼容性 5 | tags: [兼容性,移动端,iOS] 6 | --- 7 | 8 | ### 问题情况 9 | 在移动端开发过程中如果在头部或底部设置 `position:fixed` 的元素,可能会在 ios8 以下的系统中出现以下问题,当用户进行输入时系统键盘激活,此类 fixed 元素会出现位置浮动问题。类似如下图所示: 10 | ![position:fixed](http://qcyoung.qiniudn.com/qcyoung/iOS不兼容position-fixed属性/ios_position_fixed.jpeg) 11 | 12 | ### 解决办法 13 | 解决办法大致如下: 14 | 确保自己的页面已引入浏览器适应性 `meta` 15 | 16 | ``` html 17 | 18 | ``` 19 | 20 | - CSS + JS: 21 | 原理在于这个问题发生在 `overflow` 属性为 `scroll` 时 22 | 23 | ``` css 24 | .fixfixed{ 25 | position: absolute; 26 | ... 27 | } 28 | ``` 29 | 30 | ``` js 31 | var u = navigator.userAgent, app = navigator.appVersion; 32 | var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端 33 | 34 | if (isIOS) { 35 | $(document).on("focus", "input", function () { 36 | $(yourselector).addClass("fixfixed"); 37 | }).on("focusout", "input", function () { 38 | $(yourselector).removeClass("fixfixed"); 39 | }); 40 | } 41 | ``` 42 | 43 | 或使用 `iscroll.js` 库。 44 | 45 | ### 额外参考 46 | 另外 iOS 系统中目前针对 fixed 的元素还会出现闪烁的现象,具体表现为呼出系统键盘,元素在一定时间后才回归原位。 47 | 48 | 具体的移动端 fixed 兼容性情况原因在阿里的支付宝开发经验中有详细讲过[无线Web开发经验谈](http://am-team.github.io/amg/dev-exp-doc.html) 49 | 50 | - iOS 系统: 在 iOS5 之后,iOS 才正式开始支持 fixed 的布局,在 iOS5 之前,苹果处于性能上的考虑,并没有实现,因此在使用 fixed 的时候,需要注意你所做的项目对 iOS 的版本最低支持的版本,不过即使 iOS5 之后,开始支持 fixed 属性,在实际使用中,还是有很多小坑在,国外专门有个网页再说 iOS 的 fixed 的问题。提供以下地址,可供参考:[iOS-fixed issues](http://remysharp.com/2012/05/24/issues-with-position-fixed-scrolling-on-ios/)。比较安全的做法是,在固定的布局里面,尽可能保持里面的结构简单,不要出现过于复杂的布局,一般 app 的头部和尾部可以使用 fixed 属性。 51 | - Android 系统 Android 系统在 2.1 之后,就已经开始支持 fixed,不过由于各个厂商对于 fixed 的实现不同,2.1 和2.2 对于 fixed 的支持不是很好,在滚动的时候会出现闪动,消失、位移等各种渲染问题。2.3 之后的版本,fixed 的问题相对少一些,不过在个别厂商的手机上也会出现各种渲染问题。从 4.x 开始,fixed 的表现比较好。因此如果在 Android 上需要 fixed 的效果,需要综合评判其效果。 -------------------------------------------------------------------------------- /某只程序猿的扇贝英语打卡500天有感.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 某只程序猿的扇贝英语打卡 500 天有感 3 | date: 2016-07-18 12:13:05 4 | categories: 英语 5 | tags: [英语,扇贝英语] 6 | --- 7 | 8 | 作为一名学渣..尤其是英语学渣..在 500 天打卡日到来的时候不禁还是想写点啥..所以在此记录一下自己打卡 500 天的经历和想法。 9 | 10 | ## 初衷、过程及愿望 11 | 在上周日 2016.7.10 我的英语打卡到达了第 500 天。推算 500 天前大概是 2015 年 3 月之前。当时还是寒假,我决定在毕业前的最后一次六级考试中好好刷个分..(之前基本是裸考,顺便这最后一次一起陪我们宿舍某个一直没有过六级的哥们考完他最后一次的六级考试 Ծ ̮ Ծ)。在看了一些网上推荐的英语学习方法后,最后选择了觉得比较适合我的扇贝英语系列(扇贝全系列 APP)。 12 | 13 | 这里简单介绍并安利一下选择扇贝的主要原因: 14 | 15 | 1. 它的系列 APP 很全,基本上选择了它你就不需要在安装其他的英语 APP 了 16 | 2. 扇贝小组里的学习氛围很好,尤其是看到各路考托考雅思以及初、高中同学们的努力打卡的记录和笔记真的还是很有触动的。 17 | 3. 扇贝单词 APP 中有很多网友上传的单词书,基本包含了各类专业常见单词。作为程序员目前我就已经背过了专业类的:软件开发及测试、离散数学、人月神话、科技常用英语等单词书。对自己平时的工作、阅读真的起到了一定帮助。 18 | 4. 扇贝 APP 相比其他同类 APP 并不流氓,它相当注重用户体验。这里上张图大家一看就懂了。 19 | 20 | ![扇贝 APP 权限](http://qcyoung.qiniudn.com/qcyoung/shanbayapp_permissions.jpg) 21 | 22 | 然后说下我的英语成绩,说实话这是我学业生涯以来最惭愧的一科。小时候父母工资拮据时都还给我报了一个月 80 块钱的英语学习班(那时工资好像才几百元)。因此小时候还能混进英奥班学习,然而后来淘气加偏科,因此英语成绩相对的也就慢慢掉下来了。记得高考前几乎每一次英语考试中选词填空好多都是蒙的。最后高考时英语也才 100 多分。。现在想起来确实觉得实在是对不住小时候的高价英语补习班。。 23 | 24 | 后来在大学中慢慢认识到了英语的重要性,但确实大学期间也还是没有很大程度的投入精力去学习英语。所以当时也是借此为契机,准备在毕业后养成学习英语的习惯(也主要是每天学习的习惯)。而且身为一名程序猿,英语能力确实一定程度上也是自己吃饭的技能之一啊..(想起之前知乎上看到的一个梗 —— 问:2016 年,中国的前端在关注什么?答:关注国外的前端..)。因此我的梦想也是能有朝一日能够可以做到流利的与国外朋友或同行进行英语交流。出国不存在任何语言障碍的水平,这样我也就心满意足了。(马云那样一半的英语交流能力也就够吧..) 25 | 26 | ## 打卡 500 天的成果 27 | 28 | 首先需要说明,在开始打卡前我的英语水平差不多就是六级低分飘过的水平..(再高水平的英语考试目前还没考过..)然而在扇贝训练后的那次最后一次六级考试却是华丽丽的刷分失败..(没过线的水平..)当时还跟朋友说,我天天背单词,背了 100 多天也居然还是没过线(╯‵□′)╯︵┻━┻..但说实话在毕业后又坚持下来的这 300 多天来看,我觉得我的英语还是有进步的。(这里真的不虚!) 29 | 30 | 目前我每天的英语学习计划是 **50 单词 + 10 炼句 + 2 阅读 + 5 听力** (最近扇贝系列也刚出了口语系列,但目前我还没有把它加入每日计划的打算)。每天花费的时间平均大概在 30--45 分钟之间,基本上是可以接受的,也并不耽误正常工作休息时间。每天睡觉前看完 2 篇阅读,上班的路上背完单词和炼句,午休时间做完听力。基本上就是我每天正常的扇贝学习时间。 31 | 32 | 到 500 天打卡日为止累计学习单词数 10615 个,掌握单词数 10017 个,看完了 4 本英文原著。其他具体的学习内容感觉用扇贝的徽章图也比较好描述。。 33 | 34 | ![扇贝 500 天](http://qcyoung.qiniudn.com/qcyoung/shanbay500.jpg) 35 | 36 | 其实打卡这件事跟坚持做其他事的差别并不大(健身、读书、听 VOA 等等),只要能真正的坚持下来肯定是不错的,我觉得这 500 天下来我无论是从学习的劲头上还是习惯上来说确实让我更多的产生了一些自信。相信自己之后在遇到更麻烦的挑战时也会敢于去尝试解决并相信自己能够做成。 37 | 38 | 谨以此日志记录这 500 天的扇贝打卡,并祝愿自己英语能力的梦想能早日实现。 39 | 40 | 更新:前两天看到一篇讲[程序员英语学习](http://blog.jobbole.com/101359/)的文章,感觉写的很不错,在此进行分享。 -------------------------------------------------------------------------------- /使用clip-path制作简单的动画效果.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 使用 clip-path 制作简单的动画效果 3 | date: 2015-11-18 16:48:18 4 | categories: web动画 5 | tags: [CSS,web动画] 6 | --- 7 | 8 | ## 介绍 9 | 今年4月左右有一个比较火的网站 species-in-pieces 在前端圈里比较出名,[点击这里查看](http://species-in-pieces.com/#) 10 | ![species-in-pieces效果](http://qcyoung.qiniudn.com/qcyoung/使用clip-path制作简单的动画效果/poster-detail-2.png) 11 | 它的原理就是运用了 `clip-path` 来进行实现。在《species in pieces》中每个动物的组成节点如下所示 12 | 13 | ``` html 14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | . 22 | . 23 | 省略若干30个 24 | . 25 | . 26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | ``` 34 | 35 | 对应的 css 文件如下: 36 | 37 | ``` css 38 | .shard-wrap { width: 100%; height: 100%; position: absolute; transition: .5s; z-index: 2; } 39 | /* crow 乌鸦的图形描述 */ 40 | .crow .shard-wrap:nth-child(1) .shard { 41 | -webkit-clip-path: polygon(20% 50%,25% 52.4%,11.5% 54.5%); 42 | background-color: #2C323D 43 | } 44 | .crow .shard-wrap:nth-child(2) .shard { 45 | -webkit-clip-path: polygon(14.7% 47.5%,35.2% 50.2%,25% 52.5%); 46 | background-color: #63676F 47 | } 48 | .crow .shard-wrap:nth-child(3) .shard { 49 | -webkit-clip-path: polygon(22.9% 44.5%,35.2% 50.2%,25% 48.9%); 50 | background-color: #0F1622 51 | } 52 | /* 53 | . 54 | . 55 | 省略 56 | . 57 | . 58 | */ 59 | .crow .shard-wrap:nth-child(29) .shard { 60 | -webkit-clip-path: polygon(61.7% 44.7%,64.4% 44%,65.1% 36.2%); 61 | background-color: #0f1622 62 | } 63 | .crow .shard-wrap:nth-child(30) .shard { 64 | -webkit-clip-path: polygon(78.5% 21.5%,76.3% 23.7%,74.6% 22.5%); 65 | background-color: #0f1622 66 | } 67 | ``` 68 | 69 | 这样利用 30 个三角形,每个三角形代表一对 `.shard-wrap>.shard` 节点, 来进行拼接展现,所有的图形描述由 `:nth-child` 伪类选择器来控制形状。 70 | 71 | ## 举个栗子 72 | 这里做了一个简单的 demo,鼠标滑到界面上 github 小猫就会发生变化(仅支持 webkit 内核浏览器) 73 | 74 | 75 | 76 | ## 拓展 77 | 78 | 此外 `clip-path` 属性也可以实现 3D 模型渲染的效果,如下图所示: 79 | 80 | ![3D动画效果1](http://qcyoung.qiniudn.com/qcyoung/使用clip-path制作简单的动画效果/snapshot.gif) 81 | 82 | ![3D动画效果2](http://qcyoung.qiniudn.com/qcyoung/使用clip-path制作简单的动画效果/6252205cgw1eqmyg50fsjg208e0a44mf.gif) 83 | 84 | 关于更详细的描述,这里有一篇很详细的博文可以参考[网易萝卜的博文](http://leeluolee.github.io/2015/04/01/render-3d-use-clip-path/) 85 | 86 | -------------------------------------------------------------------------------- /ssh_exchange_identification: Connection closed by remote host 报错问题.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ssh_exchange_identification:Connection closed by remote host 报错问题 3 | date: 2016-08-28 22:55:11 4 | categories: bug 5 | tags: [GitHub,SSH,Debug] 6 | --- 7 | ## 错误情况 8 | 今天下午,我莫名无法向 GitHub push 代码了...最终从5点多调试到晚上11点半..感觉略坑..遂记录如下.. 9 | 10 | 报错内容: 11 | 12 | ``` bash 13 | fatal: unable to access 'https://***.git/': SSL peer handshake failed, the server most likely requires a client certificate to connect 14 | ``` 15 | 16 | ``` bash 17 | ssh_exchange_identification: Connection closed by remote host 18 | fatal: Could not read from remote repository. 19 | ``` 20 | 21 | ## 解决过程 22 | 23 | 首先简单搜了一下发现可能是 ssh key 的问题..遂重新按照[官方文档](https://help.github.com/articles/generating-an-ssh-key/)重新生成 ssh key。并再添加 key 后执行 `ssh -T git@github.com` 来测试,仍然报错: 24 | `ssh_exchange_identification: Connection closed by remote host` 25 | 26 | 执行`ssh -vT git@github.com`输出记录如下: 27 | 28 | ``` doc 29 | $ ssh -vT git@github.com 30 | OpenSSH_6.9p1, LibreSSL 2.1.8 31 | debug1: Reading configuration data /etc/ssh/ssh_config 32 | debug1: /etc/ssh/ssh_config line 21: Applying options for * 33 | debug1: Connecting to github.com [1.111.11.111] port 22. 34 | debug1: Connection established. 35 | debug1: identity file /Users/yangzhongjing/.ssh/id_rsa type 1 36 | debug1: key_load_public: No such file or directory 37 | debug1: identity file /Users/yangzhongjing/.ssh/id_rsa-cert type -1 38 | debug1: key_load_public: No such file or directory 39 | debug1: identity file /Users/yangzhongjing/.ssh/id_dsa type -1 40 | debug1: key_load_public: No such file or directory 41 | debug1: identity file /Users/yangzhongjing/.ssh/id_dsa-cert type -1 42 | debug1: key_load_public: No such file or directory 43 | debug1: identity file /Users/yangzhongjing/.ssh/id_ecdsa type -1 44 | debug1: key_load_public: No such file or directory 45 | debug1: identity file /Users/yangzhongjing/.ssh/id_ecdsa-cert type -1 46 | debug1: key_load_public: No such file or directory 47 | debug1: identity file /Users/yangzhongjing/.ssh/id_ed25519 type -1 48 | debug1: key_load_public: No such file or directory 49 | debug1: identity file /Users/yangzhongjing/.ssh/id_ed25519-cert type -1 50 | debug1: Enabling compatibility mode for protocol 2.0 51 | debug1: Local version string SSH-2.0-OpenSSH_6.9 52 | ssh_exchange_identification: Connection closed by remote host 53 | ``` 54 | 55 | 这里面`/Users/yangzhongjing/.ssh/id_rsa` 这个文件是存在的。不知道为什么会报:`key_load_public: No such file or directory`.. 56 | 57 | 后来在网上搜了很多内容,执行了以下方法: 58 | - `vim /etc/hosts.allow` 添加 `sshd: ALL` 59 | - `ssh-add ~/.ssh/id_rsa` 60 | - 调整了 `/etc/ssh/sshd_config ` 中的 `MaxSessions 10 ` 调大 61 | - 删除 `~/.ssh`目录重新生成ssh key 62 | 63 | 然而并没有什么卵用... 64 | ## 最终原因.. 65 | 66 | 最后在茫茫文海中搜到了一篇关于路由器端口禁用也可能会导致这个问题的留言..突然想到昨天我自己也调试了家里的路由器,添加了一些路由器插件...赶紧切到路由器后台,发现了幕后凶手... 67 | 68 | ![](http://qcyoung.qiniudn.com/qcyoung/shijietong.png) 69 | 70 | ![](http://qcyoung.qiniudn.com/qcyoung/shijietongdetail.png) 71 | 72 | 最终..禁用插件,重启路由。问题解决... 73 | 74 | 此种解决方案具有通用型,很多时候并不是ssh-key 的问题,而是网络问题。比如Global的VPN,Shadowsocks 都有可能导致这类错误。 75 | 76 | SO...后来人可以试试上面列举到的搜索的方法..或者看看你的网络设置,一般可以解决这一报错问题.. 77 | 78 | -------------------------------------------------------------------------------- /微信手机调试服务.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 微信手机端官方推荐调试服务————微信、手Q、Qzone之x5内核inspect调试解决方案 3 | date: 2015-09-06 14:19:48 4 | categories: 移动web 5 | tags: [微信,inspect,移动端] 6 | --- 7 | ## 更新(2016.1.11) 8 | 1 月 11 号微信推出了新版调试工具,告别这复杂的配置,试试新版[调试工具](http://mp.weixin.qq.com/wiki/10/e5f772f4521da17fa0d7304f68b97d7e.html)吧。 9 | 10 | 11 | ## 过程转载+记录补充 12 | 13 | 微信平台调试之麻烦各位同学应该都是有目共睹的,今天在遇到问题时无意间发现了官方推荐的调试解决方案,在安装完成后感觉不错,所以这里记录一下安装过程,并把遇到的一些问题也记录下来,供可能以后遇到问题的同学查看。 14 | 15 | 调试原理如下图:[原帖地址](http://bbs.mb.qq.com/thread-243399-1-1.html?fid=93) 16 | 17 | ![微信调试原理](http://qcyoung.qiniudn.com/qcyoung/微信手机调试服务/微信inspector.png) 18 | 19 | 具体过程大致与原帖相似。 20 | 21 | 1、安装微信最新版本 22 | 23 | 2、下载 TbsSuiteNew.apk,安装到手机中。[下载地址](http://res.imtt.qq.com///tbs_inspect/TbsSuiteNew.zip),打开界面如下: 24 | 25 | ![TbsSuiteNew.apk](http://qcyoung.qiniudn.com/qcyoung/微信手机调试服务/tbs工具集.png) 26 | 27 | 2.1)下一步:【如果之前有安装过 tbs,那么登录微信后找到自己,聊天窗口输入//deletetbs,点发送】 28 | 29 | ![TbsSuiteNew.apk](http://qcyoung.qiniudn.com/qcyoung/微信手机调试服务/Delete原有tbs.jpeg) 30 | 31 | 2.2)下一步:下载 tbs 调试包 32 | 33 | ![TbsSuiteNew.apk](http://qcyoung.qiniudn.com/qcyoung/微信手机调试服务/tbs安装1.png) 34 | 35 | 【注:这里应用包名分别对应关系为——— 微信:com.tencent.mm,qq:com.tencent.mobileqq,qq空间:com.qzone】 36 | 37 | 2.3)下一步:启动应用触发 tbs 静默安装 38 | 39 | ![TbsSuiteNew.apk](http://qcyoung.qiniudn.com/qcyoung/微信手机调试服务/tbs安装2.png) 40 | 41 | 3、登录微信,用微信访问一个页面,停留1分钟左右,目的是让微信来静默安装刚导入进去的 tbs_20150526_021257_inspector.apk 包 42 | 43 | 4、页面验证 tbs 是否安装成功(未成功会有弹窗,如果能继续下去,一般就是安装成功了,或者也可以去 tbs 工具集菜单,查看 tbs 信息查询) 44 | 45 | ![TbsSuiteNew.apk](http://qcyoung.qiniudn.com/qcyoung/微信手机调试服务/tbs安装3.png) 46 | 47 | ![TbsSuiteNew.apk](http://qcyoung.qiniudn.com/qcyoung/微信手机调试服务/tbs-status.jpg) 48 | 49 | 5、debug 关联 Chrome inspect 50 | 51 | 1. 下载附件 inspector_client20150401.zip 工具,解压到指定目录: 52 | [附件包下载地址](http://res.imtt.qq.com///tbs_inspect/wx_sq_webview_debug.zip) 53 | 54 | 2. 下载安装 python3 55 | 56 | 3. 下载 ADB,其是 Android 手机中非常重要的一个运行器,root 等等都需要它。而它,也是帮助 Android 手机和 Mac 通讯的工具和桥梁。Mac 上默认是没装的,搞定 ADB 之前,你先要去下载一个 Android 的 `SDK Manager`,[地址](http://developer.android.com/sdk/installing/index.html)。下载里面的 stand-alone sdk tools。 57 | 58 | 解压缩,打开 `android-sdk-macosx/tools`,里面有个 Android 的可执行文件,双击它。通过这里可以下载各种版本的 Android SDK,你默认会装好里面的 Android SDK Tools,而你需要的是安装其下面的 Android SDK platform-tools!装好后,你会发现 android-sdk-macos 下面,多了一个文件夹 platform-tools,ADB 就在里面。 59 | 60 | 接下来,配一下ADB的环境变量。打开终端,回到根目录,输入 `vim ~/.bash_profile`。照着 python,输入 ADB 的环境变量吧。`PATH="/Users/Adrian/Work/worktools/android-sdk-macosx/platform-tools:${PATH}"`。保存退出。 61 | 62 | 输入 `source .bash_profile`,执行一下环境变量,然后输入下 `adb`,是不是出现了一堆的参数说明?OK,那 ADB 的环境变量就配置好了。 63 | 64 | 拿出数据线,插上手机,连接电脑,输入 `adb devices`,如果出现了类似下面的代码,说明,你离成功又进了一步。 65 | 66 | ``` bash 67 | \* daemon not running. starting it now on port 5037 * 68 | \* daemon started successfully * 69 | List of devices attached 70 | NX505J device 71 | ``` 72 | 73 | 4. 解压 inspector_client20150401.7z 包到指定目录,执行 `python inspector.py`,【如果您本机已经安装了 adb,建议使用 python inspectory --adb YOUR/ADB/PATH】如图 74 | ![TbsSuiteNew.apk](http://qcyoung.qiniudn.com/qcyoung/微信手机调试服务/tbs-success.png) 75 | 如果权限报错,添加权限即可。 76 | 77 | 5. 手机用微信打开页面,同时 pc 电脑打开 Chrome 浏览器,输入[http://localhost:9222/](http://localhost:9222/),看到对应的区块 78 | 点击进去终于可以在微信页面上自由调试了,和 Chrome 调试就是那么像。 79 | ![TbsSuiteNew.apk](http://qcyoung.qiniudn.com/qcyoung/微信手机调试服务/tbs-webview.png) 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /2016.11 - Do whatever you do intensely.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2016.11 - Do whatever you do intensely 3 | date: 2016-12-05 13:57:19 4 | categories: 我的生活 5 | tags: [我的生活,月记,音乐] 6 | --- 7 | 8 | ## 工作相关 9 | 10 | 这个月主要是继续收尾完善 CMS 并做了一个感恩节主题的 H5 项目,同时由于 CMS 这个项目在前期规划上的交流问题,公司在 C 端方向也开发了 CMS 项目导致在开发资源上一定程度存在重复开发现象,于是上面想把这两个项目合并,合并开发一套 CMS 后台来共同服务我们 B 端和 C 端方向的前台。 11 | 12 | 而这也算是毕业以来第一次遇到这种算的上是『公司 + 部门』级别的项目合并(一定意义上的跨公司,但是在公司的技术体系上却又并不是分隔的很独立)。中间各种过程不表了。由于两边前端的技术栈比较统一,所以前端合并的开发量主要也就在接口的联调、组件展示逻辑的兼容、以及埋点逻辑等方向上的处理。相比于这个项目的开发来说,项目的复杂点更多的是管理决策的 PK 和方案的确定吧。。 13 | 14 | (就像美团和点评的合并吧,这种项目合并中间必定会或多或少[伤害其中一个团队或是Team](http://info.3g.qq.com/g/index5/ttnews/yidian.jsp?aid=yidian&id=tech_20151121032832&g_f=23748),站在公司的角度上肯定希望最大程度的节约开发资源。所以不太会容忍多个 Team 分别开发各自功能却近似的项目。但是在两边的项目都起到一定规模的时候才发觉。。。确实很伤团队的士气,而作为个人最好得便是在开发层面上自然地尽可能做好自己负责的项目,这样即便当你遇到这种项目资源重复,需要合并时。只要做到比别人的好。这样合并时更多的就会以你的开发方案和代码为主,让别人基于你的代码架构上来开发。你的工作成果也就会得到肯定并且在一定程度上不会浪费) 15 | 16 | 另外感恩节的 H5 项目主要就是一个针对每个商户的总结性的商户数据 H5 统计展示并最后分享领券的一个互动活动页。除了工期比较紧外,技术上难点并不多,于是也就比较快速的用 jq 来实现具体的移动端的展示和动画效果了。在一些具体的图形数据展示上用了 d3 作了雷达图的分类数据展示等。第一次用 d3 在移动端做项目,发现 d3 还是在移动端上有一些兼容性的问题(例如 SVG 的 dy , dx 等)。还是需要在应用时多注意一下,在平时也更熟悉一下 d3 的一些应用。 17 | 18 | ## 技术及其他相关 19 | 20 | 1. 这个月有两篇看到的关于技术债的文章讲得很好([关于技术债务](http://mp.weixin.qq.com/s?__biz=MzA4ODgwNjk1MQ==&mid=2653788501&idx=1&sn=9399568096319bbca8e80164ba304b8e&chksm=8bfdba1dbc8a330b34d3a6ae58825867a63a70b5d2407ae4bba509e0438f78167efe7cc09d6c&mpshare=1&scene=1&srcid=1202GxV3nWnpntUzj3RusBF3#rd), 21 | [技术债:the good, the bad, and the tao](http://mp.weixin.qq.com/s?__biz=MzA3NDM0ODQwMw==&mid=2649827509&idx=1&sn=61a7adbeb49a105b9a22bae41614d07f)),技术债确实是每个技术团队都或多或少会面临的问题,如何正确看待技术债,合理控制技术债。真的很有帮助(看了 MongoDb 的例子也真是有所学习了..) 22 | 主要总结的思想如下: 23 | 24 | - 拥抱 MVP。先解决温饱问题,再考虑还债。 25 | - 把技术债视情况外包出去, 26 | - 雇佣你所能获得的最优秀的人,给予她们你所能给予的,最能发挥她们能力的权限。(所有工程师各方面培养主人翁意识) 27 | - 拥抱匡威定律。你的组织架构决定了你的代码结构。想要快速独立的功能交付能力,你要有包含所有角色,拥有直接决策权的端到端的功能团队,而不是开发,测试,运维等彼此独立。(相伴随的也要有健全的 Monitoring 和测试机制) 28 | - 在实现上可以多些负债,在接口上尽量减少负债。系统设计的框架得是大体对的。 29 | - 定期处理一定的技术债务 30 | 31 | 2. 今年双 11 又看到了去年双 11 天猫的狂欢城的技术方案总结,有些细节挺有意思的,也了解了这些实时活动的相关设计,容灾机制等方案。[天猫双 11 晚会和狂欢城的互动技术方案](http://www.infoq.com/cn/articles/tianmao-interaction-solutions) 32 | 33 | 3. 由于一直在做移动端的商城,所以这些手势的相关 API 还是比较了解的,但是对于 pinch rotate 这些操作相应的实践就并不多了,通过 AlloyFinger 熟悉了一下。[超小 Web 手势库 AlloyFinger 原理](http://www.alloyteam.com/2016/11/11568/) 34 | 35 | 4. 对应到编程领域也很贴切:形成主见 -> 发现不能解释的事情 -> 融汇贯通 -> 以简御繁 -> 运用自如 -> 一览众山小 -> 通透。[梁漱溟:思考问题的八层境界](http://cul.qq.com/a/20161121/002271.htm) 36 | 37 | 5. [HoloLens 初代到底有多牛](http://mp.weixin.qq.com/s?__biz=MzA4MzYyNjM2OQ==&mid=2247483939&idx=1&sn=6b7600e93fed84875ba02b6121eac117&chksm=9ff2d2cda8855bdb9983ae6193e32eded93a58e7f08b427dfc8a75ad3e29d9fe29c2e084d17c&scene=0#rd),这是一篇关于 HoloLens 硬件、技术原理、细节的 PPT 介绍,内容比较详实。期待 HoloLens 能早日普及。(然而有生之年是否能见到类似 SAO 的产品呢..) 38 | 39 | 6. 看了月影个人的英语学习方法经验,有一些经验还是很有参考价值的。 40 | 例如:翻译技术文章的时候可以根据作者的 GitHub 地址进行深入了解背景甚至交流等等。 41 | [实录|月影谈循序渐进的英语学习方法](http://mp.weixin.qq.com/s?__biz=MzIwNjEwNTQ4Mw==&mid=2651576733&idx=1&sn=6ca82a137b129114e34ab26b2299a2cb&chksm=8cd9c779bbae4e6fcd8a35610cd34a247a0e46fd4ed328c3e38e944bf406d4ceba840919434b&mpshare=1&scene=1&srcid=11301plTAQrl7LP0AtEtIEMD#rd) 42 | 43 | ## 个人生活相关 44 | 45 | 这个月到了 24 岁,感觉良好。 46 | 47 | 这个月业余时间没有写太多新的代码,主要因为有一些其他烦心的事,看到 Github 上灰溜溜的四列还是挺惭愧的。需要调整一下心态了。 48 | 49 | (本文的题目是本月扇贝某日打卡的每日一句,『Do whatever you do intensely -- 罗伯特亨利』,说的是无论做什么,都要满怀热情。而对于我来讲如何保证热情呢?就是去践行新的计划与目标。) 50 | 51 | ## 三首歌 52 | 53 | [ユメセカイ - 戸松遥](http://music.163.com/#/song?id=656437) 54 | 55 | [失う - らいらい](http://music.163.com/#/m/song?id=39224531) 56 | 57 | [外面的世界 - 莫文蔚](http://music.163.com/#/m/song?id=276904) 58 | -------------------------------------------------------------------------------- /type-number非法值的一些探究及拓展.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 关于表单input type="number"非法值时的一些探究及拓展 3 | date: 2015-09-01 13:58:50 4 | categories: HTML 5 | tags: [浏览器,表单,input,HTML5,兼容性] 6 | --- 7 | 8 | ## 问题描述 9 | 10 | ### 需求是这样的 11 | 12 | 今天在处理表单验证时发现了一个很诡异的现象,遂记录下来。 13 | 14 | 事情是这样的: 15 | 产品 MM 提了个需求,在微信端要求做一个表单,提交一些信息,然后其中有一个 input 需要直接调用数字键盘 16 | 17 | ### 最初思路 18 | 19 | 既然调用数字键盘,那么 `input type` 肯定就是 number 或者 tel。因为 tel 不能输入小数点,所以`input type`就为 `number` 了,然后在填表单时要做一些验证来及时反馈吧,所以代码大概就是这样的了 20 | 21 | ``` js 22 | 23 | 24 | alertDebug:function(formbug){ 25 | let alertcontent ={ 26 | 6:'整数位最多不超过4位,小数位最多不超过2位', 27 | } 28 | let texts = {} 29 | texts.text = alertcontent[formbug] 30 | this.$dispatch('alertMsg',texts); 31 | }, 32 | submitForm: function(event){ 33 | let eventname = ''; 34 | let formbug = false; 35 | if(this.$data.retail_price != ''){ 36 | if(!this.validateNum(this.$data.retail_price) || this.checklength(this.$data.retail_price) > 4){ 37 | if(!this.validateNum(this.$data.retail_price)){ 38 | if(!eventname){ 39 | formbug = 6; 40 | } 41 | if(eventname == 'retail_price'){ 42 | formbug = 6; 43 | let temp = this.retail_price; 44 | this.retail_price = temp.toString().slice(0,-1); 45 | event.target.value = temp.toString().slice(0,-1); 46 | } 47 | }else{ 48 | let retailprice = this.$data.retail_price + ''; 49 | if(retailprice.indexOf('.') > -1){ 50 | if(this.checklength(this.$data.retail_price) > 7){ 51 | if(!eventname){ 52 | formbug = 6; 53 | } 54 | if(eventname == 'retail_price'){ 55 | formbug = 6; 56 | let temp = this.retail_price; 57 | this.retail_price = temp.toString().slice(0,-1); 58 | event.target.value = temp.toString().slice(0,-1); 59 | } 60 | } 61 | }else{ 62 | if(!eventname){ 63 | formbug = 6; 64 | } 65 | if(eventname == 'retail_price'){ 66 | formbug = 6; 67 | let temp = this.retail_price; 68 | this.retail_price = temp.toString().slice(0,-1); 69 | event.target.value = temp.toString().slice(0,-1); 70 | } 71 | } 72 | } 73 | } 74 | } 75 | if(formbug){ 76 | this.alertDebug(formbug); 77 | return false; 78 | } 79 | }, 80 | ``` 81 | 82 | 这样出现了一个问题在电脑 Chrome,iphone上,对于 `input type="number"` 的 input 都会将 value 变为 "";而在安卓的微信上却显示为正确的 input number 格式(如输入值为 "1...." 时,由于值并不为数字,非法,大多数按照[W3C相关规范]( http://www.w3.org/TR/html5/forms.html#number-state-(type=number)\)会将它处理为 "",而在 Android 微信上为 "1.") 83 | 84 | 85 | ## 相关知识 86 | 87 | 这里主要就是 input 的 number;其为 html5 加入的 type 类型。 88 | 89 | [input html5 添加内容介绍](http://www.w3school.com.cn/html5/html_5_form_input_types.asp) 90 | 91 | ## 解决思路 92 | 93 | 由于在 W3C 规范中,如果输入了一些非数字的字符,就会返回空字符串。 94 | 95 | 但这样其实比较坑,导致验证的时候如果输入非数字的时候,直接使用 `.value`( 或者`$('.selector').val()`)都拿不到值,而拿不到值的情况下就会认为没有填写这个输入框。 96 | 97 | 这里的解决方案就是在 input 的属性中有一个 `validity` 属性: 98 | 99 | 在 Chrome 中,input 元素的 `validity.badInput` 这个属性里,可以判断值是否合法,如果填入了非法值,这个属性就是 true,正常值的话就是 false。 100 | 101 | 但是火狐下 `.validity` 里没有 `badInput` 属性,如下图,它可以直接通过.value 正常返回非数字的字符串。(微信 X5 同样也这样..) 102 | ![安卓微信](http://qcyoung.qiniudn.com/qcyoung/type-number非法值的一些探究及拓展/安卓微信,valid对象有的属性.png) 103 | 104 | 而 IE8、9 则也可以直接 .value 获取到非数字的字符串值,不会返回空字符串。 105 | 106 | -------------------------------------------------------------------------------- /【译】使用 currentColor 属性写出更好的 CSS 代码.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 【译】使用 currentColor 属性写出更好的 CSS 代码 3 | date: 2016-09-28 12:19:19 4 | categories: CSS 5 | tags: [CSS] 6 | --- 7 | > 原文地址:[Writing better CSS with currentColor](https://hashnode.com/post/writing-better-css-with-currentcolor-cit5mgva31co79c53ia20vetq) 8 | > 原文作者:[Alkshendra Maurya](https://hashnode.com/@alkshendra) 9 | > 译文出自:[掘金翻译计划](https://github.com/xitu/gold-miner) 10 | > 译者:[yangzj1992](http://qcyoung.com) 11 | > 校对者: [linpu.li](https://github.com/llp0574), [Nicolas(Yifei) Li](https://github.com/yifili09) 12 | > 首发于: [掘金](http://gold.xitu.io/entry/57eb30bebf22ec0058898ee7/detail) 13 | 14 | 15 | 总有一些极其强大的 CSS 属性在目前已经有了很好的浏览器支持,但却很少被开发者使用。 `currentColor` 就是这样的属性之一。 16 | 17 | MDN 把 currentColor [定义为](https://developer.mozilla.org/en/docs/Web/CSS/color_value#currentColor_keyword): 18 | 19 | > `currentColor` 代表了当前元素被应用上的 color 颜色值。它允许让继承自属性或子元素属性的 color 属性为默认值而不再继承。 20 | 21 | 在本文中,我们将通过一些有趣的方式来概述如何使用 CSS `currentColor` 这一关键字。 22 | 23 | * * * 24 | 25 | ## 介绍 26 | 27 | `currentColor` 关键字按某种规则获取了 color 属性的值并赋值给了自身。 28 | 29 | 在任何你想要默认继承 `color` 属性值的地方都可以使用 `currentColor` 这一关键字。这样当你改变 `color` 关键字的属性值时,它会自动的通过规则反映在所有 `currentColor` 关键字使用的地方。这难道不是很棒吗?😀 30 | 31 | ``` css 32 | .box { 33 | color: red; 34 | border: 1px solid currentColor; 35 | box-shadow: 0 0 2px 2px currentColor; 36 | } 37 | ``` 38 | 39 | 在上面的代码片段里,你可以看到我们不是在所有的地方都重复相同的 color 值,而是用 currentColor 来代替。这使得 CSS 变得更加容易管理,你将不再需要在不同的地方来追踪 color 值 40 | 41 | * * * 42 | 43 | ## 各种用法 44 | 45 | 来看一下 `currentColor` 可能的用例和例子: 46 | 47 | **简化 color 定义** 48 | 49 | 像链接,边框,图标以及阴影的值总是随着它们的父元素 color 值保持一致,这可以通过简化的 currentColor 来替换一遍又一遍的特定 color 值;从而使代码更加易于管理。 50 | 51 | 例如: 52 | 53 | ``` css 54 | .box { 55 | color: red; 56 | } 57 | .box .child-1 { 58 | background: currentColor; 59 | } 60 | .box .child-2 { 61 | color: currentColor; 62 | border 1px solid currentColor; 63 | } 64 | ``` 65 | 66 | 在上面的代码片段中,你可以看到我们不是在边框、阴影上指定一个颜色,而是在这些属性上使用了 `currentColor`,这将使它们自动变为 `red`。 67 | 68 | **简化过渡和动画** 69 | 70 | currentColor 可以使 transitions 和 animations 变得更加简单。 71 | 72 | 让我们考虑一下最早的代码示例,并且改变一下 hover 时的 `color` 值。 73 | 74 | ``` css 75 | .box:hover { 76 | color: purple; 77 | } 78 | ``` 79 | 80 | 这里,我们不需要再在 `:hover` 里写三个不同的属性,我们只需改变 `color` 值;所有使用 `currentColor` 的属性会自动在 hover 时发生改变。 81 | 82 | **在伪元素上使用** 83 | 84 | 像是`:before` 和 `:after` 这样的伪元素也同样可以通过用 currentColor 来获取它的父元素的值。这就可以用于创建带有动态颜色的『提示框』,或是使用 body 颜色的『覆盖层』,并给它一个半透明的效果。 85 | 86 | ``` css 87 | .box { 88 | color: red; 89 | } 90 | .box:before { 91 | color: currentColor; 92 | border: 1px solid currentColor; 93 | } 94 | ``` 95 | 96 | 这里,`:before` 伪元素的 `color` 和 `border-color` 会从父元素 div 中获得并可以被组建成类似提示框的东西。 97 | 98 | **在 SVG 中使用** 99 | 100 | SVG 中 `currentColor` 的值同样可以从父元素中获取。当你在不同地方应用 SVG 并想从父元素中继承 color 值而又不想每次明确提及时,使用它是相当有帮助的。 101 | 102 | ``` css 103 | svg { 104 | fill: currentColor; 105 | } 106 | ``` 107 | 108 | 在这里,svg 将会使用与它父元素相同的填充颜色,并且会动态的随着父元素颜色的修改而发生变化。 109 | 110 | **在渐变中使用** 111 | 112 | `currentColor` 可以同样用于创建 CSS 渐变,其中渐变属性的一部分可以被设置成父元素的 `currentColor` 。 113 | 114 | ``` css 115 | .box { 116 | background: linear-gradient(top bottom right, currentColor, #FFFFFF); 117 | } 118 | ``` 119 | 120 | 在这里,**顶部**的渐变颜色将会总是与父元素保持一致。虽然在这种情况下只会有一个动态颜色的限制,但对基于父元素颜色来生成动态的渐变来说,这仍然是一个简洁的方法。 121 | 122 | 这儿有一个 [Codepen 示例](http://codepen.io/alkshendra/pen/xEVrJJ?editors=1100#0)来演示上述的所有例子。 123 | 124 | * * * 125 | 126 | ## 浏览器支持 127 | 128 | CSS `currentColor` 是从 CSS3 引入 SVG 规范时产生的,自 2003 年以来一直存在。因此浏览器对 `currentColor` 的支持是很可靠的,除了 IE8 和一些更低版本的浏览器。 129 | 130 | 下面这张图展示了目前有关浏览器支持情况的信息,信息来自 [caniuse.com](http://caniuse.com/#feat=currentcolor): 131 | 132 | ![currentColor Support](https://res.cloudinary.com/hashnode/image/upload/v1474021764/g03f4hx1ftb0frtoonfw.png) 133 | 134 | * * * 135 | 136 | ## 结论 137 | 138 | CSS `currentColor` 尽管是一个很好的特性,但还尚未得到充分运用。它提供了很棒的支持并带来了相当的可能性来使你保持你的代码更加的整洁。 139 | 140 | 尽管 CSS 变量有它自己的方式,但是养成使用 `currentColor` 的习惯还是很酷的。 141 | 142 | 这只是一个我发现的很有趣的简单的话题,如果有人也对此话题感兴趣。请让我知道你的想法并在下面留言!😊 143 | 144 | -------------------------------------------------------------------------------- /毕业六个月后回顾我的前端路暨2015总结2016新年祈愿.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 毕业六个月后回顾我的前端路暨2015总结2016新年祈愿 3 | date: 2015-12-31 20:37:38 4 | categories: 我的生活 5 | tags: [我的生活] 6 | --- 7 | 8 | ![never_too_late](http://qcyoung.qiniudn.com/qcyoung/毕业六个月后回顾我的前端路暨2015总结2016新年祈愿/2015_2016.jpg) 9 | 在写这篇日志时已近年尾,离我正式本科毕业入职的时间 2015 年 7 月 1 号也近 6 个月。不禁想写一篇日志认真的回顾总结一下自己的前端路,顺带做一下年终总结及新年祈愿。 10 | 11 | ### 简要概述 12 | 13 | 我毕业于 USTB,专业是信息管理与信息系统。大学期间成绩平平,基本上如大多数同学一样,我在大学干的正经事也就是:学习学习、参加了些社团、过了四六级、参加些小比赛的按部就班的度过了大学的前几年。 14 | 15 | 到了大三暑期,我决定毕业后直接工作,但确实在此时我还是或多或少的有一些迷茫,或者说并没有一个准确的职业发展方向让我在实习校招时进行选择,秉着『干一行爱一行』的错误思想,在这段日子中我先后于大三暑期在京东方担任OA开发实习工程师,在秋季校招进入了长城战略咨询所的知识管理部担任实习咨询师。后来在长城时,我终于开始对自己的职业规划展开了反思,说实话,在长城所时我并不喜欢那里的工作氛围。它给我的感觉是缺少活力、较为死板的工作节奏和方式,当我看到自己未来几年的工作模式或许都将如此时,每一天的起床上班都成为了一种痛苦。在那段时间,我纠结于继续坚持适应当前的工作环境还是重新备战春招。 16 | 17 | 后来我在知乎上看了许多职业发展上的相关分享和见解,也看到很多同龄人在校招获得优秀 Offer 时的分享心得,个人简单总结也十分认可的如下: 18 | - 一个优秀的职业人应该是遵循一套从上至下相关联的职业发展的。隔行如隔山,随意跨行将消耗你大量曾经的学习成本。坚持一条相近的路成为专家是最经济的。 19 | - 务必将自己的特长、兴趣尽可能的与工作结合。 20 | - 持续不断的通过各种方式提高自己的工作相关能力。 21 | 22 | 因为之前我曾经担任过一阵子的程序员,而且在从事程序员的工作时也确实充满了活力和希望,尽管之前曾经因为犹豫自己的专业水平并不能与正规计算机专业的同学进行对抗,并没有坚持选择这一方向,但最终我还是决定践行成为一名开发工程师的道路,并且选择了之前有过一定经验的前端方向作为起步(并不多,也并没有系统的学习),最终在2015年寒假后我辞职踏入了准备春招的行列。 23 | 24 | ### 程序员的路 25 | 26 | #### 正式工作前 27 | 28 | 从专业上来讲我其实属于计算机半科班人士,我们也学习了计算机的主流基础课程,但是由于专业属于综合性专业(计算机+经管的融合),我们也学习了相当的经管类知识,这样的综合型专业导致我们专业的同学从事的工作也的确是五花八门。这样也确实在一定程度上给我们的择业方向参考上并不是那么明确。(直观来看就是啥都能干。。) 29 | 30 | 而我与前端项目的接触,是从 2014 年 1 月开始搭建自己的个人博客 [qcyoung](http://qcyoung.com) 开始的,当时并没有太多的去系统的学习知识,依靠 Wordpress,简单的改改主题,写写文章就是当时的水平,而且那时我也没有想到未来的工作就真的是写代码。。然而现实就是这样,很多事情不管你之前怎么计划,可能最终也都会推翻你之前的设想。 31 | 32 | 后来在春招前,参考 w3school 和慕课网的前端学习计划,简单系统的学习了基本的知识,但是确实当时基础依然不是很好,在互联网领航公司的面试中基本都没有走到好的结果,只有一些小公司给了我 offer,最后在美菜网的面试中,被当时的前端带头人[冯岩](https://www.zhihu.com/people/feng-yan)面试,记得很清楚当时的面试就是一张白纸冯岩一路下来问基础问题,如果答对了继续针对原问题拓展问,错了转下一个方向的问题继续问。足足面了近 1 个小时。最后他给我推荐了基础的书单让我进来先实习——经典的3本书(javascript 红皮书,css 权威指南,javascript 语言精粹)。这时我才真正算是踏入了互联网公司行业的程序员的门,在转正后也拿到了当时对于我来说算比较满意的薪资(半狗左右。。) 33 | 34 | #### 正式工作后 35 | 36 | [美菜网](http://www.meicai.cn/)是中国目前最大的农产品移动电商平台,它也很年轻,公司到目前也仅创立 1 年半左右(14 年 6 月 6 日创立),我于 4 月份以实习生身份加入后,于 7 月转正,在这个公司中我确实找回了正式工作的乐趣(或者说是编码的乐趣)。而且公司中的同事都是相当有乐活精神的。leader 也的确是十分照顾我们,项目组及部门内都没有什么奇葩的制度,一切都相对比较自由,所以在公司工作的时候总的来说心情也都还是很好。在这家公司我先后参与开发了美鲜送司机微信端报名系统、新商品系统以及美菜的微信商城等。在这些过程中也确实逐渐至少了解了一个普通的发展迅速的创业公司的系统开发过程和系统业务之间的配合等情况。(这里尤其是电商行业,一次上下游全业务线的项目开发、联调到上线真的是相当复杂。。)由于公司也很年轻,所以总有一种错觉觉得我和它都是在这个世界上共同探索成长。当然公司比我发展的猛多了。。(1 年半就已经融到 C 轮,覆盖了 30 多个城市,成为了国内最大的农产品移动电商平台。) 37 | 38 | 由于最初公司前端开发较少,我们前端都是分插到各个业务线进行开发。基本上述各业务系统的前端部分直到 11 月新来了同事之前都是我一个人负责开发的。总的来说还是锻炼了我很多。至少从今年年初的菜鸟到现在基本上我应该已经算是一个及格的前端开发者了。 39 | 40 | 在这里的近一年时间也十分感谢在公司中共事帮助过我的很多同学: 41 | 前端组: 42 | [冯岩](https://www.zhihu.com/people/feng-yan)、[春佳](https://github.com/silvialiu)、[久代](https://github.com/cuijiudai)、[成亮](https://github.com/yamakasiluke)、[俊杉]()、[志强]() 43 | 44 | 前端组外的其他开发同学: 45 | [云涛](https://github.com/albertyann)、[刘强](#0)、[荣强](#0)、[兴权](#0)、[振发](#0)、[大师兄杨希](#0)、[二师兄张岩](#0)、[雁辉](#0)、[丛姐](#0)、[科兄](#0) 46 | 47 | 产品: 48 | [丁娟](#0)、[天楚](#0)、[小溪](#0)、[文帅](#0) 49 | 50 | 设计: 51 | [亚运](#0)、[田华](#0)、[贵君](#0) 52 | 53 | 运维: 54 | [东霖](#0) 55 | 56 | 测试: 57 | [亮哥](#0)、[芯冉](#0) 58 | 59 | 老大们: 60 | [辉哥](#0)、[一行哥](#0) 61 | 62 | 感谢以上同学、老大们以及其它同事在工作中给予我的配合照顾和分享体谅。十分感谢。 63 | 64 | ### 2015 个人总结 65 | 66 | 1. 基本顺利的完成了从毕业前的迷茫不知所措到毕业后有目标向前的职业生活。 67 | 2. 每天坚持在下班后学习一些工作之外的知识及程序员技能,并且重新捣鼓了自己的博客。 68 | 3. 通过大师兄、二师兄、亮哥等「煽动鼓励」,我也开始学起吉他来了。。 69 | 4. 办了定期理财,把我为数不多的积蓄尽量存起来..(月入半狗左右,基本也只能攒多少是多少。。) 70 | 5. 坚持学(huan)习(zhai),用扇贝英语打卡,从今年 2 月后旬开始每天坚持至少 50 个单词、10 句子、2 篇新闻阅读、5 个听力的练习。至今只断过 2 天,到今日已打卡 308 天,并第一次真正的读完了英文原著(老人与海,小王子) 71 | 72 | ### 拖到 2016 的不足与希望 73 | 74 | 1. 学习更多知识,提升自己的实力,争取经济上早日更自由.. 75 | 2. 年年说要努力减肥,今年自然也不例外..(年年到最后依然保持 80kg 左右的身材..) 76 | 3. 跑步从今年 4,5 月开始一直有练习准备今年的第二次北马,奈何比赛前一天发高烧..只能退赛,然后就没跑过步了..(帝都雾霾天增多,自己工作又老坐着..争取尽快拾起找到一个更适合自己的运动锻炼方式.) 77 | 4. 和女朋友继续友好相处,在她读完研后争取一起生活。 78 | 5. 家人朋友生活平安幸福。 79 | 80 | ### 总结 81 | 82 | 今年初或者说从校招开始时,令我最痛苦的就是——迷茫、困惑。它们缠绕着整个校招季的我,令我不能自拔,我迷茫于到底选择什么样的工作来踏上自己的工作路程,我认为我是热爱编程的,但我的胆怯最后让我畏惧、让我彷徨。由于种种原因我曾偏离了这条路。我怕已经太迟去选择编程这条道路而不敢前行。但在寒假之后我想通了,通过重新自学准备春招,最后总算还是有了一个比较好的结果。(虽然在春招后仍有遭到拒绝真的有怀疑自己的时候,但是随着时间的推移,我最终还是坚持了下来,走上了自己的职业道路,这点至少真的很感动我。) 83 | 在之后不管是学编程,还是后面的学吉他,还是做其他事,我都不会太在意自己的时间和曾经的过程,喜欢就去做,只要你觉得值得、觉得有价值就去做。这是我15年领悟到的最大的东西并决定践行于之后一生。 84 | ![never_too_late](http://qcyoung.qiniudn.com/qcyoung/毕业六个月后回顾我的前端路暨2015总结2016新年祈愿/never_too_late.jpg) 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /2016.10 - 往日的伤秋情怀也在这短暂的秋天里变得没影了.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2016.10 - 往日的伤秋情怀也在这短暂的秋天里变得没影了 3 | date: 2016-11-07 13:57:19 4 | categories: 我的生活 5 | tags: [我的生活,月记,音乐,美食] 6 | --- 7 | 从今以后,想每个月粗略记录一下自己在这个月的工作、技术相关以及生活的内容。记录一些自己看到的好东西啥的...也算是每个月简单的一些总结 + 扯扯淡(增添些生活气息 =.=)。 8 | 9 | ## 工作相关 10 | 11 | 目前这个月一直在搞公司的 CMS 系统。其实公司这块起步相对也算挺晚的了。这个项目也算是又一次从零开始参与搭建一个项目.. 12 | 13 | 理论上来讲这是公司一个很大的项目,公司的双 11 活动页面很多入口都会走由此系统搭建的各级页面。从 9 月开始从 0 起步进行开发到这个月月底完成两期版本上线。但是在公司里..由于每个项目都是最高优先级..所以这个项目中途都还被插了好几个紧急需求..真的要吐槽下.. 14 | 15 | 这个项目中我主要负责了 CMS 后台设计器部分的页面展示和交互,以及前台部分上微信和 APP 的展示对接。两边的技术栈上我都统一用了 Vue + Vuex + Vuerouter 全家桶,撸起来也还是挺快的。 16 | 17 | 在开发过程中主要是在后台设计器的制作中回顾了下 drag event 这一事件。用了一个基于 Vue 的拖拽插件 [vue-drag-and-drop](https://github.com/james2doyle/vue-drag-and-drop) 来协助实现了设计器里的拖拽控件交互。写了一个点击展示调色板的小插件,准备回头整理一下开源出来。同时后台的设计器由于想回头交给后端方便点,所以也加了 Bootstrap 的样式。并用了 [titatoggle](http://kleinejan.github.io/titatoggle/) 来优化展示 toggle 形式的一个小插件。 18 | 19 | 最后在双 11 前完成了目前的 CMS 系统,他主要具有以下特性: 20 | 21 | 1. 可视化快速构建页面内容和设置, 22 | 2. 前后端分离,不由后端来负责渲染页面,后端只负责提供高性能,可复用的 API。 23 | 3. 主要负责移动端展示,兼容 APP 逻辑。 24 | 4. 版本可降级,页面加载逻辑性能优化。 25 | 26 | 架构上来讲,CMS及其周边系统大概为如下的关系: 27 | 28 | ![系统关系](http://qcyoung.qiniudn.com/qcyoung/201610/module_relation.png) 29 | 30 | 其中 Weblog 是我们公司自己的埋点分析处理工具。在前台会自动将数据埋到各个组件模块上。auth 系统是权限系统用来审核页面发布流程。GIS 负责来提供城市区域维度的信息,它与商户智能服务共同进行判断使每个用户根据自己的位置信息和用户标签来浏览差异化的页面展示信息。而商品中心提供了基础的商品信息服务。而在后台方案管理模块中我们可以进入设计器和方案预览页去编辑、查看搭建效果。 31 | 32 | 在前端我们会首次请求拿到此页面的方案信息(包含页面背景,页面名称,模块序列等页面方案层级的信息)在模块序列中会包含这个方案页面的各模块ID,根据各模块ID,我们来反查各模块的内容并填充到页面上,在首次加载时只会加载首屏的模块内容从而也起到一个懒加载的效果。 33 | 34 | 另外后端会在每个方案生成后产生一个版本ID字段,在复用次数较多的页面,前端会存储这个页面模块的信息内容和布局以及版本号,在请求后端接口时会携带这一版本ID,如果能够匹配,或是请求失败,则会直接调用前端存储的上次内容。这也是降级和性能优化的一个方案。 35 | 36 | 37 | ## 技术及其他相关 38 | 这里简单说一下这个月看到的技术和其他相关的有意思的东西: 39 | 40 | 1. 首先分享的还是在做 CMS 项目时刚好看到 JD 他们的 CMS 架构演进分享,毕竟我所在的公司在体量上还相差甚远,从他们的架构中可以去了解其他公司目前的 CMS 系统是如何实现发展的。[京东上千页面搭建基石——CMS前后端分离演进史](http://mp.weixin.qq.com/s?__biz=MzIwODA4NjMwNA==&mid=2652897861&idx=1&sn=f2804fd064c7d3ea86554c187ae03db7) 41 | 42 | 2. 这个月在忙 CMS 的同时,还参与了 [Vue2 中文文档](https://vuefe.cn/)的翻译校对,也算是为一直在使用的 Vue 做出一些贡献..不过在这个翻译校对的过程中也发现,以社区形式贡献的内容输出。质量管理真的是一个需要重点把握的内容。例如某人初次翻译后我认为应该对其进行初次校对后视能力和态度才能再让他参与翻译,这样就很容易发现一些其他人翻译时留下的不负责任的坑。(不要问我为什么有这样的领悟 = =。。) 43 | 44 | 3. 此外这个月接触到了 [BEM](http://getbem.com/introduction/) 这一 CSS 命名方案,发现这也算是很老的一个概念了。。尽管目前类似 webpack css-loader 使 CSS 已经变得模块化并解决了很多作用域冲突的问题,但在语义化和设计规范的推进下还是准备尝试在个人项目中先试着使用来体验一下感受。 45 | 相关资料: 46 | - [Battling BEM (Extended Edition): 10 Common Problems And How To Avoid Them](https://www.smashingmagazine.com/2016/06/battling-bem-extended-edition-common-problems-and-how-to-avoid-them/) 47 | - [如何看待 CSS 中 BEM 的命名方式?](https://www.zhihu.com/question/21935157?sort=created) 48 | 49 | 使用案例: 50 | - [饿了么组件库 element](https://github.com/ElemeFE/element) 51 | - [微信组件库 weui](https://github.com/weui/weui/) 52 | 53 | 4. 另外看到一个有趣的校招题:用 HTML 和 CSS 画一个笑脸。如下是预期效果和最终实现参考。 54 | ![系统关系](http://qcyoung.qiniudn.com/qcyoung/201610/smile.png) 55 | [demo](http://codepen.io/yangzj1992/pen/mrNBdZ) 56 | 57 | 5. 这个月还看到了『绿色地球』这一个很有意义的项目,创建人居然选择在我大成都开始创业运行,这就更得关注并支持一下这样的项目,希望它能走的长远,早日把业务拓展到帝都来。感兴趣的朋友可以看看下面的文章来具体了解。 58 | - [他是年薪几十万的微软工程师,却辞职去收破烂,成了最让女儿自豪的爸爸](http://mp.weixin.qq.com/s?__biz=MjM5ODAwNDIwMA==&mid=2650522355&idx=1&sn=66e16af0905af40324740f1763f22320) 59 | 60 | 下面是他在一席的演讲,挺值得看看的: 61 | - [我们每天制造这么多垃圾,到底拿它怎么办](http://mp.weixin.qq.com/s?__biz=MjM5NjYyMjM0MA==&mid=2650864114&idx=1&sn=b6a6dab97498a430e4b28099f6e8c7eb) 62 | 63 | ## 个人生活相关 64 | 65 | 这个月国庆回了次绵阳,在城区逛了很多地方,市中心的公园、警钟街等地方基本和小时候一样还是保留着原来的样子,甚至几年前吐槽的车多了路还是跟九几年一样窄..但是新的变化也是有的 —— 66 | 67 | 在涪江畔越王楼,曾经的三江广场被彻底翻修,由以前长满野草的河岸变成了沿河散步休憩的步行广场,修的十分的漂亮,两岸江边的建筑墙上也做了光幕,到了晚上在建筑物上可以展现十分靓丽的灯光秀,今年国庆恰逢绵阳主题灯光展,在越王楼上看三江河畔的灯光秀还是很吸引人的。 68 | 69 | ![涪江](http://qcyoung.qiniudn.com/qcyoung/201610/riverside.jpeg) 70 | ![富乐大桥](http://qcyoung.qiniudn.com/qcyoung/201610/fule_bridge.jpeg) 71 | ![灯光秀](http://qcyoung.qiniudn.com/qcyoung/201610/light_show.jpeg) 72 | 73 | 另外马家巷的小吃 + 平日早餐的(油茶 + 米粉)真的是绵阳一绝。唉,帝都实在是难找如此这般正统风味的米粉和油茶...(所幸找到一家淘宝店卖的油茶很不错..可解相思之苦= =..) 74 | 75 | 下面是正宗的[四川米粉](http://baike.baidu.com/view/1641554.htm)和油茶的样子(我就不说淘宝直接搜油茶,默认搜出来的其他省的冲泡型油茶有多难喝了..) 76 | 77 | ![四川米粉](http://qcyoung.qiniudn.com/qcyoung/201610/rice_noodle.jpg) 78 | 79 | ![四川油茶](http://qcyoung.qiniudn.com/qcyoung/201610/oil-tea.jpg) 80 | 81 | 82 | 另外也第一次去了北川地震遗址,感受了生命、生活的无常,珍惜现有的日子和幸福时光吧。 83 | 84 | ![纪念碑](http://qcyoung.qiniudn.com/qcyoung/201610/monument.jpeg) 85 | ![宣传画](http://qcyoung.qiniudn.com/qcyoung/201610/hero_chinese.jpeg) 86 | ![学校废墟](http://qcyoung.qiniudn.com/qcyoung/201610/school_ruin.jpeg) 87 | 88 | 另外 WOW 更新 7.0 后,作为一个单纯的剧情党和战场爱好者,深深地感受到了暴雪对我们这种休闲玩家的恶意,加上网易月卡的补刀。游戏成本一下子陡增(虽然架不过脸好,居然莫名的掉了小德核心橙护腕。。居然战场啥的还能混下去。)然而在 7.1 打了一把 4 个小时才通关的 KLZ 之后。。确实发现 WOW 真的越来越有点肝不动了。。实在是有些可惜吧。。 89 | 90 | 最后,在这十月的一个月里,我的衣着从:四川的短袖 + 短裤 => 北京的毛衣 + 秋裤。。不禁感慨我国真是幅员辽阔。。(相反帝都的秋天也真是越来越短暂了。。以前这个月里我还总会沉浸在伤秋的氛围里过上好几天日子,这一年感觉都没啥反应。。就已经开始来暖气准备过冬了 = =。。) 91 | 92 | ## 三首歌 93 | 94 | [Pray - 川瀬智子](http://music.163.com/#/song?id=662235) 95 | 96 | [βίος - 澤野弘之](http://music.163.com/#/song?id=498187) 97 | 98 | [三葉のテーマ - RADWIMPS](http://music.163.com/#/song?id=426881500) 99 | -------------------------------------------------------------------------------- /我的 2016 总结暨 2017 新年祈愿.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 我的 2016 总结暨 2017 新年祈愿 3 | date: 2017-01-02 21:48:25 4 | categories: 我的生活 5 | tags: [我的生活] 6 | --- 7 | 8 | ![](https://ww4.sinaimg.cn/large/006y8lVajw1fb6bof5tjej31hc0u0tf0.jpg) 9 | 10 | 这一年发生了不少的事,但在抬笔时却又不知从何处细谈起。这一年让我对很多事有了更深的认识。下面还是按简单的分类简谈一下吧。 11 | 12 | ## 工作 13 | 14 | 这一年是我司工作环境变化巨大的一年。总体上来讲公司依然是在较好的发展,公司搬了家,让办公环境有了很大的改善。整体技术团队也扩张了许多。可以说在硬件环境方面,这一年还是提升了许多的。 15 | 16 | 然而从个人角度而言,硬件环境改善的背面却是入职以来所认同的好几名前辈和同事的相继离职。尤其是所在的商城组,可以说是流水的老大 + 组员。尽管目前所在的前端组的小气候相比来说还算稳定。但是由于大气候的原因,导致在今年的一段时间内还是很难保持一个稳定的开发环境。。 17 | 18 | 此外随着公司的发展,在我看来公司的环境和公司文化间也存在了一定的撕裂。不少公司都或多或少存在上面的撕裂现象,例如今年[百度的魏则西事件](https://zh.wikipedia.org/zh-hans/%E9%AD%8F%E5%88%99%E8%A5%BF%E4%BA%8B%E4%BB%B6),[阿里的校园日记事件](https://www.zhihu.com/question/52987944)等等。这些事态的发展肯定是与公司所宣扬、认同的文化、价值观相悖的。但最后是如何执行成这样的?多少都是因为这样的撕裂导致的。此外,这一年里对上下级管理、加班文化、公司人文关怀等也有了更多深刻的看法。这一年里真的需要对公司里负责的同事,老大报以十分的感谢。 19 | 20 | 这一年里在商城我们从年初用 Vue 开始重构,到目前年底总算将商城主流程的大多数页面改造成了由 Vue 全家桶开发的单页面应用(期间遇到的各种业务更替、拆分和插入需求而影响的进度不表,但这里并不是说公司不重视重构,这里的确存在着公司成立尚 2 年的客观现实,可以说相比其他主流电商,我们的商城的功能和复杂度还远远不够。商城很多新的需求的优先级确实要比重构要高许多,急需增加的很多功能对解决商户的需求是很重要的,所以技术债的解决也只能是随着需求的变化来适时的同步推进。) 21 | 22 | 此外参与了许多公司项目的开发,个人觉得印象比较深或是说有难度、特色的技术项目包括: 23 | - 商城 Vue 全家桶重构(Vue + Webpack + ES6) 24 | - 商城数据采集与埋点代码搭建 25 | - CDN 资源部署方案(Koa + Mongodb + Vue)等。 26 | 27 | 业务需求项目主要包括: 28 | 29 | - 商城抽奖系统(砸金蛋 + 刮刮卡 + 大转盘..) 30 | - 商城 CMS 31 | - 会员系统及会员特卖 32 | - 感恩节 H5 (D3 + jq) 33 | - 采购工具等项目。 34 | 35 | 在这些项目中除了熟悉应用相关框架、库的方法外,在代码之外还深刻认识到了如下道理,简要列举如下: 36 | 37 | 1. 在 [程序员修炼之道](https://book.douban.com/subject/1152111/) 一书中对代码重构方法的基本原则提炼: 38 | 39 | > 重构是一项需要慎重、深思熟虑、小心进行的活动。关于怎样进行利大于弊的重构, Martin Fowler 给出了以下提示。 40 | > 1. 不要试图在重构的同时增加大量工能。 41 | > 2. 在开始重构之前,确保你拥有良好的测试。 42 | > 3. 对重构任务尽可能的划分为短小、深思熟虑的步骤方案。重构常常涉及到许多局部的改动,在代码复杂度达到一定程度时,这样的改动可能产生很大的影响。如果你的重构步骤能够保持短小,并且每次改动都有良好的测试方案,你将能够避免长时间的调试和隐含的巨大错误。 43 | 44 | 此外还包括重构项目实施的若干方法,在针对不同用户群或项目情况时,重构可以采取不同的方案,来尽可能的做到科学并达到最大化的项目效果。一般公司都是由于技术债的原因导致代码需要重构来保证代码的质量、稳定、功能拓展性等。这里还可以结合我今年 11 月的总结博文里推荐的两篇讨论技术债的文章来更加深入的了解相关的内容([链接](http://www.qcyoung.com/2016/12/05/2016.11%20-%20Do%20whatever%20you%20do%20intensely/)) 45 | 46 | 2. 在职位分工明确的大环境下,工作压力不小的情况中,也要时刻警醒自己的工作计划状态。当你过多的被动工作生活时,就是你需要停下来思考一下的时候了。这里可以参考阮一峰的这篇博文[你的命运不是一头骡子](http://www.ruanyifeng.com/blog/2016/06/your-destiny-is-not-like-a-mule.html) 、 47 | 48 | 3. 这一年的 Alpha Go 、无人驾驶等都展示了深度学习下的计算机应用的加速推进。在愈演愈烈的 AI 浪潮和职业环境背景下,个人更需不断提升自己的核心竞争力来提高自身工作的价值。这就如工厂制造业机械化的演进一样,相信在未来十几年各行各业都将面临新一步的劳动力革命。 49 | 50 | 4. 做事的时候经常换一个角度想想,会有更多更深刻更有意思的发现。方法可以参考这篇博文[做卧底,如何不动声色的毁掉对手的产品](https://mp.weixin.qq.com/s?__biz=MjM5MzE3MDQ3Mw==&mid=402884722&idx=1&sn=f043571eb59b31addba833059c0cf777) 51 | 52 | 5. 正常加班的原则也应当是救急不救穷。 53 | 54 | ## 个人 55 | 56 | - 这一年简单的做了几个完整的个人项目: 57 | 58 | 1. 对个人网站 [qcyoung.com](http://qcyoung.com) 的[主题](https://github.com/yangzj1992/TKL-REVISION)进行完善、增加了新的功能和样式。 59 | 60 | 2. 一个简单的基于网易云音乐 API 的在线音乐播放器 [yPlayer](https://github.com/yangzj1992/yPlayer) 61 | 62 | 3. 一个基于 Koa 的个人题库系统 [Koa Test](https://github.com/yangzj1992/koa-test-middleware) 63 | 64 | 4. 一个基于总结有趣题目 & 面试题 & 算法、数据结构等基础的库[FE-Questions](https://github.com/yangzj1992/FE-Questions) 65 | 66 | - 在开源项目和社区中参与了一些贡献。 67 | 68 | 在[掘金翻译计划](https://github.com/xitu/gold-miner/wiki/%E8%AF%91%E8%80%85%E7%A7%AF%E5%88%86%E8%A1%A8)、[众成翻译](http://zcfy.cc/@yangzj1992/article)参与了十多篇文章的翻译和校对。参与了 [Vue2](http://cn.vuejs.org/about/) 的中文文档翻译校对等。 69 | 70 | ## 其他 71 | 72 | 这一年坚持了扇贝打卡的习惯,没有缺勤一天(`Unbelievable!`)。今日办了新的扇贝新年打卡计划。希望能继续保持。 73 | 74 | 然而今年的 Keep 和吉他计划却夭折了。。这里十分不满意。。毕竟也是真想有生之年有个好身~~材~~体和会一门拿的出手的乐器。 75 | 76 | ## 个人总结 77 | 78 | 按照传统,后面推荐下今年的一些内容 79 | 80 | [All Alone With You - EGOIST](http://music.163.com/#/song?id=26118113) 81 | 82 | [Daisy - STEREO DIVE FOUNDATION](http://music.163.com/#/song?id=28018269) 83 | 84 | [空も飛べるはず - 高杉さと美](http://music.163.com/#/song?id=26608941) 85 | 86 | [花 - 花儿](http://music.163.com/#/song?id=357421) 87 | 88 | [静止 - 花儿](http://music.163.com/#/song?id=357424) 89 | 90 | [シルシ - LiSA](http://music.163.com/#/song?id=29785472) 91 | 92 | [Startear - 春奈るな](http://music.163.com/#/song?id=28949422) 93 | 94 | [ninelie - Aimer / EGOIST](http://music.163.com/#/song?id=409872504) 95 | 96 | [Stay Alive - 高橋李依](http://music.163.com/#/song?id=426502173) 97 | 98 | [夢灯籠 - RADWIMPS](http://music.163.com/#/song?id=426881480) 99 | 100 | 今年很喜欢的几本书: 101 | 102 | [重构](https://book.douban.com/subject/4262627/):通过多样的重构方法,来达到合适的设计模式。分辨那些具有 Bad smell 的代码,提高自己的代码质量。 103 | 104 | [代码大全](https://book.douban.com/subject/1477390/):参与工作进行更多实践之后看这本书,更是大有所悟。很多经典的准则都是数代人的经历所总结的经验。 105 | 106 | [程序员修炼之道](https://book.douban.com/subject/1152111/):讲的很泛,但每个方向都有一些收获。 107 | 108 | [手把手教你读财报](https://book.douban.com/subject/26290085/): 讲解十分落地,面向国内市场。很适合入门级。 109 | 110 | [具体数学](https://book.douban.com/subject/21323941/):很多习题,配合英文版的书籍还能参看翻译。了解并温固了很多数学技巧。 111 | 112 | [累](https://book.douban.com/subject/25739928/):分镜很不错,目前关注无奈而扭曲的女主如何收场。 113 | 114 | [GrandBlue](https://book.douban.com/subject/26294929/):这真的是一本以青春、潜水为主题的故事。 115 | 116 | [亞人](https://book.douban.com/subject/25799687/):漫画的剧情,分镜相当高水准,人物性格塑造的也很优秀。赞 117 | 118 | [進擊的巨人](https://book.douban.com/subject/5906052/): 16 年里剧情又掀起了最后的高潮,目前来看漫画剧情应该也快要完结了,第二季动画在 17 年也将上映(虽然应该会被墙)。结局应该是像《大剑》那样结束,但希望最后还能有新的别出心裁。 119 | 120 | ## 2017 的希望 121 | 122 | 1. 继续学习更多知识,提升自己的实力,争取经济上早日更自由。。 123 | 2. 年年说要努力减肥,今年自然还是不例外。。(年年到最后依然保持 80kg 左右的身材..这句话真是有毒!!!) 124 | 3. 和女朋友继续友好相处,在她读完研后争取一起生活。 125 | 4. 家人朋友生活平安幸福。 126 | 127 | 128 | -------------------------------------------------------------------------------- /【译】如何编写避免垃圾开销的实时 Javascript 代码.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 【译】如何编写避免垃圾开销的实时 JavaScript 代码 3 | date: 2016-06-12 16:33:21 4 | categories: JavaScript 5 | tags: [JavaScript,性能优化,浏览器] 6 | --- 7 | > 原文链接 : [How to write low garbage real-time Javascript](https://www.scirra.com/blog/76/how-to-write-low-garbage-real-time-javascript) 8 | > 原文作者 : [Ashley ](https://www.scirra.com/users/ashley) 9 | > 译文出自 : [掘金翻译计划](https://github.com/xitu/gold-miner) 10 | > 译者 : [yangzj1992](http://qcyoung.com) 11 | > 校对者: [L9m](https://github.com/L9m), [Dwight](https://github.com/ldhlfzysys), [宁金](https://github.com/godofchina) 12 | > 首发于: [掘金](http://gold.xitu.io/entry/575d14937db2a2005437df32/detail) 13 | 14 | _编辑于 2012 年 3 月 27 日: 哇,这篇文章已经写了有很长一段时间了,十分感谢那些精彩的回复!其中有一些对于一些技术的指正,如使用 'delete' 。我知道了使用它可能会导致其他的降速问题,因此,我们在引擎中极少使用它。一如既往的你还需要对所有的事进行权衡并且需要通过其他关注点来平衡垃圾回收机制,这也只是一个在我们引擎中发现的的实用、简单的技术列表,它并不是一个完整的参考列表。但是我希望它还是有用的!_ 15 | 16 | 一个用 Javascript 编写的 HTML5 游戏,要达到流畅体验的一个最大阻碍就是**垃圾回收 ( GC ) 卡顿**。 Javascript 并没有一个显式的内存管理,意味着你创造东西后却不能释放它们占用的内存。因此迟早浏览器便会替你决定去清理它们:这时代码执行就会被暂停,浏览器会找出哪一部分内存是现在仍在被使用的,并把其他所有东西占用的内存释放掉。这篇博文将会去探究避开 GC 开销的技术细节,这对方便进行使用任何插件或是使用 Construct 2 进行 [Javascript SDK](http://www.scirra.com/manual/15/sdk "Construct 2 Javascript Plugin and Behavior SDK")开发都应该能派上用场。 17 | 18 | 浏览器有很多技术性手段来减少 GC 卡顿,但是如果你的代码创造了许多垃圾,迟早浏览器也将会暂停并进行清理。随着对象逐步创建的过程中,之后浏览器又突然清理,这最后将导致内存使用情况图表呈现 z 字形。例如,下面是 Chrome 在玩太空爆破手时的内存使用情况。 19 | 20 | ![Chrome garbage-collected memory usage](https://www.scirra.com/images/chromememoryusage.png) 21 | 22 | _当在玩一个 Javascript 游戏时会呈现 z 字形的内存占用情况。这可能是一个内存泄漏错误,但是实际上是 JavaScript 的正常操作。_ 23 | 24 | 此外,游戏以 60 fps 运行时只有 16 ms 的时间来渲染每一帧,但是 GC 会很轻易的产生最少 100 ms 以上明显的卡顿,在更糟的情况下,这会导致不断卡顿的游戏体验,因此对于像游戏引擎一样实时运行的 Javascript 代码,解决办法是努力尝试在典型帧的持续时间内*你不要创建任何东西*。这实际上是相当困难的,因为有许多看上去无害的 Javascript 语句实际上却创造了垃圾,它们*都*必须从每帧动画的代码路径里删除掉。在 Construct 2 中我们竭尽全力减少每一处引擎的垃圾开销,但是你可以从图表中看到上面仍然有许多小的对象被创建所以 Chrome 还会每隔数秒进行一次清除。要注意这里只是一个小的清理 - 这里并没有大量的内存被清理出来,因为一个更高更极端的z曲线会更引起关注,但是它可能已经足够好了,因为小型的垃圾集合执行会更快并且偶尔的小卡顿也一般不太引人注意 - 因此我们应该看到了,有时我们确实很难避免产生新的资源分配。 25 | 26 | 同样重要的包括第三方插件以及开发人员行为也需要遵守这些原则,否则,一个写的不好的插件可以产生许多垃圾并会让游戏十分卡顿,尽管主引擎 Construct 2 已经是一个非常低垃圾开销的引擎了。 27 | 28 | ## 简单的技巧 29 | 30 | 首先,最明显的是,关键词 `new` 指示了资源的分配,例如 `new Foo()` 在可能的情况下,它会在启动时尝试创建一个对象,并且尽可能长时间、简单的**重新使用相同的对象**。 31 | 32 | 不太明显的是,这里有三种快捷语法方式来相似的调用 `new` : 33 | 34 | `{}` _(创建一个新对象)_ 35 | `[]` _(创建一个新数组)_ 36 | `function () { ... }` _(创建一个新函数,也会被垃圾收集)_ 37 | 38 | 对于对象,用避免 `{}` 一样的方式来避免 `new` - 尝试去回收对象。请注意这包括像 `{ "foo": "bar" }` 这样带属性的对象,也就是我们在函数中常用的一次性返回多个值。或许将每一次的返回值写入一个相同的(全局)对象来返回的写法是更好的 - 在文档中要仔细记录这一点,因为如果你保持引用这样的返回对象,可能在每次调用改变的时候发生错误。 39 | 40 | 实际上你可以回收一个存在的对象(如果它没有原型链)通过删除它的所有属性,将它还原为一个空的对象如 `{}` 一样。为此你可以使用 `cr.wipe(obj)` 函数,它的定义如下: 41 | 42 | ``` js 43 | // remove all own properties on obj, 44 | effectively reverting it to a new object 45 | cr.wipe = function (obj) 46 | { 47 | for (var p in obj) 48 | { 49 | if (obj.hasOwnProperty(p)) 50 | delete obj[p]; 51 | } 52 | }; 53 | ``` 54 | 55 | 因此在某些情况下,你可以调用 `cr.wipe(obj)` 并为其再次添加属性来重用一个对象。比起重新简单分配 `{}` 现场清除一个对象可能需要更长的时间,但是在实时处理的代码中更重要的是避免产生垃圾,从而减少未来可能产生的卡顿情况。 56 | 57 | 分配 `[]` 到一个数组中被经常用来作为一个快捷方式去清除这个数组(例如 `arr = [];`),但请注意这将创建一个新的空数组并使旧的数组成为一个垃圾!更好的写法是 `arr.length = 0;` ,这种方式具有相同的效果但却继续使用了相同的数组对象。 58 | 59 | 函数则有一点棘手,函数通常在执行时创建并且不倾向于在运行时进行过多分配 - 但这意味着它们在动态创建时很容易被忽视。一个例子是返回函数的函数。主要的游戏循环使用了 `setTimeout` 或者 `requestAnimationFrame` 方法来调用一个成员函数类似如下: 60 | 61 | ``` js 62 | setTimeout( 63 | (function (self) { 64 | return function () { 65 | self.tick(); 66 | }; 67 | })(this) 68 | , 16); 69 | ``` 70 | 71 | 这看起来像是一个合理的方式来每 16ms 调用一次 `this.tick()` 。然而,这也意味着每一次执行 tick 函数都会返回一个新函数!这可以通过永久存储函数的方法来避免,例如: 72 | 73 | ``` js 74 | // at startup 75 | this.tickFunc = (function (self) { return function () { 76 | self.tick(); }; })(this); 77 | 78 | // in the tick() function 79 | setTimeout(this.tickFunc, 16); 80 | ``` 81 | 82 | 这将在每次执行 tick 函数时重复使用相同的函数来代替产生一个新的函数。这个方法可以应用到任意其他地方的返回函数中或是运行创建的函数中。 83 | 84 | ## 进阶技巧 85 | 86 | 随着我们的进展,进一步的避免产生垃圾变得更加困难,由于 Javascript 本身就是围绕着 GC 所设计的。许多 Javascript 中方便的库函数也总是创建了新的对象。这儿没有什么你可以做的但是当你返回文档查阅那些返回值时。例如,数组中的 `slice()` 方法会返回一个数组(基于保持不变的原始数组范围内),字符串的 `substr` 会返回一个新的字符串(基于保持不变的原始字符串字符的范围),等等。调用这些函数都会产生垃圾,而你能做的就是不要去调用它们,或是在极端情况下重写你的函数使它们不再产生垃圾。例如在 Construct 2 这种引擎,由于各种原因一个经常的操作是通过索引去删除数组里的一个元素。这个方法的快捷使用方式如下: 87 | 88 | ``` js 89 | var sliced = arr.slice(index + 1); 90 | arr.length = index; 91 | arr.push.apply(arr, sliced); 92 | ``` 93 | 94 | 然而 `slice()` 返回一个原始数组的后半部分来组成了一个新的数组,并且在被 (`arr.push.apply`)复制后产生了垃圾。由于这是我们引擎中一个生产垃圾的热门处,它被改写为了一个迭代版本: 95 | 96 | ``` js 97 | for (var i = index, len = arr.length - 1; i < len; i++) 98 | arr[i] = arr[i + 1]; 99 | 100 | arr.length = len; 101 | ``` 102 | 103 | 显然重写大量的库函数是相当痛苦的,所以你需要仔细的权衡需求实现的方便性以及垃圾产生之间的平衡。如果它在每帧中被调用了很多次,你可能最好重写这个你需要的函数库。 104 | 105 | 这里可以很容易的使用 `{}` 语法来沿着递归函数传递数据。通过一个数组来表示一个堆栈,在这个堆栈中对递归的每一级进行 push 和 pop 是更好的。更好的是,实际上你并不需要在数组中 pop - 你应该将数组中最后一个对象像垃圾一样处理掉。来代替使用一个 `top index` 变量进行简单减量。然后为了代替 pushing ,则增加 `top index` 并且如果有的话就重用数组中的下一个对象,否则执行真正的 push。 106 | 107 | 此外,**在所有可能的情况下避免向量对象**(如 vector2 中的 x 和 y 属性)。虽然可能函数返回这些对象会让它们立刻改变或返回这两个值时会方便些,你可以在*每一帧*中轻松地结束数百个这样的创建对象,这将导致可怕的 GC 性能。这些函数必须分离出来在每个单独的组件中工作,例如:使用 `getX()` 和 `getY()` 来代替 `getPosition()` 来返回一个 vector2 对象。 108 | 109 | 有时候你无法摆脱一个库是一个产生垃圾的噩梦。 Box2Dweb 是一个典型的例子:它每一帧产生了数百个 b2Vec2 对象并且不断的在浏览器产生垃圾,并最终导致垃圾处理器产生显著的卡顿效果。在这种情况下最好的办法是创建一个缓存回收机制。我们一直在测试 Box2D ([Box2Dweb-closure](https://github.com/illandril/box2dweb-closure)) 的修正版本,它似乎可以使 GC 暂停进行缓解(虽然没有完全解决)。查阅 [b2Vec2.js](https://github.com/illandril/box2dweb-closure/blob/master/src/common/math/b2Vec2.js) 的 `Get` 和 `Free` 代码。这里有一个名字叫 `free cache` 的数组,在之后的整个代码中如果不再使用 b2Vec2,它就会在 free cache 中被释放,当需要请求一个新的 b2Vec2,而它如果在 free cache 中还存在那么它就会被重用,否则才会分配一个新的。这并不完美,在一些测试后通常只有一半的 b2Vec2s 被创建并回收,但它确实帮助 GC 缓解了压力从而减少了频繁的卡顿。 110 | 111 | ## 结论 112 | 113 | 在 Javascript 中很难去完全避免垃圾。它的垃圾收集模式根本上是不符合像游戏这样的实时软件的需求的。从 Javascript 代码中需要进行大量的工作来消除垃圾,因为有很多直接的代码含有创建大量垃圾的副作用。然而,只要仔细小心一些,Javascript 也是可以在实时项目中不产生或是制造很少的垃圾开销,而对于需要保持高度响应性的游戏和应用程序这也是至关重要的。 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /微信内置浏览器不支持gzip压缩及gzip模块配置简述.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 微信内置浏览器不支持 gzip 压缩方式及 gzip 模块配置简述 3 | date: 2015-11-11 17:50:02 4 | categories: 微信X5浏览器 5 | tags: [微信浏览器,AJAX,gzip,性能优化,HTTP] 6 | --- 7 | 8 | ### 情况 9 | 今天在做微信项目用 ajax 传值时发现了一些异常的现象。使用微信版本:6.3.7 10 | 11 | ![异常 ajax 列表](http://qcyoung.qiniudn.com/qcyoung/微信内置浏览器不支持gzip压缩方式及gzip模块配置简述/yichang1.png) 12 | 13 | 1 个 ajax 请求请求了 120kb?!打开此请求详情看了一下发现了一个关键点。 14 | 15 | ![微信请求头](http://qcyoung.qiniudn.com/qcyoung/微信内置浏览器不支持gzip压缩方式及gzip模块配置简述/weixin_requestheader.png) 16 | 17 | 这个微信请求,在请求头中没有接受编码头(`Accept-Encoding`),而在正常的电脑 Chrome 中 `Accept-Encoding` 是正常的。 18 | 19 | ![Chrome 请求头](http://qcyoung.qiniudn.com/qcyoung/微信内置浏览器不支持gzip压缩方式及gzip模块配置简述/chrome_requestheader.png) 20 | 21 | 难道是微信浏览器不支持 gzip 的压缩方式?这里我抓包做了实验,首先我在电脑端 Chrome 下把 `Accept-Encoding` 中的 gzip 值干掉进行请求。果然,请求的大小一下子飙升到微信上请求的相应大小 22 | 23 | ![请求列表](http://qcyoung.qiniudn.com/qcyoung/微信内置浏览器不支持gzip压缩方式及gzip模块配置简述/chrome_kill_gzip_list.png) 24 | 25 | 此请求报表头如下: 26 | 27 | ![清理头](http://qcyoung.qiniudn.com/qcyoung/微信内置浏览器不支持gzip压缩方式及gzip模块配置简述/chrome_kill_gzip_header.png) 28 | 29 | ### w3标准 30 | 由于在 w3.org 中关于 [XMLHttpRequest](http://www.w3.org/TR/XMLHttpRequest/) 的描述中指出 31 | 32 | > 4.6.2 The setRequestHeader() method 33 | > 34 | > Terminate these steps if header is a case-insensitive match for one of the following headers: 35 | > - Accept-Charset 36 | > - Accept-Encoding 37 | > - Access-Control-Request-Headers 38 | > - Access-Control-Request-Method 39 | > - Connection 40 | > - Content-Length 41 | > - Cookie 42 | > - Cookie2 43 | > - Date 44 | > - DNT 45 | > - Expect 46 | > - Host 47 | > - Keep-Alive 48 | > - Origin 49 | > - Referer 50 | > - TE 51 | > - Trailer 52 | > - Transfer-Encoding 53 | > - Upgrade 54 | > - User-Agent 55 | > - Via 56 | 57 | > The above headers are controlled by the user agent to let it control those aspects of transport. This guarantees data integrity to some extent. Header names starting with Sec- are not allowed to be set to allow new headers to be minted that are guaranteed not to come from XMLHttpRequest. 58 | 59 | 上面的消息头被认为是应当由浏览器控制,而不能用 XMLHttpRequest 对象来修改,即不能通过 JavaScript 修改。但是这也只是 W3 建议的标准而已,至于浏览器遵不遵循标准,那就得看开发人员了。 60 | 61 | 这里为了测试,可以试着写一个 PHP,回显 `User-Agent`: 62 | 63 | ``` php 64 | 67 | ``` 68 | 69 | 然后再次发送 ajax 请求,并在发送之前用 XMLHttpRequest 对象的 `setRequestHeader` 方法修改 `User-Agent`: 70 | 71 | ``` js 72 | $.ajax({ 73 | type: "GET", 74 | url: "ua.php", 75 | success: function(data) { 76 | alert(data); 77 | }, 78 | beforeSend: function(xhr) { 79 | xhr.setRequestHeader("User-Agent", "uTorrent"); 80 | } 81 | }); 82 | ``` 83 | 84 | 通过测试最后得到结论:IE 还是跟往常一样无视标准的存在,可以用 JavaScript 在 ajax 请求中设置 `User-Agent`,而 FireFox 和 Chrome 都无法修改 `User-Agent`。 85 | 86 | ### 其余网站验证 87 | 之后我测试了一米鲜和京东的相关页面,也发现了类似的情况。这里拿 JD 举例。 88 | 89 | 在微信中未压缩请求,大小 17.53kb。 90 | ![jd](http://qcyoung.qiniudn.com/qcyoung/微信内置浏览器不支持gzip压缩方式及gzip模块配置简述/weixinjd.png) 91 | 92 | 请求头如下 93 | 94 | ![jd](http://qcyoung.qiniudn.com/qcyoung/微信内置浏览器不支持gzip压缩方式及gzip模块配置简述/chrome_jd_header副本.png) 95 | 96 | 在手机 Chrome 下启用 gzip 大小为 5.2kb: 97 | 98 | ![jd](http://qcyoung.qiniudn.com/qcyoung/微信内置浏览器不支持gzip压缩方式及gzip模块配置简述/mobile_chrome_jd_list.png) 99 | 100 | ![jd](http://qcyoung.qiniudn.com/qcyoung/微信内置浏览器不支持gzip压缩方式及gzip模块配置简述/mobile_chrome_jd_header.png) 101 | 102 | 103 | ### gzip 配置说明 104 | 另外在这个过程中还核对了 nginx 的 gzip 模块配置,这里顺便一路贴出来吧: 105 | 106 | ``` bash 107 | > Gzip 模块的各项配置 108 | 109 | > gzip on|off; 110 | > # 默认值: gzip off 111 | > # 开启或者关闭gzip模块 112 | > 113 | > gzip_static on|off; 114 | > # nginx对于静态文件的处理模块 115 | > # 该模块可以读取预先压缩的gz文件,这样可以减少每次请求进行gzip压缩的CPU资源消耗。该模块启用后, 116 | nginx首先检查是否存在请求静态文件的gz结尾的文件,如果有则直接返回该gz文件内容。为了要兼容不支持 117 | gzip的浏览器,启> 用gzip_static模块就必须同时保留原始静态文件和gz文件。这样的话,在有大量静态 118 | 文件的情况下,将会大大增加磁盘空间。我们可以利用nginx的反向代理功能实现只保留gz文件。 119 | > # 可以google"nginx gzip_static"了解更多 120 | > 121 | > gzip_comp_level 4; 122 | > # 默认值:1(建议选择为4) 123 | > # gzip压缩比/压缩级别,压缩级别 1-9,级别越高压缩率越大,当然压缩时间也就越长(传输快但比较消耗cpu)。 124 | > 125 | > gzip_buffers 4 16k; 126 | > # 默认值: gzip_buffers 4 4k/8k 127 | > # 设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。 例如 4 4k 代表以4k为单位,按照原 128 | 始数据大小以4k为单位的4倍申请内存。 4 8k 代表以8k为单位,按照原始数据大小以8k为单位的4倍申请内存。 129 | > # 如果没有设置,默认值是申请跟原始数据相同大小的内存空间去存储gzip压缩结果。 130 | > 131 | > gzip_types mime-type [mime-type ...]; 132 | > # 默认值: gzip_types text/html (默认不对js/css文件进行压缩) 133 | > # 压缩类型,匹配MIME类型进行压缩 134 | > # 不能用通配符 text/* 135 | > # (无论是否指定)text/html默认已经压缩 136 | > # 设置哪压缩种文本文件可参考 conf/mime.types 137 | > 138 | > gzip_min_length 1k; 139 | > # 默认值: 0 ,不管页面多大都压缩 140 | > # 设置允许压缩的页面最小字节数,页面字节数从header头中的Content-Length中进行获取。 141 | > # 建议设置成大于1k的字节数,小于1k可能会越压越大。 即: gzip_min_length 1024 142 | > 143 | > gzip_http_version 1.0|1.1; 144 | > # 默认值: gzip_http_version 1.1(就是说对HTTP/1.1协议的请求才会进行gzip压缩) 145 | > # 识别http的协议版本。由于早期的一些浏览器或者http客户端,可能不支持gzip自解压,用户就会看到乱码, 146 | 所以做一些判断还是有必要的。 147 | > # 注:99.99%的浏览器基本上都支持gzip解压了,所以可以不用设这个值,保持系统默认即可。 148 | > # 假设我们使用的是默认值1.1,如果我们使用了proxy_pass进行反向代理,那么nginx和后端的upstream server 149 | 之间是用HTTP/1.0协议通信的,如果我们使用nginx通过反向代理做Cache > Server,而且前端的nginx没有开启gzip, 150 | 同时,我们后端的nginx上没有设置gzip_http_version为1.0,那么Cache的url将不会进行gzip压缩 151 | > 152 | > gzip_proxied [off|expired|no-cache|no-store|private|no_last_modified|no_etag|auth|any] ...; 153 | > # 默认值:off 154 | > # Nginx作为反向代理的时候启用,开启或者关闭后端服务器返回的结果,匹配的前提是后端服务器必须要返回 155 | 包含"Via"的 header头。 156 | > # off - 关闭所有的代理结果数据的压缩 157 | > # expired - 启用压缩,如果header头中包含 "Expires" 头信息 158 | > # no-cache - 启用压缩,如果header头中包含 "Cache-Control:no-cache" 头信息 159 | > # no-store - 启用压缩,如果header头中包含 "Cache-Control:no-store" 头信息 160 | > # private - 启用压缩,如果header头中包含 "Cache-Control:private" 头信息 161 | > # no_last_modified - 启用压缩,如果header头中不包含 "Last-Modified" 头信息 162 | > # no_etag - 启用压缩 ,如果header头中不包含 "ETag" 头信息 163 | > # auth - 启用压缩 , 如果header头中包含 "Authorization" 头信息 164 | > # any - 无条件启用压缩 165 | > 166 | > gzip_vary on; 167 | > # 和http头有关系,加个vary头,给代理服务器用的,有的浏览器支持压缩,有的不支持,所以避免浪费不支持 168 | 的也压缩, 169 | 所以根据客户端的HTTP头来判断,是否需要压缩 170 | > 171 | > gzip_disable "MSIE [1-6]."; 172 | > # 禁用IE6的gzip压缩,又是因为杯具的IE6。当然,IE6目前依然广泛的存在,所以这里你也可以设置为“MSIE [1-5].” 173 | > # IE6的某些版本对gzip的压缩支持很不好,会造成页面的假死,为了确保其它的IE6版本不出问题,所以建议加上 174 | gzip_disable的设置 175 | ``` 176 | -------------------------------------------------------------------------------- /【译】JavaScript 变量的生命周期:为什么 let 不存在变量提升.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 【译】JavaScript 变量的生命周期:为什么 let 不存在变量提升 3 | date: 2016-08-03 13:21:20 4 | categories: JavaScript 5 | tags: [JavaScript,ECMAScript6] 6 | --- 7 | > 原文链接 : [JavaScript variables lifecycle: why let is not hoisted](https://rainsoft.io/variables-lifecycle-and-why-let-is-not-hoisted/) 8 | > 原文作者 : [Dmitri Pavlutin](https://rainsoft.io/author/dmitri-pavlutin/) 9 | > 译文出自 : [众成翻译](http://zcfy.cc/) 10 | > 译者 : [yangzj1992](http://qcyoung.com) 11 | > 校对者: [lisa](https://www.zhihu.com/people/ha-ha-qiu-52) 12 | > 首发于: [众成翻译](http://zcfy.cc/article/javascript-variables-lifecycle-why-let-is-not-hoisted-976.html) 13 | 14 | 变量提升是一个将变量或者声明函数提升到作用域起始处的过程,通常指的是变量声明 `var` 和函数声明 `function fun() {...}` 15 | 16 | 当 `let`(以及具备了和 `let` 相似声明行为的 `const` 和 `class`)等声明方式在 ES2015 中被引入后,许多的开发者包括我都使用了*变量提升*的定义来描述变量是如何被访问的。但经过对这个问题更多的搜索后,我十分惊讶的发现*变量提升*并不是可以用来准确描述 `let` 变量初始化和可用性的合适术语。 17 | 18 | ES2015 为 `let` 提供了一个不同的改进机制。它要求了更严格的变量声明方式(你在定义变量前是无法访问它的)并且这也在结果上保证了更好的代码质量。 19 | 20 | 现在让我们一起深入了解关于这个过程的更多细节。 21 | 22 | ### 容易出错的 `var` 变量提升 23 | 24 | 有时我会在作用域下的任何位置上看到一个奇怪的变量声明 `var varname` 和函数声明 `function funName() {...}` 。 25 | 26 | [Try in JS Bin](http://jsbin.com/fewiri/1/edit?js,console) 27 | 28 | ``` js 29 | // var hoisting 30 | num; // => undefined 31 | var num; 32 | num = 10; 33 | num; // => 10 34 | // function hoisting 35 | getPi; // => function getPi() {...} 36 | getPi(); // => 3.14 37 | function getPi() { 38 | return 3.14; 39 | } 40 | ``` 41 | 42 | 变量 `num` 在它的声明语句 `var num` 之前就被访问了,所以它的值为 `undefined` 43 | 44 | 函数 `function getPi() {...}` 是定义在文件的末尾的。然而函数可以在它声明 `getPi()` 之前就被调用,因为它被提升到了作用域的顶部。 45 | 46 | 这就是典型的*变量提升*。 47 | 48 | 事实证明,在首次使用变量或函数后才声明变量或函数会很容易产生困惑。假设你正滚动查看一个大文件,然后发现了一个未声明的变量...你肯定会想它到底为什么在这里出现并且它是在哪定义的呢? 49 | 50 | 当然一个熟练的 JavaScript 开发者并不会这样编写代码。但在成千上万个 JavaScript Github 库中却可能存在着相当数量的这样的代码。 51 | 52 | 甚至在上面给出的代码示例中,我们也很难去明白代码中的声明流程。 53 | 54 | 我们应当自然地首先声明或是描述一个未知的术语。在这之后再对它进行使用。`let` 便是鼓励你遵循这种方法来设置变量。 55 | 56 | ### 深层内容: 变量的生命周期 57 | 58 | 当引擎使用变量时,它们的生命周期包含以下阶段: 59 | 60 | 1. **声明阶段** 这一阶段在作用域中注册了一个变量。 61 | 62 | 2. **初始化阶段** 这一阶段分配了内存并在作用域中让内存与变量建立了一个绑定。在这一步变量会被自动初始化为 `undefined` 。 63 | 64 | 3. **赋值阶段** 这一阶段为初始化变量分配具体的一个值。 65 | 66 | 一个变量在通过声明阶段时它还是处于 **未初始化的** 状态,这时它仍然还没有到达初始化阶段。 67 | 68 | ![Infographic](http://p0.qhimg.com/t01ea63a0e0c145b0f3.jpg) 69 | 70 | 注意,按照变量的生命周期过程,*声明阶段*与我们通常所说的*变量声明*是不同的术语。简单来讲,引擎处理变量声明需要经过完整的这 3 个阶段:声明阶段,初始化阶段和赋值阶段。 71 | 72 | ### `var` 变量的生命周期 73 | 74 | 稍微熟悉下这些生命周期阶段,现在让我们用它们来描述引擎是如何处理 `var` 变量的。 75 | 76 | ![Infographic](http://p0.qhimg.com/t014b5f030a2ed83760.jpg) 77 | 78 | 假设一个场景,当 JavaScript 遇到了一个函数作用域,其中包含了 `var variable` 的语句。则在任何语句执行之前,这个变量在作用域的开头就通过了*声明阶段*并马上来到了*初始化阶段*(步骤一)。 79 | 80 | 同时 `var variable` 在函数作用域中的位置并不会影响它的声明和初始化阶段的进行。 81 | 82 | 在声明和初始化阶段之后,赋值阶段之前,变量的值便是 `undefined` 并已经可以被使用了。 83 | 84 | 在*赋值阶段* `variable = 'value'` 语句使变量接受了它的初始化值(步骤二)。 85 | 86 | 这里的*变量提升*严格的说是指变量在函数作用域的*开始位置就完成了声明和初始化阶段*。在这里这两个阶段之间并没有任何的间隙。 87 | 88 | 让我们参考一个示例来研究。下面的代码创建了一个包含 `var` 语句的函数作用域: 89 | 90 | [Try in JS Bin](http://jsbin.com/karuxe/3/edit?js,console) 91 | 92 | ``` js 93 | function multiplyByTen(number) { 94 | console.log(ten); // => undefined 95 | var ten; 96 | ten = 10; 97 | console.log(ten); // => 10 98 | return number * ten; 99 | } 100 | multiplyByTen(4); // => 40 101 | ``` 102 | 103 | 当 JavaScript 开始执行 `multipleByTen(4)` 时进入了函数作用域中,变量 `ten` 在第一个语句之前就经过了声明和初始化阶段,所以当调用 `console.log(ten)` 时打印为 `undefined`。 104 | 105 | 当语句 `ten = 10` 为变量赋值了初始化值。在赋值后,语句 `console.log(ten)` 打印了正确的 `10` 值。 106 | 107 | ### 函数声明的生命周期 108 | 109 | 对于一个 *函数声明语句* `function funName() {...}` 那就更简单了。 110 | 111 | ![Infographic](http://p0.qhimg.com/t0134485377a7130217.jpg) 112 | 113 | *声明、初始化和赋值阶段*在封闭的函数作用域的开头便立刻进行(只有一步)。 `funName()` 可以在作用域中的任意位置被调用,这与其声明语句所在的位置无关(它甚至可以被放在程序的最底部)。 114 | 115 | 下面的代码是一个函数提升的演示: 116 | 117 | [Try in JS Bin](http://jsbin.com/ximedo/2/edit?js,console) 118 | 119 | ``` js 120 | function sumArray(array) { 121 | return array.reduce(sum); 122 | function sum(a, b) { 123 | return a + b; 124 | } 125 | } 126 | sumArray([5, 10, 8]); // => 23 127 | ``` 128 | 129 | 当 JavaScript 执行 `sumArray([5, 10, 8])` 时,它便进入了 `sumArray` 的函数作用域。在作用域内,任何语句执行之前的瞬间,`sum` 就经过了所有的三个阶段:声明,初始化和赋值阶段。 130 | 131 | 这样 `array.reduce(sum)` 即使在它的声明语句 `function sum(a, b) {...}` 之前也可以使用 `sum`。 132 | 133 | ### `let` 变量的生命周期 134 | 135 | `let` 变量的处理方式不同于 `var`。它的主要区分点在于声明和初始化阶段是分开的。 136 | 137 | ![Infographic](http://p0.qhimg.com/t0122846bdbec4513d7.jpg) 138 | 139 | 现在让我们研究这样一个场景,当解释器进入了一个包含 `let variable` 语句的块级作用域中。这个变量立即通过了*声明阶段*,并在作用域内注册了它的名称(步骤一)。 140 | 141 | 然后解释器继续逐行解析块语句。 142 | 143 | 这时如果你在这个阶段尝试访问 `variable`,JavaScript 将会抛出 `ReferenceError: variable is not defined`。因为这个变量的状态依然是*未初始化*的。 144 | 145 | 此时 `variable` 处于*临时死区*中。 146 | 147 | 当解释器到达语句 `let variable` 时,此时变量通过了初始化阶段(步骤二)。现在变量状态是*初始化的*并且访问它的值是 `undefined`。 148 | 149 | 同时变量在此时也离开了*临时死区*。 150 | 151 | 之后当到达赋值语句 `variable = 'value'` 时,变量通过了赋值阶段(步骤三)。 152 | 153 | 如果 JavaScript 遇到这样的语句 `let variable = 'value'` ,那么变量会在这一条语句中同时经过初始化和赋值阶段。 154 | 155 | 让我们继续看一个示例。这里 `let` 变量 `number` 被创建在了一个块级作用域中: 156 | 157 | [Try in JS Bin](http://jsbin.com/qixoko/2/edit?js,console) 158 | 159 | ``` js 160 | let condition = true; 161 | if (condition) { 162 | // console.log(number); // => Throws ReferenceError 163 | let number; 164 | console.log(number); // => undefined 165 | number = 5; 166 | console.log(number); // => 5 167 | } 168 | ``` 169 | 170 | 当 JavaScript 进入 `if (condition) {...}` 块级作用域中,`number` 立即通过了声明阶段。 171 | 172 | 因为 `number` 尚未初始化并且处于临时死区,此时试图访问该变量会抛出 `ReferenceError: number is not defined`. 173 | 174 | 之后语句 `let number` 使其得以初始化。现在变量可以被访问,但它的值是 `undefined`。 175 | 176 | 之后赋值语句 `number = 5` 当然也使变量经过了赋值阶段。 177 | 178 | `const` 和 `class` 类型与 `let` 有着相同的生命周期,除了它们的赋值语句只会发生一次。 179 | 180 | #### 为什么变量提升在 `let` 的生命周期中无效 181 | 182 | 如上所述,*变量提升*是变量的*耦合*声明并且在作用域的顶部完成初始化。 183 | 184 | 然而 `let` 生命周期中将声明和初始化阶段*解耦*。这一解耦使 `let` 的*变量提升*现象消失。 185 | 186 | 由于两个阶段之间的间隙创建了临时死区,在此时变量无法被访问。 187 | 188 | 这就像科幻的风格一样,在 `let` 生命周期中由于*变量提升*失效所以产生了临时死区。 189 | 190 | ### 结论 191 | 192 | 使用 `var` 自由的去声明变量很容易出现错误。 193 | 194 | 基于这一点,ES2015 引进了 `let`。它使用了一种改进的算法来声明变量并添加了块作用域。 195 | 196 | 因为声明和初始化阶段是解耦的,变量提升对于 `let` 变量(也包括 `const` 和 `class`)是无效的。在初始化之前,变量处于临时死区中并不可被访问。 197 | 198 | 为了保证平稳的变量声明,推荐这些技巧以供参考: 199 | 200 | * 声明,初始化变量后再使用变量。这个流程才是正确并易于遵循的。 201 | 202 | * 尽可能的减少变量数。你暴露的变量越少,你的代码则会变得更加模块化。 203 | 204 | 这就是今天所有的内容。我们在下一篇文章再见。 -------------------------------------------------------------------------------- /【译】UI 的黑暗面!暗色背景的优势.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 【译】UI 的黑暗面!暗色背景的优势 3 | date: 2016-07-06 12:45:39 4 | categories: UED 5 | tags: [UI,UX,网页设计] 6 | --- 7 | > 原文链接 : [Dark Side of UI. Benefits of Dark Background](https://medium.com/@tubikstudio/dark-side-of-ui-benefits-of-dark-background-12f560bf7165#.k0d00u47a) 8 | > 原文作者 : [Tubik Studio](https://medium.com/@tubikstudio) 9 | > 译文出自 : [掘金翻译计划](https://github.com/xitu/gold-miner) 10 | > 译者 : [yangzj1992](http://qcyoung.com) 11 | > 校对者: [David Lin](https://github.com/wild-flame), [Ruixi](https://github.com/Ruixi) 12 | > 首发于: [掘金](http://gold.xitu.io/entry/577c9385a633bd005be7fe7a/detail) 13 | 14 | ![](http://ac-Myg6wSTV.clouddn.com/18dcdce02f167c38bd04.jpeg) 15 | 16 | 在用户界面的背景中是否选择使用暗色调依然是一个具有高度争议的问题。毋庸置疑,这个问题是很实际的:选择一个合适的背景在所有的产品功效上都起着至关重要的作用,因为它可能会是改善或是反而毁掉设计方案中布局和功能的关键因素。在今天,我们的文章将致力于讨论在 UI 设计中使用暗色背景的好处和缺陷,所以让我们前往 UI 的黑暗面吧。 17 | 18 | 在我们[之前的文章](http://tubikstudio.com/light-and-darkness-in-ui-design-matter-of-choice/)中我们已经分析了一些可以影响选择通常的配色方案和基本的背景颜色的因素,也提到了一些在这个过程中要考虑的重点。这一次我们将更多的关注暗色设计的网站和移动应用的优缺点。我们在 [Tubik Studio](http://tubikstudio.com/) 中创建并测试了不同的用户界面,这些实际的工作经验证实了暗色背景会是强大而有吸引力的、能提供积极用户体验的解决方案。所以,理所当然的,让我们来开始讨论应该在何时何地怎样让它最大程度的发挥效果吧。 19 | 20 | ### 对于暗色的视觉感知 21 | 22 | 很久之前,在 2009 年曾有过一个公开的投票调查结果,[ProBlogger](http://www.problogger.net/archives/2009/05/19/light-or-dark-blog-backgrounds-poll-results/) 基于此已经公布了一些有趣的观点。读者被问及他们更喜欢哪种颜色的博客背景。几乎一半的读者回答更喜欢亮色背景 - 这对于传统的文本驱动型博客来说是十分合理的,在可读性方面如此可以胜过其他方案。然而,有 10% 的受访者回答他们更喜欢暗色背景,并且有超过三分之一的人提到选择的依据应该取决于博客的性质和内容。设计师在寻找设计方案时是不能忽略占有如此大比例的用户的。此外,在具有更少的文本型驱动内容的数字产品情况时,如网站或应用程序中,持上述观点的人数比例应该还会增加。这个例子很好的说明了用户研究和调查应该是设计过程中的重要组成部分。了解用户想要什么或是至少了解他们所能够接受的是什么,这能够将传统视觉的限度推向一个极致。 23 | 24 | Richard H. Hall 和 Patrick Hanna 对于这个问题提供的[科学研究](http://lite.mst.edu/media/research/ctel/documents/LITE-2003-04.pdf)中强调了视觉感知的背景颜色和效果的关键点。在分析了不同研究者之前对网络页面效果和可读性方面的实际试验后。作者们总结了:「*他们发现正向对比(即白底黑字)会有更好的效果,并与之前提到的研究结合,说明颜色组合之间的对比度越大效果越好。*」因此在合适的设计和测试下,在其他方面深色背景也可以像浅色背景一样具有好的效果,尤其是在对比性以及布局元素的易读性上。在用户测试角度上这项研究基于不同颜色组合和效果下包含了很多有趣及有用的信息。所以在此强烈推荐给设计师们。 25 | 26 | ![](http://ac-Myg6wSTV.clouddn.com/f5f8b33e3c4fb542fef3.jpg) 27 | 28 |
Ribbet 的用户界面来自 Tubik Studio
29 | 30 | ### 可读性方面 31 | 32 | 用户体验设计的著名大师之一 Jacob Nielsen 曾提到过:「*在使用高对比度颜色的文本和背景时。最优的易读性方案是要求使用黑色文字和白色背景(所谓的正向文本)。而白色文字和黑色背景(反向文本)几乎也是一样好的。尽管这在对比度上与正向文本是一样的,但倒配色方案会让人们略微有些迷惑并会稍微降低他们的阅读速度。易读性相当受配色方案的影响,像文本比纯黑稍亮的颜色,尤其是背景色比纯白稍暗的配色,易读性会变得很差。*」 33 | 34 | 的确,可读性是产品效果表现上的重要指标并且它不仅只针对文本。它超越了文本的限制并且意味着所有有意义的象征,包括字母,数字,象形符号和图片都应该被留意到并轻易的在界面中识别出。因此,设计师在选择深色的背景时应该准备更额外深入的选择并测试不同设备上的字体、图标和图像。 35 | 36 | ![](http://ac-Myg6wSTV.clouddn.com/30476ea6fc9c5178170f.png) 37 | 38 |
SwiftyBeaver 的着陆页,来自 Ludmila Shevchenko
39 | 40 | 最好的网页和应用程序的设计实践,例如 [Awwwards 上最好的黑色网站](http://www.awwwards.com/websites/black/)合集上的例子,这里展现了大量使用深色背景作为基础配色的优秀设计方案,这些方案都没有以牺牲可读性为代价。为了避免低可读性这个问题,在设计过程中重要的是要记住: 41 | 42 | * 深色背景会吸收一部分其他元素的光线,所以应该在元素之间留有足够的空间或"气"; 43 | * 行的长度可以让文本区块对用户更具可读性并易于理解; 44 | * 行间距的空间设计,以及文本行的长度问题都会对可读性具有很大的影响,在深色背景下尤甚,所以段落的大小,字距和行间距都需要仔细考虑。 45 | * 深色并不总是意味着黑色,所以在每一个特定情况的设计中,去花费一些时间测试不同种类的深色背景和颜色所呈现的内容是十分合理的,在试验中尽情的尝试吧; 46 | * 阴影,渐变和光晕都会影响可读性; 47 | * 无衬线字体通常比较清晰,而衬线字体看起来更加优雅,在实践中应用这个因素可以增强内容的可读性。 48 | 49 | ### 对比度方面 50 | 51 | [webdesign.about.com](http://webdesign.about.com/od/color/l/bl_contrast_table.htm) 用表格展现了一个有趣的视觉感知方面需要考虑的展现效果。该表展示了不同的颜色组合之间的对比和效果水平并提供了一个有趣的事实:表中的黑色部分是唯一一个可以为几乎所有颜色提供良好对比度效果的颜色。因此在设计界面的每一个特定情况下去仔细试验,这一因素可以作为尝试使用深色背景的理由之一。 52 | 53 | ![](http://ac-Myg6wSTV.clouddn.com/962624f37bb9c9a8b839.jpg) 54 | 55 | 在可读性方面,对比度能是使内容更容易识别和清晰的因素之一。 56 | 57 | 关于对比度和可读性的这种提示信息在之前的一个[早期的调查](http://www.writer2001.com/colwebcontrast.htm)中有说过:「_在深色背景下,确保你没有包含相当明亮的字体:使用柔和的白色到浅灰色字体,或使用单调的色彩来最小程度的减少巨大的反差和眩光;这个原则在做幻灯片时也同样适用:用至少 5% 的灰度来减少眩光的亮白。有趣的是,这样仍然在「阅览」时会被认为是白色的。同样的,将字体加粗,可以让字体有足够的大小让人不觉得文字被深色背景所「吞噬」_」这个试验以及其他试验能够提供不同类型的调色法,而这些调色法能够为网页和应用页面提供高效、自然的内容。 58 | 59 | 还有一件事就是深色背景在某种程度上通常显得更沉重以及能更深入的呈现图形的内容如图片,相片,插图,海报和广告。良好的构图并遵守视觉层级原则可以显著的增强这种布局元素的视觉感知。这个因素在当界面基于更多图形材料而非文本时会使深色背景更高效并且具有吸引力。 60 | 61 | ![](http://ac-Myg6wSTV.clouddn.com/ffb8689a5486125bdc5b.png) 62 | 63 |
一款分析应用来自 Ludmila Shevchenko
64 | 65 | ### 情感感知方面 66 | 67 | 色彩心理学也是在选择背景颜色时需要考虑到的,这不仅只是包含在所展现的有效范围中,还包含内容自身所承担的信息载体。黑暗的颜色通常与优雅和神秘感有关。此外,黑色往往与优雅,礼节,声望和权利有关。这或许是为什么许多强大的品牌都会使用黑白色调的主题,用深色来主导、用亮色来展示承载的信息,使用这样的方案来构建视觉展现效果。界面设计在这方面可以为其他设计解决方案和一般的产品展示提供额外的支持。 68 | 69 | ![](http://ac-Myg6wSTV.clouddn.com/dd0719f001ef35d5600e.gif) 70 | 71 |
Tubik Studio | 博物馆 来自 Ernest Asanov
72 | 73 | ### 深色背景的优势 74 | 75 | 根据上述各点,我们可以总结得到在用户界面应用深色背景可以提供以下实际好处,包括: 76 | 77 | * 格调及优雅 78 | * 神秘感 79 | * 奢华显赫的外观 80 | * 可以广范围的运用对比 81 | * 支持视觉层次的展示 82 | * 反映内容的深度 83 | * 视觉吸引力。 84 | 85 | ![](http://ac-Myg6wSTV.clouddn.com/7947c9ab8ad7a9dd9128.png) 86 | 87 |
Tubik Studio | Vinny 的面包店 来自 Ernest Asanov
88 | 89 | ### 考虑要点 90 | 91 | 在另一方面,深色背景需要彻底的关注和分析最微小的细节,如果它们没有以合适的方式呈现,那么这些细节则可能会在布局中变得模糊。因此我们应该考虑: 92 | 93 | * **用户研究** 实际调查,理论研究和试验数据是针对目标用户十分重要的数据资源,他们的需求是选择有效和有吸引力的设计方案的基础。 94 | * **竞争研究** 对关系密切的竞争对手进行市场研究,可以理解已经被市场上其他对手使用的设计方案,并且这一因素会影响到原始设计的选择从而使产品更加明显。 95 | * **用户测试** 深色背景在可读性和易读性方面是十分脆弱的,所以应当在各种类型的设备和分辨率下严格的去测试。 96 | * **环境因素** 去分析典型条件下将被用于目标用户的产品,可以为选择或反对深色背景提供其他的理由。 97 | * **大量的内容** 元素和块的数量需要在屏幕或网页上达到能影响周围背景的决策:深色的背景如果在元素间留下了太少的空间会为视觉造成极大的困难。 98 | * **内容的性质** 相比于大量的文本区块,深色背景可以为基于图形元素的界面提供更好的展示效果。 99 | 100 | ![](http://ac-Myg6wSTV.clouddn.com/695e0a55cb834721ce2b.gif) 101 | 102 |
关于食谱和烹饪的 GIF 动画 来自 Sergey Valiukh
103 | 104 | ### 推荐阅读 105 | 106 | * [**The Impact of Web Page Text-Background Color Combinations on Readability, Retention, Aesthetics, and Behavioral Intention**](http://lite.mst.edu/media/research/ctel/documents/LITE-2003-04.pdf) 107 | * [**Visual Perception: An Introduction**](https://books.google.com.ua/books?id=rvt4a_AmKFQC&pg=PA11&lpg=PA11&dq=visual+perception+readability&source=bl&ots=6_rkYdGkj9&sig=_UYthMOEgDSLJEFftDA895epms8&hl=ru&sa=X&ved=0ahUKEwjiwPjRmsPMAhVOKywKHf1FCSM4FBDoAQgtMAM#v=onepage&q=visual%20perception%20readability&f=false) 108 | * [**Art and Visual Perception: A Psychology of the Creative Eye**](https://books.google.com.ua/books?id=9RktoatXGQ0C&pg=PA350&lpg=PA350&dq=visual+perception+readability&source=bl&ots=NTLfJ_Akj6&sig=bpw4URR8U-QwWZwOndhoYs-wJWE&hl=ru&sa=X&ved=0ahUKEwjiwPjRmsPMAhVOKywKHf1FCSM4FBDoAQgZMAA#v=onepage&q=visual%20perception%20readability&f=false) 109 | * [**Colour Choices on Web Pages: Contrast vs Readability**](http://www.writer2001.com/colwebcontrast.htm) 110 | * [**The Dos and Don’ts of Dark Web Design**](http://www.webdesignerdepot.com/2009/08/the-dos-and-donts-of-dark-web-design/) 111 | -------------------------------------------------------------------------------- /【个人总结】正则表达式语法及常用正则.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 【个人总结】正则表达式语法及常用正则 3 | date: 2016-06-07 18:13:05 4 | categories: 工具资源 5 | tags: [工具资源,JavaScript] 6 | --- 7 | 项目中常用正则表达式来进行校验,然而确实总是遗忘一些相关的语法,需要谷歌搜索一些不太好想或写的正则规则。所以在此总结一份。争取依靠个人总结不断更新这篇日志,节约之后 90% 的查阅搜索时间。 8 | 9 | ## 概述 10 | 正则表达式就是事先声明一组规则,用于匹配字符串中的字符。 11 | ## 基本语法 12 | ### 修饰符 13 | |修饰符 | 描述 | 14 | |:-----: | :----: | 15 | |i | 执行对大小写不敏感的匹配。| 16 | |g | 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。 | 17 | |m | 执行多行匹配。 | 18 | ### 元字符 19 | 在正则表达式的模式中,有一些字符是有特殊含义的,被称为元字符。元字符都是针对单个字符匹配的。 20 | 21 | |元字符 | 描述 | 22 | |:-----: | :----: | 23 | |. | 查找单个字符,除了换行和行结束符。| 24 | |\w | 匹配大小写英文字符及数字 0 到 9 之间的任意一个及下划线,相当于 [a-zA-Z0-9_] | 25 | |\W | 不匹配大小写英文字符及数字 0 到 9 之间的任意一个,相当于 [^a-zA-Z0-9_] | 26 | |\s | 匹配任何空白字符,相当于 [\f\n\r\t\v] | 27 | |\S | 匹配任何非空白字符,相当于 [^\s] | 28 | |\d | 匹配任何 0 到 9 之间的单个数字,相当于 [0-9] | 29 | |\D | 不匹配任何 0 到 9 之间的单个数字,相当于 [^0-9] | 30 | |\b | 匹配单词边界。 | 31 | |\B | 匹配非单词边界。 | 32 | |\0 | 查找 NUL 字符。 | 33 | |\n | 查找换行符。 | 34 | |\f | 查找换页符。 | 35 | |\r | 查找回车符。 | 36 | |\t | 查找制表符。 | 37 | |\v | 查找垂直制表符。| 38 | |\xxx | 查找以八进制数 xxx 规定的字符。| 39 | |\xdd | 查找以十六进制数 dd 规定的字符。| 40 | |[\u4e00-\u9fa5] | 匹配任意单个汉字(这里用的是 Unicode 编码表示汉字的 ) | 41 | |^ | 匹配字符串的开头| 42 | |$ | 匹配字符串的结尾| 43 | 44 | ### 方括号 45 | 方括号用于查找某个范围内的字符 46 | | 表达式 | 描述 | 47 | |:-----: | :----: | 48 | |[...] | 匹配方括号中的所有字符| 49 | |[^...] | 匹配非方括号中的所有字符| 50 | 51 | ### 量词 52 | 53 | | 表达式 | 描述 | 54 | |:-----: | :----: | 55 | |n* | 匹配任何包含零个或多个 n 的字符串。| 56 | |n+ | 匹配任何包含至少一个 n 的字符串。| 57 | |n? | 匹配任何包含零个或一个 n 的字符串。| 58 | |n{X} | 匹配包含 X 个 n 的序列的字符串。| 59 | |n{X,Y} | 匹配包含 X 或 Y 个 n 的序列的字符串。| 60 | |n{X,} | 匹配包含至少 X 个 n 的序列的字符串。| 61 | |n$ | 匹配任何结尾为 n 的字符串。| 62 | |^n | 匹配任何开头为 n 的字符串。 | 63 | |?=n | 匹配任何其后紧接指定字符串 n 的字符串。| 64 | |?!n | 匹配任何其后没有紧接指定字符串 n 的字符串。| 65 | 66 | ### 断言 67 | 68 | | 表达式 | 描述 | 69 | |:-----: | :----: | 70 | |(exp) | 匹配 exp,并捕获文本到自动命名的组里| 71 | |(?exp)| 匹配 exp,并捕获文本到名称为 name 的组里,也可以写成(?'name'exp)| 72 | |(?:exp) | 匹配 exp,不捕获匹配的文本,也不给此分组分配组号| 73 | |(?=exp) | 正向先行断言——代表字符串中的一个位置,紧接该位置之后的字符序列能够匹配 exp。| 74 | |(?!exp)| 负向先行断言——代表字符串中的一个位置,紧接该位置之后的字符序列不能匹配 exp| 75 | |(?<=exp) | 正向后行断言,代表字符串中的一个位置,紧接该位置之前的字符序列能够匹配 exp。| 76 | |(?]*>.*?|<.*? />` (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力) 187 | 188 | - 首尾空白字符的正则表达式:`^\s*|\s*$或(^\s*)|(\s*$)` (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式) 189 | 190 | - 校验金额(2位小数): `^[0-9]+(.[0-9]{2})?$` 191 | 192 | - 腾讯 QQ 号:`[1-9][0-9]{4,}` (腾讯 QQ 号从 10000 开始) 193 | 194 | - 中国邮政编码:`[1-9]\d{5}(?!\d)` (中国邮政编码为 6 位数字) 195 | 196 | - IP 地址:`\d+\.\d+\.\d+\.\d+` (提取IP地址时有用) 197 | 198 | - IP 地址:`((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))` 199 | 200 | - IPV6 地址: `(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))` 201 | 202 | - URL 链接: `((http|ftp|https)://)(([a-zA-Z0-9\._-]+\.[a-zA-Z]{2,6})|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,4})*(/[a-zA-Z0-9\&%_\./-~-]*)?` 203 | 204 | - EMOJI 表情: `([\uE000-\uF8FF]|\uD83C[\uDF00-\uDFFF]|\uD83D[\uDC00-\uDDFF])` 205 | 206 | - 检查 IE 版本 `^.*MSIE [5-8](?:\\.[0-9]+)?(?!.*Trident\\/[5-9]\\.0).*$` 207 | 208 | 209 | ## 参考资料 210 | 这里的一篇图灵文章可以帮助你了解正则表达式的更深层原理:[模式、自动机和正则表达式](http://www.ituring.com.cn/tupubarticle/5512) 211 | 212 | 213 | 214 | -------------------------------------------------------------------------------- /【原创翻译】有哪些信号能让我知道我在一家『没落的』公司工作.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 【原创翻译】有哪些信号能让我知道我在一家『没落的』公司工作 3 | date: 2016-01-11 10:37:26 4 | categories: 职业生涯 5 | tags: [职业生涯,原创翻译] 6 | --- 7 | 文章来自 Quora 的同名问题及 Michael Wolfe 的[回答](https://www.quora.com/What-are-telltale-signs-that-youre-working-at-a-sinking-ship-company),我接触于[扇贝读书](http://www.shanbay.com/read/article/reviews/7330/) 8 | 9 | # What are telltale signs that you're working at a "sinking ship" company? 10 | 11 | > 有哪些迹象表明你正在一家【没落的】公司工作 12 | 13 | Answered by Michael Wolfe, Five startups and counting. 14 | 15 | > 回答来自Michael Wolfe ,有五次创业经历。 16 | 17 | ## Large Company Edition 18 | - New opportunities are framed in terms of how they impact the existing legacy businesses, not how they impact the customer and the future. 19 | - Mediocre employees are not fired since you can't recruit better ones anyway. 20 | - You benchmark against your direct (mediocre) peers instead of the disruptive entrants in your market. Your co-workers roll their eyes at Facebook, Twitter, cloud services, iPhones, about how they are for children and your customers will never trust their business to them. 21 | - You spend more time talking about how you are going to make the quarter than you do about long-term growth. 22 | - Cross-functional committees are formed to solve problems that would have been solved already if the people responsible for them were any good. 23 | - Management consultants are brought in to solve problems that would have been solved already if the people responsible for them were any good. 24 | - All problems can be solved with more budget (not better people or better decisions). 25 | - Acquired companies disintegrate after they regress to the mean of the rest of the company. 26 | - The CFO spends 95% of his time looking for places to spend less money and 5% looking for new investment opportunities. 27 | - The HR department thinks their job is administration, not leadership. 28 | - All technology decisions go through a centralized IT bottleneck steering committee. 29 | - IT sends out a memo that says anyone using unauthorized cloud services will be fired. 30 | - You have a Chief Strategy Officer. 31 | - You don't have a recruiting playbook. 32 | - People argue over offices. 33 | - When risky, innovative projects are cancelled, the people working on them are laid off, thus getting richly punished for their risk-taking. 34 | - Spending and hiring decisions are "approved" by an entity outside of your group, even if they are within existing budget. 35 | - The company shuts down over the holidays just to get vacation off of the books. 36 | - No one can answer, "why work here?" except to talk about the dental plan. 37 | - Executives are shuffled around the company to new roles, but outsiders don't ever seem to be brought in to raise the bar. 38 | - When an exec quits, their next in line is automatically promoted to their bosses' job, even if they weren't that great and there would have been better candidateselsewhere. 39 | - Each employee has a rationale for why, "I'm glad I don't have to work at Facebook/Twitter/Goldman." 40 | 41 | > ## 大公司版本 42 | > - 在面临新机遇时首先考虑对现有的遗留业务会造成什么影响,而不是考虑新机遇对客户和未来的影响。 43 | > - 平庸的员工不会被解雇,反正也雇不到更好的员工。 44 | > - 你在工作中总是在与你那些平庸的同事对抗,而不是与试图颠覆市场的公司对抗。你的同事总是关注『Facebook』、『Twitter』、『云服务』、『iPhone』以及他们的孩子,以至于你的客户永远不会放心的将业务交给你们公司。 45 | > - 你总是花更多的时间来说这季度该如何做,而不是为了公司的长远发展去行动。 46 | > - 对于那些由于人为不负责所导致的问题,公司专门设立了跨职能委员会来解决,其实让员工自己负起责任来会更有用。 47 | > - 公司还引进管理顾问来解决问题,而这些问题只要员工负责就不会产生。 48 | > - 所有的问题都可以用投入更多的预算来解决(而不是更好的人或者更好的决策)。 49 | > - 被收购的子公司的业绩倒退到总公司的平均收益以下后会被瓦解掉。 50 | > - 财务总监将他95%的时间用于找地方花更少的钱,只有5%的时间在寻找新的投资机会。 51 | > - 人力资源部认为他们的工作是管理工作,而不是领导工作。 52 | > - 所有的技术决策都要经过一个带有中央集权性质的,并且IT经验不足的指导委员会。 53 | > - IT部门发通知说:使用了未经授权的云服务的人将被解雇。 54 | > - 你有一个首席战略官。 55 | > - 你们没有招募计划。 56 | > - 办公室充满了争吵。 57 | > - 当有风险的,创新性的项目被取消后,从事这个项目工作的人都被解雇,因为需要对他们的冒险进行惩罚。 58 | > - 你们小组的支出和招聘计划是由一个你们小组之外的部门决定的,即使这些计划不超过现有的预算。 59 | > - 公司在节日期间关闭的目的只是为了让大家在假期不看书。 60 | > - 除了牙科保险,没有人能回答上来在这个公司工作的原因。 61 | > - 新的高管总是试图围绕公司进行改组,但由于还并不了解具体的项目所以改组并没有真正的提高效率。 62 | > - 当一个高管辞职后,位于他下面一级的人会自动升级做他的工作,即使这些人并不怎么样,或者即使其他地方有更合适的人选。 63 | > - 每个员工都有一个这样的工作的理由:“我很高兴我没有在Facebook//Twitter/Goldman工作”。 64 | 65 | ## Small Company Edition 66 | - You "rehearse" for board meetings. 67 | - When pressured on the business by employees, CEO always starts with, "I need you to stay focused on..." 68 | - You have more than one MBA on the team. 69 | - You have a Chief Strategy Officer. 70 | - Your CTO just came out of a Phd program. 71 | - Your CEO sells instead of listens. 72 | - You have a launch party, and no customers attend. 73 | - Customers hate the product and vision, so the sales guy is fired. 74 | - You are not told the terms of the last funding round (5x liquidation preference?) 75 | - You never hear how much cash you have in the bank or see board meeting notes. 76 | - You complain about how the customers "just don't get it" and aren't "visionary." 77 | - Your CEO says revenue is coming in in two weeks, just after he gets a meeting with the buyer, negotiates price, gets it approved, agrees on terms, writes up up contracts, negotiates them, signs them, and invoices the customer on net 30 terms. 78 | - You add features because board members want them. 79 | - Your CEO calls himself a "visionary" in his bio. 80 | - The CEO keeps everything secret because, "that is how Apple does it." 81 | - The CEO approves all of the design decisions because, "that is how Apple does it." 82 | - You are selling a platform. 83 | - Co-founder agrees to bring in experienced execs but thinks they will report to him. 84 | - You are selling to schools, hospitals, or non-profits. 85 | - You are commercializing a technology. 86 | - Your value proposition is that you help workers break down organizational barriers and work cross-functionally. 87 | - Your business model assume you will become one of the 7 websites that the average user visits every day. 88 | - Your site is going to be ad-supported, and you have 1500 users. 89 | - CEO avoids eye contact. 90 | - It gets really quiet. 91 | - You get free lunch but have no customers. 92 | - Your free lunch is taken away. 93 | - You get asked, "how much do you really need to live on?" 94 | - You get a pay cut. 95 | - Your co-worker disappears. 96 | - Your CEO still doesn't make eye contact. 97 | - You get laid off and become a creditor to the company because they didn't reimburse your last 5 expense reports. 98 | - The company declines to buy your unvested shares back. 99 | - The liquidation yields 5 Aeron chairs and an espresso machine, and Ashton Kutcher's stock is senior to yours. 100 | 101 | > ## 小公司版本 102 | > - 你为董事会会议不断排练。 103 | > - 当员工的行为使公司的业务压力增大时,CEO总是说到,“我需要你专心投入......” 104 | > - 在你的队伍里有一个以上的MBA成员 105 | > - 你有一个首席战略官。 106 | > - 您的CTO刚刚博士学位毕业。 107 | > - 你的CEO总是在推销而不是倾听。 108 | > - 你有一个发布会,但并没有客户参加。 109 | > - 客户讨厌产品和UI展示,所以销售被炒了。 110 | > - 你没有被告诉最后一轮的融资条款细则(有5X清算优先权?) 111 | > - 你从来没有听说过你银行账户里有多少钱或阅读到过董事会会议记录。 112 | > - 你抱怨客户“为什么总是不明白这一点”,而不是“富有远见”。 113 | > - 你的CEO称公司将在两周内开始营收,只要他和买家会面,协商完价格,获得了核准,同意了条款,撰写完合同,讨论了具体细则,签署了合同,并开具含有30个条款的发票就可以了。 114 | > - 你为产品增加了新的功能是因为董事会成员需要他们。 115 | > - 你的CEO自称他是“有远见”的。 116 | > - 你的CEO把每件事都当做秘密来处理,并说“因为苹果公司就是这么做的。” 117 | > - 你的CEO批准了所有的设计决策,并说“因为苹果公司就是这么做的。” 118 | > - 你在销售一个平台。 119 | > - 联合创始人同意引进有经验的高管,却认为他们需要向他汇报。 120 | > - 你在向学校,医院,以及非营利性组织销售产品。 121 | > - 你在将技术商业化处理。 122 | > - 你的价值主张是你来帮助工人打破编制障碍来跨职能进行工作。 123 | > - 你的商业模式假定为将成为普通用户每天访问的7个网站中的一个。 124 | > - 您的网站将要开始投放广告,但你只有1500个用户。 125 | > - CEO总是避免眼神接触。 126 | > - 公司逐渐变得很安静。 127 | > - 你得到了免费的午餐,但开始没有客户。 128 | > - 你免费的午餐权利也被剥削了。 129 | > - 你被问到,“究竟你需要多少薪水来生活呢?” 130 | > - 你被降薪。 131 | > - 你的同事开始逐渐消失。 132 | > - 你的CEO仍然没有眼神接触。 133 | > - 你被解雇而成为公司的债权人,因为他们没有偿还你的最后5次开支报告。 134 | > - 公司拒绝购买你拥有的股权协议。 135 | > - 清算收益后你只有第5代Aeron椅子和一台咖啡机,以及Ashton Kutcher的股票比你更多的消息。 136 | 137 | -------------------------------------------------------------------------------- /npm left-pad模块删除事件始末梳理及看法及应对依赖风险处理方法.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: npm left-pad模块删除事件始末梳理及看法及应对依赖风险处理方法 3 | date: 2016-03-24 11:37:26 4 | categories: npm 5 | tags: [npm,模块化] 6 | --- 7 | ## 事件起因 8 | 事件原因是在23日凌晨,一个开发者因为对 NPM 不满,unpublish 了自己的所有模块。其中包括被广泛使用的`left-pad`,导致`Babel`、`ReactNative`、`Ember`等大量工具构建失败。 9 | 10 | [left-pad](https://www.npmjs.com/package/left-pad) 是一个依赖度非常高的仓库,根据 NPM 的统计显示,`left-pad`在23日统计显示昨日的下载量是 10 万,上周的下载量为 57 万,上个月下载量达到了 255 万。 11 | 12 | 之后 `left-pad` 作者 Azer 在 Medium 发布了一篇文章来阐述他删除自己模块的原因 13 | [I’ve Just Liberated My Modules](https://medium.com/@azerbike/i-ve-just-liberated-my-modules-9045c06be67c#.7unu9xvjk) 14 | 15 | 这里参考 justjavac 提供的[翻译文章](http://mp.weixin.qq.com/s?__biz=MzI0NTAyNjE0NQ==&mid=427175657&idx=1&sn=57c0cda917797198df18552f7d8f4eca&scene=0#wechat_redirect)如下: 16 | > 作者在《I've Just Liberated My Modules》文章中写道: 17 | 18 | >几个星期前有位专利律师给我发了一封电子邮件,要求我取消发布 NPM 上的 “KIK” 模块。我的回答是“不”,于是他回复我说:“I don’t wanna be dick about it(这句就不翻译了,你只需要知道 dick 是什么意思就够了),但 “KIK” 是我们的注册品牌,并且我们的律师遍布世界各地。” 19 | 20 | >当我开始编写 kik 时,并不知道有同名的公司。而我也不希望因为这个公司而被迫改变项目的名字。在遭到了我的拒绝后,他们联系了 NPM 的技术支持,为了强调他们的律师权力,每一个电子邮件都抄送给了我。在未经我允许的情况下,@izs 更改了此模块的所有权。 21 | 22 | >鉴于此我才意识到,NPM 是某个人的私有地盘,他比其他人有更多的控制权,但是我是做开源的,因为权力属于人民。(Power To The People 是约翰·列侬的同名歌曲) 23 | 24 | >概述一下就是; NPM 不再是我分享开源工作的地方,所以,我取消了曾经发布的所有模块。(一共取消了 273 个) 25 | 26 | >这不是一个下意识的行为。我喜欢开源,相信开源社区将最终创造一个真正自由的 NPM。 27 | 28 | >如果你的项目因此而构建失败,我向你道歉。你可以在仓库(azer/dependency)指出你的依赖,或者如果你自愿参加我的 Github 上的任何模块,我会高兴地转移所有权。 29 | 30 | >干杯,再见。 31 | 32 | ## npm 模块依赖的生态环境 33 | 之后有人对 [left-pad 源码](https://github.com/azer/left-pad)进行查看,惊讶的发现其源码仅有 11 行: 34 | 35 | ``` js 36 | module.exports = leftpad; 37 | function leftpad (str, len, ch) { 38 | str = String(str); 39 | var i = -1; 40 | if (!ch && ch !== 0) ch = ' '; 41 | len = len - str.length; 42 | while (++i < len) { 43 | str = ch + str; 44 | } 45 | return str; 46 | } 47 | ``` 48 | 于是一部分的人产生了疑问:**为什么这么短的代码,也能成为众多库比如 RN 的依赖?** 49 | 50 | 之后 Haney 的一篇博文对类似这样的模块进行了更多的搜索,发现了相当多类似 `left-pad` 这样的模块。提出了疑问:我们都忘记了怎样去写程序了吗?原文在此 [NPM & left-pad: Have We Forgotten How To Program?](http://www.haneycodes.net/npm-left-pad-have-we-forgotten-how-to-program/) 51 | 这里简单翻译一下他列举的事实给大家: 52 | >好的开发者们,接下来是一个比较严肃的讨论。正如你们可能已经知道的那样,这一周里 `babel`,`react` 以及类似一大堆高依赖的模块在 npm 无法被成功构建。他们宕机的原因是相当惊人的。 53 | 54 | >因为他们共同依赖了一个简单的 NPM 包 `left-pad`,它的目的是实现左填充一个字符串,他的源码也总共只有 11 行。 55 | 令人担心的是这里有这么多包选择去依赖一个这样简单的函数,而不是采取几分钟去写一个这样的基本功能。 56 | 57 | >由于这次灾难,我开始调查整个 NPM 的生态系统。这里果然有一些类似的事情: 58 | 59 | >- 有一个叫 [IsArray](https://www.npmjs.com/package/isarray) 的包,每天达到 88 万的下载量,而它的源代码仅有一行: 60 | 61 | >``` js 62 | return toString.call(arr) == '[object Array]'; 63 | ``` 64 | > - 有一个判断是否为正数的函数 [is-positive-integer](https://www.npmjs.com/package/is-positive-integer),源代码只有 4 行,截至昨日仍然有 3 个项目依赖使用。后来作者重构了它依赖才变为 0 65 | > - 一个全新安装的 babel 包,包含了 41000 个文件 66 | > - 一个空白的 jspm/npm-based 应用模板起始就包含了 28000 个文件 67 | >**这些都让我感到相当惊讶。难道我们都忘记了怎样编程了吗?** 68 | 69 | ## 看法 70 | 这次的危机算是一个潜在问题的大爆发,的确现在模块依赖是大势所趋,如果大量的基础函数可以通过外部依赖解决,那么自己的程序的代码行数就可以减少很多,程序员便可以专注于写一些新的不同的东西。这种思想肯定是没有问题的。 71 | 而类似 Haney 所列举的这些简单依赖包能够产生的原因正是因为标准函数库存在不足。让任何人都必须在最开始得亲手写一个左填充字符串函数也是十分荒谬的。 72 | 另外,其实 npm 对于解决这种包名纠纷也是有很明确的规则 [npm-disputes](https://docs.npmjs.com/misc/disputes)。我觉得其实 NPM 官方的处理也不能说有太大的问题。 73 | 74 | 类似这样的事件我认为最需要解决的两件事是: 75 | 76 | - 语言应该能够提供一个足够健壮并且充分的标准库函数,这是解决这样的问题的一个重要关键。 77 | - 出现这种问题的原因也一部分在于 NPM 目前没有应对这种问题的机制,NPM 应该尽快补充类似这种危机的处理手段,如尝试修改 unpublish 包的规则、依赖项目如果缺失尝试寻找更多的替代品,防范其他人伪造同名库等。 78 | 79 | ## 后续 80 | 81 | npm 今日在[官方宣布](http://blog.npmjs.org/post/141577284765/kik-left-pad-and-npm),由于昨天的事件,今后将严格限制 unpublish 命令。并且,不再允许自由认领已经废弃的模块,必须向 npm 官方提出申请。 82 | 83 | 84 | ## 经验教训([参考](https://segmentfault.com/a/1190000004700432)) 85 | 86 | ### 不要太依赖他人 87 | 如果我们想构建稳定的应用,非常重要的一点就是“不要将自己的全部身家都拴在别人的裤腰带”上,你永远不知道那个别人什么时候会“扑街”。其实在代码实现中,我们一直都被教导要小心强依赖,依赖过强会导致我们不够灵动。“牵一发而动全身”是很可怕的一件事。 88 | 89 | 具体到 Node 模块的依赖这件事上,太依赖他人会有些什么“可怕”的事情? 90 | 91 | - 模块全部要从 NPM 的 registry 拉取然后安装,每天的持续集成越来越慢、越来越慢。 92 | - 像 left-pad 这个模块一样,你依赖的模块被作者怒删了,应用挂掉。 93 | - 你在 package.json 里面指定依赖时使用了 `~a.b.c` 这种表示法(意思是小版本我都要),这表示每次 npm install 时其实获取到的模块依赖很可能是和你测试后发布的版本不一致的(模块发布了新的小版本),心里慌慌的。 94 | - 你依赖模块的作者是个傻逼,不小心将不兼容的改动当作小版本发布了一个新版。npm install 或者 npm update 以后你依赖了这个新版,应用挂掉了。 95 | *注:对 3、4 有疑问的可以查看:[深入 Node 模块的安装和发布](https://segmentfault.com/a/1190000004221514)* 96 | 97 | ### 破解强依赖 98 | 99 | 先来列出我们需要些什么: 100 | 101 | - 在发布前“冻结”依赖模块的版本号。这让我们对安装的依赖有信心,依赖模块的版本都是我们验证、测试过的。 102 | - 在发布前“打包”依赖模块到自己项目。这让我们可以坦然面对我们依赖的某个模块“没有了”这样的囧境。 103 | 104 | ### 冻结依赖模块 105 | 冻结依赖模块的版本号最简单的办法就是直接在`package.json`里面写死版本号,但是这解决不了深度依赖的问题。我们来看个例子。 106 | 107 | 假设有下面这样的依赖: 108 | 109 | ``` bash 110 | A@0.1.0 111 | |—B@0.0.1 112 | |—C@0.0.1 113 | ``` 114 | A 模块依赖了 B 模块,B 模块又依赖了 C 模块。我们可以将 B 模块的依赖写死成 `0.0.1` 版本,但是如果 B 模块对 C 模块的依赖写的是 `C: ~0.0.1`,会怎样? 115 | 116 | 这时候 C 模块更新到了 0.0.2 版本,虽然我们安装的 B 模块是 `B@0.0.1`,但是安装的 C 模块却是 `C@0.0.2`。如果不巧这个`C@0.0.2` 刚好有 bug,那我们的模块很有可能就不能正常工作了。 117 | 118 | 实际上,NPM 提供了一个叫做 `npm shrinkwrap` 的命令来我们解决这个问题: 119 | 120 | ``` doc 121 | NAME 122 | npm-shrinkwrap -- Lock down dependency versions 123 | 124 | SYNOPSIS 125 | npm shrinkwrap 126 | 127 | DESCRIPTION 128 | This command locks down the versions of a package's dependencies so that you can control exactly which versions of each dependency will be used when your package is installed. 129 | ``` 130 | 这条命令会根据目前我们 `node_modules` 目录下的模块来生成一份“冻结”住的模块依赖(npm-shrinkwrap.json)。 131 | 132 | 还是上面的例子,我们在模块 A 的根目录执行 `npm shrinkwrap` 后,生成的 `npm-shrinkwrap.json` 文件内容大概是下面这样: 133 | 134 | ``` json 135 | { 136 | "name": "A", 137 | "dependencies": { 138 | "B": { 139 | "version": "0.0.1", 140 | "resolved": "http://registry.npmjs.com/B-0.0.1.tgz", 141 | "dependencies": { 142 | "C": { 143 | "version": "0.0.1", 144 | "resolved": "http://registry.npmjs.com/C-0.0.1.tgz" 145 | } 146 | } 147 | } 148 | } 149 | } 150 | ``` 151 | 然后,当我们执行 `npm install` 时,依赖查找的“来源”不再是 `package.json`,而是我们生成的 `npm-shrinkwrap.json`,再也不会突然装上什么 `C@0.0.2` 了,依赖里面的模块版本都是我们验证、测试后的版本,让人安心。 152 | 153 | 注:`npm shrinkwrap` 默认只会生成 `dependencies` 的依赖,不会生成 `devDependencies` 的依赖,如果你真的需要,可以加 `--dev` 参数。 154 | ### 打包依赖模块 155 | 我们解决了依赖模块版本号的问题,但是每次安装时其实还是会去 NPM 的 registry 获取模块的 tgz 包然后进行安装。我们需要将这些依赖都打包进我们的项目。这可能会带来一些问题(比如:项目体积的增大),但是好处也是显而易见的。 156 | 157 | 上面生成的 `npm-shrinkwrap.json` 里面有个 `resolved` 字段,表示模块所在的位置,实际上这个字段完全可以写一个文件路径。所以,我们可以递归的遍历 `npm-shrinkwrap.json` 文件,将所有的 tgz 包先下载到我们项目的某个目录,然后改写 `resolved` 字段为对应的文件路径。这样的功能有开发者已经实现了,我们可以直接[享用](https://github.com/JamieMason/shrinkpack) 158 | 159 | 还是上面的例子: 160 | 161 | ``` bash 162 | A@0.1.0 163 | |—B@0.0.1 164 | |—C@0.0.1 165 | ``` 166 | 执行 `shrinkpack` 后,会生成下面的打包目录: 167 | 168 | ``` bash 169 | node_shrinkpack 170 | - B-0.0.1.tgz 171 | - C-0.0.1.tgz 172 | ``` 173 | 和 node-shrinkwrap.json 文件: 174 | 175 | ``` json 176 | { 177 | "name": "A", 178 | "dependencies": { 179 | "B": { 180 | "version": "0.0.1", 181 | "resolved": "./node_shrinkpack/B-0.0.1.tgz", 182 | "dependencies": { 183 | "C": { 184 | "version": "0.0.1", 185 | "resolved": "./node_shrinkpack/C-0.0.1.tgz" 186 | } 187 | } 188 | } 189 | } 190 | } 191 | ``` 192 | 于是,我们以后再进行 `npm install --loglevel=http` 时会发现依赖模块的获取根本没有网络请求了(因为依赖都在我们自己的仓库里了嘛)。 193 | 194 | 可能有人会说,为啥不直接把 node_modules 目录提交进仓库算了?原因主要是这样: 195 | 196 | 有些模块需要编译,编译是和环境有关的,你当前的环境编译可用,其他环境直接使用该模块不一定能用。 197 | `node_modules` 目录里面啥东西都有,太凌乱,很容易把提交给搅乱。diff 时突然 diff 出 `node_modules` 下的源代码、README,你应该不想这样吧? 198 | 只存储模块的 tgz 包,安装编译的过程交给 NPM 命令更明智。 199 | 200 | ### 新方式 201 | 于是,现在我们使用 NPM 模块的正确姿势应该是这样了: 202 | 203 | 本地安装、更新需要的模块,测试、验证 204 | 执行 `npm shrinkwrap` 将依赖模块的版本冻结 205 | 执行 `shrinkpack` . 将依赖模块打包进仓库 206 | 提交代码(注意要将 `npm-shrinkwrap.json` 和 `node_shrinkpack` 一起提交哦) 207 | 发布模块或者部署应用 208 | 如果你觉得这样很繁琐,可以定义一个 NPM 命令: 209 | 210 | ``` json 211 | "scripts": { 212 | "pack": "npm shrinkwrap & shrinkpack ." 213 | } 214 | ``` 215 | ### 总结 216 | 拆分模块是必要的,我们应该坚持模块“小而美” 217 | 不要太依赖他人,一定要有依赖方挂掉的应急方案 218 | 推荐使用 `npm shrinkwrap`(冻结依赖模块的版本) 加 `shrinkpack`(打包依赖模块到自己项目) 来解决依赖模块的不确定性 219 | -------------------------------------------------------------------------------- /Git日常使用提交信息参考规范及总结梳理.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Git日常使用提交信息参考规范及总结梳理 3 | date: 2016-01-14 10:46:11 4 | categories: Git 5 | tags: [Git] 6 | --- 7 | 8 | 本篇大多数内容参考自阮一峰博文 [Commit message 和 Change log 编写指南](http://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html) 9 | 并总结了 Git 的一些命令来协助各位程序员们可以在年终时依靠Git总结代码提交的方法。 10 | 11 | ## Commit message 和 Change log 编写指南(转载内容) 12 | 作者: [阮一峰](http://www.ruanyifeng.com) 13 | 日期: [2016年1月 6日](http://www.ruanyifeng.com/blog/2016/01/) 14 | Git 每次提交代码,都要写 Commit message(提交说明),否则就不允许提交。 15 | 16 | ``` bash 17 | $ git commit -m "hello world" 18 | ``` 19 | 20 | 上面代码的 `-m` 参数,就是用来指定 commit message 的。 21 | 如果一行不够,可以只执行 `git commit`,就会跳出文本编辑器,让你写多行。 22 | 23 | ``` bash 24 | $ git commit 25 | ``` 26 | 但是,一般来说,commit message 应该清晰明了,说明本次提交的目的。 27 | ![commit-message-example](http://qcyoung.qiniudn.com/qcyoung/Git日常使用提交信息参考规范及总结梳理/commit-message-example.png) 28 | 29 | 目前,社区有多种 Commit message 的[写法规范](https://github.com/ajoslin/conventional-changelog/tree/master/conventions)。本文介绍 [Angular 规范](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#heading=h.greljkmo14y0)(如上图),这是目前使用最广的写法,比较合理和系统化,并且有配套的工具。 30 | 31 | ### 一、Commit message 的作用 32 | 格式化的 Commit message,有几个好处。 33 | 34 | #### (1)提供更多的历史信息,方便快速浏览。 35 | 比如,下面的命令显示上次发布后的变动,每个 commit 占据一行。你只看行首,就知道某次 commit 的目的。 36 | 37 | ``` bash 38 | $ git log HEAD --pretty=format:%s 39 | ``` 40 | ![git-log-pretty](http://qcyoung.qiniudn.com/qcyoung/Git日常使用提交信息参考规范及总结梳理/git-log-pretty.png) 41 | #### (2)可以过滤某些 commit(比如文档改动),便于快速查找信息。 42 | 比如,下面的命令仅仅显示本次发布新增加的功能。 43 | 44 | ``` bash 45 | $ git log HEAD --grep feature 46 | ``` 47 | #### (3)可以直接从 commit 生成 Change log。 48 | Change Log 是发布新版本时,用来说明与上一个版本差异的文档,详见后文。 49 | ![git-change-log-example](http://qcyoung.qiniudn.com/qcyoung/Git日常使用提交信息参考规范及总结梳理/git-change-log-example.png) 50 | ### 二、Commit message 的格式 51 | 每次提交,Commit message 都包括三个部分:Header,Body 和 Footer。 52 | 53 | ``` html 54 | (): 55 | // 空一行 56 | 57 | // 空一行 58 |