使用XtraFinder增强OS X的finder

XtraFinder

国庆后的周末只有一天,很多事情都赶到了一起,这次的文章就从简了,介绍一款OS X的finder增强工具XtraFinder

介绍页比较简单,安装后的偏好设置也基本上看几眼就明白(而且大部分是中文的)。更推荐使用homebrew cask安装,执行sudo brew cask install xtrafinder即可(需root权限)。运行后会出现在顶部工具栏上(logo跟finder一致),所有功能在其偏好设置内开启/关闭。

介绍几个个人觉得比较实(zhuang)用(bi)的功能:

  1. 首当其冲的便是高大上的彩色侧边栏图标:
    真的是为finder增『色』不少~开关在『Appearance』 -> 『显示彩色侧栏图标』
  2. tab功能,自OS X 10.9后已经支持
  3. 不少人对于OS X不支持像windows那样的CTRL + X / CTRL + V剪切功能而烦恼(其实剪切可以通过 ⌘+C / ⌘ + ⎇ + V 实现),现在你可以通过XtraFinder实现,位于『特性』 -> 『剪切和粘贴』
  4. 获取文件(夹)的路径一直是OS X的痛点,通过XtraFinder有两种方式可以获取:
    a) 勾选 『将项目添加到Finder菜单中』-> 『拷贝路径』,然后在你想要获取路径的文件(夹)上右键,就可以看到多了一项『拷贝路径』:
    直接点击『拷贝路径』默认就是拷贝了路径到剪贴板。
    b) 在a的基础上,勾选 『特性』 -> 『在工具栏中添加XtraFinder的功能』,然后回到finder,在工具栏右键选择『自定义工具栏…』,将『拷贝路径功能拖上去』:

    然后,选择需要获取路径的文件(夹),再点击工具栏上那个按钮即可将该路径复制到粘贴板了
  5. 在OS X中新建文件也是一个痛点,在上面的截图中,我另外把『New File』框出来了,和『拷贝路径』同理,前提要勾选 『将项目添加到Finder菜单中』-> 『新建文件』,可自定义添加别的类型文件:

     

还有一些finder实用功能它自身就有提供,比如『显示』-> 『显示路径栏』,『显示状态栏』等。

之所以会写这篇文章,是因为国庆期间更新了 OS X 10.11,导致了XtraFinder不可用了,Google了一下,跟系统的debug模式有关,参见 这篇文章。根据文章上说,将系统debug关闭,再重启,XtraFinder果然可以启动了,不过似乎有些功能失效了,比如『自动调节宽度』,等待开发者团队修复这些问题吧。

DIY利用NodeJS生成团队工作汇总表

这个想法源自最初基于Excel | Numbers二进制文件繁琐的记录过程。不得否认,Excel | Numbers功能很强大,可以绘制出非常完美的表格。

我们之前的做法是,表头制作好以后,由多人合作将此文件中的表格填充完整。关键是,我们通过QQ等工具以文件发送的形式合作完成这份表格,只能以『一人填写完再转给下一个人』的方式保证文件内容不冲突,或者说是保证内容完整性,这样的统计效率很低。

然后,我思考,可不可以用版本控制来完成这件事呢?似乎可以,但有个大问题,它是二进制文件,版本控制工具无法对其做出精确的修改记录,也就无法自动合并内容。就好比图片,一旦冲突,只能选择一个保留,无法合并修改。

我再思考,markdown不也可以做表格吗,而且它是基于文本的,版本控制可以合并修改。但是,直接用markdown写表格,也蛮痛苦的,很不直观,各种参差不齐,处女座又要被逼死的节奏:

1
2
3
4
5
6
7
|Date|Week|Incident|李四|王五|赵六|张三|
|---|---|---|---|---|---|---|
|1|三||开始XXX项目|Animate.css||css|
|2|四||Grunt|Webpack||js|
|3|五||完成了XXX开发,完成了XXX评审|Gulp||html|
|4|六|公休日|||||
|5|日|公休日|||||

换做是html似乎会更多累赘,一坨td标签,不忍直视。这个时候,我突然想到有一个模板叫 jade,它就是提倡简洁语法的Node模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
table
tr
th Date
th Week
th Incident
th 李四
th 张三
tr
td 1
td 三
td
td CSS
td JAVASCRIPT

Oh,No! 我刚写到第2行就受不了了,还是要写标签就不说了,人和任务很难对应起来,这是什么鬼体验。。。

另外,以上方案共同的最大的问题是,日期、星期全部都要手动填写,这就坑爹了吧(使用Excel | Numbers也好不到哪去- -)。

于是,我想到了利用NodeJS帮我们做数据转换(包括日期星期的自动计算),再结合jade模板,生成html表格。那我们需要人工维护的数据在哪里呢?第一个想到的肯定是json文件,但忽然又想起半个月前玩codepen的时候,里面提到了HAML(和 jade是同路子的),我想起了另一种新兴的数据文件,叫做 YAML。早前并没有太关注它,再次google之,有篇文章提到了json作为配置文件的几个痛点,我此刻才『幡然醒悟』:

  1. json无法写注释
  2. 到处都是双引号
  3. 深层次的json结构,大括号与中括号有堆金字塔的感觉,剪不断,理还乱- -
    比起YAML的简洁性,json逊色很多。

于是乎,YAML搞起!YAML文件的扩展名为yml。

第一版的形式是,团队所有人维护同一个数据yml,数据结构大致是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
year: 2015 #年
month: 9 #月
incidents: null #事件节点
members: #团队成员
- name: '张三' #成员姓名
tasks: #当月任务列表
1: 'Angular' #{日期}:{做了什么事情}
2: 'React'
3: 'Ember'
- name: '李四'
tasks:
1: 'jQuery'
2: 'Moment'
3: 'Backbone'

再通过Node解析yml,生成js对象数据,结合jade模板生成html。

经过一个晚上的奋战,终于搞定了!

第二天,考虑到多人维护同一个yml还是有一些不方便,于是改进为,每人维护自己的yml,最后统一生成html。

第二版的形式是,在仓库中为每个月创建类似 『201509』这样的目录,团队每个成员往里面push自己的yml(比如ls.yml),格式为:

1
2
3
4
5
6
7
name: '李四'
tasks:
1: 'Angular'
2: 'React'
3: 'Ember'
6: 'Bootstrap'
8: '请假'

相当简洁,易于维护。

再由专人添加当月的事件yml(_incidents.yml),格式为:

1
2
3
4
1: 'outing'
5: '加班'
16: '发布'
30: '内测'

每个人每天都可以写这个文件,并可直接生成汇总文件预览。

在月末,执行node sum {年月}(e.g.201509)即可在相应目录下生成sum.html,再push到github或gitlab,方便大家查看。

后来,由于在github 或gitlab上无法方便的预览html,而markdown可以,同时又生成了sum.md,期间又是踩了许多坑。最终得到了现在的版本,见 https://github.com/stoneChen/task-summary

总结

这种方式让团队每个成员都参与进来,效率高了不少。

但还有许多不足的地方,比如表格无法合并单元格,无法在多个维度下统计等等,仅能非常轻量级地汇总。这个月打算在团队里试运行。

其实最好的统计方式,还是开发一个专门的web站点,不仅仅可以统计每个人的工作内容,还可以做更多的事情,不过这种方式有点重,要看公司的具体情况了。

CSS3实现圆环式百分比

早前尝试实现过实现一个缺口圆环loading,我们来回顾一下:

 

See the Pen XmNdVy by cloudstone (@cloudstone) on CodePen.


 

主要使用了CSS3的border-radius、transform:rotate、transform-origin,以及白色长矩形的遮挡。 前两天偶然又看到了一个百分比的圆环式表示法,好奇,研究之。用chrome开发者工具摆弄了一番,终于明白其原理,但还是觉得它的实现过于繁琐,自己重新实现了一番,这是jquery版:

 

See the Pen Mabyzq by cloudstone (@cloudstone) on CodePen.


 

再看Angular版:

 

See the Pen YypWvr by cloudstone (@cloudstone) on CodePen.


 

LESS是一样的,但js明显要简练的多。 而且,在实现jquery版本时,也花了更多时间去调试,由此可见,操作DOM需要维护更多的状态,稍有不慎就会造成疏漏。虽然angular的双向绑定很强大,在简单场景下会事半功倍,但是在复杂场景下,有时定位问题显得力不从心,需要对Angular框架本身非常精通才可准确定位问题。由此引申出React+Flux的思想精髓,单向数据流肯定是会简化问题的,虽然从代码量上可能会比双向绑定多一点,但从长久来看,它将更有利于团队的发展。

使用codepen分享前端代码

之前文章的demo演示,都是直接贴关键代码到文章里,然后再把完整的代码提交到 runjs.cn ,将演示地址拷贝到文章里,读者需要点击一个链接才能查看demo效果,似乎麻烦了一点点。想到平时google到的一些老外的博客,很多喜欢用codepen来分享,不需要跳转到新的页面就可查看代码和效果,遂今日研究之。
站点地址: http://codepen.io/,是一款高效在线IDE。当然在线IDE有很多,详见 https://zh.wikipedia.org/zh/%E5%9C%A8%E7%BA%BFIDE

Demo

令人惊喜的是,此站点是在墙内的,并且可免费使用其常用功能。目前我发现的一些特点有:

  1. 暗色基调界面,符合现代IDE的主色调,代码高亮和字体看着很舒服
  2. 可引入现成的很多CSS、Javascript开源类库/框架
  3. 支持Emmet,甚至代码检查
  4. 支持HTML、CSS、Javascript各种预处理器,我们只需写预处理的代码即可
  5. 自动保存,实时预览
  6. 提供跨平台测试的友情链接(我没测试成功囧)
  7. 可方便的分享代码给小伙伴,可以直接发送全屏演示的地址,或将代码嵌入到我们的博客中(这也是本文的重点啦)
    为了演示代码的嵌入,我随意写了个小demo,上个图:

写完demo后,点击左下角的 Embed 按钮,出现如下对话框:

可进行若干颜色的设置,默认已经挺不错了,然后点击右上角的文本框,复制它,粘贴到我们的文章源代码中就大功告成啦,效果如下:

See the Pen VvaJPX by cloudstone (@cloudstone) on CodePen.

 


嗯,不错!以后我的文章就用这种方式上demo啦。你也赶快试试吧!

 

题外话:

这个礼拜开始根据公司UI部门给出的新UI,对bootstrap进行二次开发,顺便开始尝试gulp的使用,确实速度比grunt快的多,网上看了一些文章,很多人都是从grunt转过来的,继续深入。ReactJS的调研学习可能要暂停一小段时间。

另一方面,向公司申请了一台Linux机器,开始尝试搭建gitLab(我们目前还在用SVN囧),但愿一切顺利,虽然从SVN迁移到Git估计还要很长一段时间,但不管怎么说,这件事情总要有人推动才能实现,即使慢一点也行,幸福的日子就要开始啦!

iOS浏览器中fixed元素失效问题

最近参与一个ios混合App的开发,是挺大的一块功能,而且设计上是与原生风格一致的,即看设计图感觉不到这是网页。为了方便流程控制,就把整个屏幕区域交给了H5,H5有自己的标题栏,而且是fixed的,到这里还没有大问题,当fixed元素遇到文本框,问题就来了。

上一个Angular的 demo ,请用iphone查看,先往上滚屏,标题栏固定在顶部,没有问题。现在点击某个文本框,虚拟键盘弹出,这里滚动页面,发现标题栏定位已经失效了!无论是ios Safari(情况可能会好一些)或UIWebView,都有这个问题,来个截图:

223F185918DAAD9518B5E10740E194CC

经过一番google,查到这是Apple的一个设定,考虑到虚拟键盘已经占了很大一大块屏幕了,剩下的内容如果再有固定元素,那么可滚动查看的内容区域将更加小,所以当虚拟键盘弹出时,取消fixed元素的固定定位!但是这个『取消』有些蹩脚,在我们这个例子里,标题栏在页面中间的某个位置『绝对定位』了,太丑了,表示难以接受囧。

继续google,有人说可以在文本框获取焦点时,将fixed元素设置为absolute定位。尝试一番,效果比原来好了一些,而且也不违背Apple的设计,请看 优化版 。关键代码:

1
2
3
4
5
6
7
element
.on('focus', function () {
J_fixed.addClass('abs');
})
.on('blur', function () {
J_fixed.removeClass('abs');
})

嗯,效果已有所改善,但在我的项目中,有时候还是会定位失效囧。

于是,再尝试索性将标题栏通过某个手段定在顶部,请看 scroll事件版定位版 ,效果勉强接受,在滚动过程中,还是会随和页面移动,滚动停止时,才会触发scroll事件。关键代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var fixTop = function () {
var winScrollTop = J_win.scrollTop();
J_fixed.css('top', winScrollTop);
};
element
.on('focus', function () {
J_fixed.addClass('abs');
J_win.on(FIX_FIXED_EVENT_NAME, fixTop);
fixTop();
})
.on('blur', function () {
J_fixed.removeClass('abs');
J_win.off(FIX_FIXED_EVENT_NAME);
J_fixed.css('top', 0);
})

再试试另一个 定时版 ,关键代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var timer;
var fixTop = function () {
var winScrollTop = J_win.scrollTop();
J_fixed.css('top', winScrollTop);
};
element
.on('focus', function () {
J_fixed.addClass('abs');
timer = $interval(fixTop, 20);
})
.on('blur', function () {
J_fixed.removeClass('abs');
J_fixed.css('top', 0);
$interval.cancel(timer);
})

表面上看似乎效果与scroll版差不多,但据我的经验,这种方式会更可靠一点点,scroll事件不是太靠谱,定时的方式缺点是比较耗cpu,因为是频繁计算,可以将时间间隔改短一点,节省CPU。

 

另外,再送一点干货:

ios下弹出纯数字键盘方式:

1
<input type=”text” pattern=”\d*”>


1
<input type=”number” pattern=”\d*” >

 

隐藏键盘代码:

1
$('input:focus, select:focus').blur();

 

再扯点别的。

前几个礼拜的文章里,提到会尽量抽时间研究ReactJS,很抱歉,我没有做到,因为时间都投身在一线项目里了囧,包括加班也是赶项目。差不多一个礼拜前,甚至又在AngularJS和ReactJS之间动摇,到底公司新架构应该推哪一个呢。就在这两天,重新确定,『回到』ReactJS的怀抱,似乎React更可能是未来的方向,尤其是与Node的结合,以及React Native,这是一个长远的理想,Fighting!
 

移动端touch事件无视disabled属性-探索收货

先上个 demo ,点击全屏查看,切换到移动模拟模式,并点击按钮,查看控制台。发现click没有事件没有触发,而touch事件依然触发。

算是倒序,虽然不是写小说,拍电影科科~

这个问题挺早就发现了,当时使用Angular + hammerjs,很疑惑为啥disabled的按钮还能触发tap事件,Google无果,无奈通过别的方式在touch事件触发时,判断当前是否处于disabled状态,是则不往下执行。后来,自己在bootstrap的UI框架下,做了个实验,按照平常的习惯,写了个button.btn.btn-default,再添加disabled属性,模拟项目环境,依然引入了Angular + hammerjs,绑定了hm-tap指令,意外的发现居然不会触发tap事件,陷入苦思冥想中。

接着,我把问题简化,移除Angular 和 hammerjs,只使用jquery绑定touch事件,发现依然不会触发touch事件,上个类似我当时使用的 实验代码

通过与上面代码的对比,你应该不难发现,前后只差了 btn 和 btn-default 这两个class,于是就有了线索。那再去掉一个class试试?发现去掉btn-default后,还是不触发touch事件,再去掉btn就恢复到了上个demo的情况了。也就是说,bootstrap的btn这个class,做了某件事可以阻止disabled触发touch事件!

事情更加明朗了,那么我们来看看btn这个“神奇”的class都干了神马。使用chrome审查元素,找啊找,发现了这个:

322

对,就是这个神奇的pointer-events属性!回忆一下,很早前就看到过这个属性,不过当时并没有进入到移动端的开发领域,对它的作用并没有过多关注。我们来看一下mdn上怎么说的:

The CSS property pointer-events allows authors to control under what circumstances (if any) a particular graphic element can become the target of mouse events. When this property is unspecified, the same characteristics of the visiblePainted value apply to SVG content.

In addition to indicating that the element is not the target of mouse events, the value noneinstructs the mouse event to go “through” the element and target whatever is “underneath” that element instead.
一共有11个值,其中只有 auto 和 none 是普通web元素的,其他的都是 SVG only的,SVG相关的我们暂不讨论。

auto 是默认值。

设置pointer-events:none的元素,将不会成为事件目标。但是如果其子孙元素设置了pointer-events:auto,该子孙元素仍然可成为事件目标,并且如果该事件支持冒泡,其设置了pointer-events:none的祖先元素,也会由于冒泡触发相应的监听事件。我们来做个 实验

嗯,终于搞明白这个属性了!

我们再来看一下它的浏览器兼容性:

又是IE拖后腿了囧,不过移动端表现良好~

 

总结

pointer-events这个CSS3属性,在移动端我们基本可以“放肆”的使用,在你需要禁用某个元素事件或某个区域事件的时候,可以考虑下这个属性,简单高效~

软件工程师需要处女座精神

前言:近半年来,处女座总是被黑,一般指处女座的人经常有强迫症,与人难以相处。这次我将其“引入正道”,本文的“处女座精神”特指开发者对自己的代码有洁癖,有重构优化“强迫症”,无法容忍烂代码存在,不屑于为了完成任务就草草复制代码了事的工作态度。
这又是一篇酝酿了很久的文章,用难产形容也不为过,直到此时仍不能文思如尿崩。

前段时间,看到一篇关于“程序员”与“工程师”的文章,跟这篇文章主题也有些关系。大意是讲,“程序员”仅仅是coding,完成开发即可,甚至只是把编程变成当做一件糊口的事情,不会站在更高的层面上看问题,对于整个系统的生命周期,质量把控,公用模块,代码可维护性方面,则关注度不高或能力上不足以胜任这类工作,但在领导看来,只要完成开发任务就是个好员工。而“工程师”在完成开发任务的同时,会思考,有没有更好的实现方式,可扩展性如何,有没有继续优化的空间,甚至深入到底层源码去研究,进而扩大到整个系统的思考,哪些模块可以作为通用功能实现,哪些模块只能差异化实现,就像对待自己的孩子一般,深耕细作。

通常,“工程师”是从“程序员”成长起来的,有的人需要1-2年,有的人需要3-5年,有的人甚至一辈子都停留在“程序员”阶段。但在国内,尤其是行外人眼里,这两个词,几乎是被化作等号的。无妨,我们做自己该做的就好,摆正态度,认证对待自己的工作,努力使自己成长为“工程师”,当有一天闪耀出光芒的时候,也是我们最自豪的时候。

72a6e59bcb0311ad8dd8a327a43877ca

好了,回到正题。

我觉得软件工程师应具备的“处女座精神”包括但不限于以下几点:

一、熟记编码规范

这个应该不用多说,好的编码规范,能够帮助我们避免一些难以发现的错误,同时能让合作伙伴尽可能顺利地读懂你的代码。坚决抵制“脏、丑、乱”的代码存在!作为前端开发,推荐阅读《Javascript语言精粹》、《编写可维护的Javascript》这两本书。

二、多读别人的代码

始终活在自己的世界,总归是不好的,好比于闭门造车,坐井观天。开源社区鼓励工程师们共享代码,互相学习交流,所以开源的技术,总是发展飞快的。Javascript占据开源榜第一,理所当然的成为了世界上最流行的语言。远的不说,我们采用就近原则,多读读日常工作中使用的开源类库/框架源码,也是大有裨益的。特别是在遇到某些棘手问题时,深入到源码进行分析,可以更加有效的找出问题所在并解决。甚至,在阅读了足够多的开源类库框架源码后,我们就能从中领悟出一些其中的精髓思想,假如有一天我们需要打造自己的框架,终究能派上用场。

三、多读书

虽然现在互联网很便捷,遇到问题,稍微花点时间Google或百度一下就能找到解决方案,但绝大部分是零散的知识点,没能系统地总结相关知识点。要想系统地学习,还得通过书籍来完成。即使你已经掌握了大部分基础知识,在阅读过相关书籍后,总会有一些你遗漏的角落,而好的书籍可以帮你查漏补缺,很可能有一天就需要这个被遗忘的细节来帮你解决难题。不要找借口说没时间读书,只要你想,总能抽出时间来做这样一件事。强烈推荐每天留出一点时间来读书!作为前端开发,强烈推荐《Javascript权威指南》(俗称犀牛书),不要怕厚,这是迄今为止,我看过的介绍Javascript最细致的书籍。

目前我的做法是,在公司每天中午饭后,读书20-30分钟;在家里另有一本,在睡前阅读10-20分钟。这样日积月累下来,肯定是一笔不小的财富。我经常觉得,有些事情真是冥冥中注定的,比如前几天在树上刚刚看过某个知识点,几天后就遇到这个它了,很快便解决了我的问题;又比如反过来,我前一天在一个问题上卡了很久,当时只是采用了权宜之计,过了几天在书上就找到了更好的解决方案,是不是上天安排好的呢?

另外,不一定要全部都是技术类的书籍,可以是技术类与人文励志类相结合,一方面在技术上不断深入,一方面提高自己的情商。

四、关注名人名组织

名人之所以会成为名人,一定是在某个领域成为了专家,他们讨论的东西,应该是值得关注的。名组织则可以简单理解为名人的集合,名组织发表的文章会更频繁一些。看的多了,真的觉得世界好大,自己太渺小了,居然还有这么多神奇的东西我还没学会囧。关注名人名组织,毫无疑问会帮助我们打开眼界,跟随世界的脚步。

关注名人名组织的途径,目前主要有RSS,微博,微信公众号。微博,微信也足够了,只要关注对象足够多,每天推送的文章就已经够消化了。等到有一天我们自己也有机会成为名人了,也应当为同行们分享自己的所学所感。当然,我自己显然还远达不到那种境界,想想又不犯法是不是~

这里推荐几个:

微博:

react-china , InfoQ, HTML5中国 ,图灵教育 , 淘宝UED , 奇舞团

司徒正美, 池建强,鬼道-徐凯 , 拔赤 , 玉伯也叫黑侠寸志 , 民工精髓V

还有好多。。。

微信公众号:

InfoQ , 36氪 , 虎嗅网 ,猎云网 , WEB开发者 , FEX , 移动观察

MacTalk , 小道消息 ,探索时间 , 道哥的黑板报

五、遇到陌生的字眼及时Google

在阅读名人文章或优秀的代码时,经常会看到一些自己没见过的技术字眼,这时只要时间允许,请务必要及时Google,这都是在为自己的未来做准备,说不定哪天这个字眼能够帮助你打开一扇大门,通往光明之路~否则某些精彩将与你擦身而过,岂不遗憾终身?不过你也未必会发现当初如果Google了那个东西,现在就会如何如何厉害了,机会总是留给有准备的人,这句话总是对的。比如Angular, React, Grunt, Gulp, Promise等,这些我都是从别人的文章中初次认识,然后就是自己逐步深入研究,并慢慢拿到工作中使用。

六、学会做“懒人”

在开发过程中,经常会遇到需要重复劳动的问题,我们不能抱怨“这个事情好繁琐啊,我不想做了”,或是让它继续浪费你的生命。就拿我最近的一个例子来说,模拟ajax返回数据,由于数据量巨大,如果我每次都通过手动修改硕大的json假数据来反复测试,那真的是要疯了。于是我想起,可以用nodejs循环造对象,造数组,最后通过JSON.stringify转换成json字符串写入json文件。这样,以后我想批量改数据,只要修改基础随机范围,重新生成json文件即可轻松切换模拟的数据,着实可以称的上“偷懒”了。

再套用我先前的那句话:我们要学会做一个“懒人”,脏活累活都让程序去干吧~

七、经常总结

写博客是一个比较有效的总结手段,即使之前你刚刚掌握了一个知识点,但只是一个“点”,通过写博客的方式,你可以更加深刻的理解它,有时写着写着你会发现原来还有一些细节被忽略了,甚至联想开去,由这个点发散成一个面的知识点,会有更加意外的收获。再举一个我最近的例子,在项目里实现了一个抛物线动画效果,但当时是用固定定位结合left和top实现的,后来在写博客时,想起来也可以用transform的translate实现,动手再次试验了一把,在移动端具有更加流畅的效果!然后,回到项目里,把原来的代码也改为translate实现,完美!

目前我给自己定的任务是,无重大事情占据时间的前提下,每周至少一篇博客。通过几个月的时间下来,发现写一篇文章真不容易,尤其是技术类,为了保证给出的demo不出差错,需要反复的校对,为了验证正确性,也需要查询很多资料。一篇质量过的去的文章一般需要1.5-3个小时才能完成。

现在微信公众号也异常火热,也是做总结的一个渠道,可能更加偏重于与读者互动,而博客偏重于自我沉淀。公众号主要针对移动端,博客一般在电脑上阅读,看代码也方便的多。

八、利用合适的工具提高效率

这里的工具主要指软件,现代化的软件开发,几乎没有人用记事本从零开始写代码,各个领域基本都有自己的专业IDE或编辑器,强大的代码提示,有的达到了“令人发指”的地步(似乎是阮一峰大大说的)。但是有了强大的代码提示,不代表你有理由不记住相应的完整代码,最近面试的几个应聘者,居然不会说CSS position的fixed和absolute两个值,只记得f开头和a开头了。。。我也是醉了。代码编辑器越来越多,鼓励大家都去尝试一下,然后选出最适合自己的。

然后,说说操作系统。工具软件也是软件,是运行在操作系统之上的,在软件工程师用户里,主流操作系统无非Windows,OS X,Linux。Windows 本身就用户量巨大,在其之上从事开发工作也无可厚非。Linux比较适合做服务器,GUI软件太少,个人用户量并不大。但是OS X简直就是为软件工程师而生的,GUI与命令行的完美结合体(引卖桃君所言)。OS X上有太多适合软件工程师的功能与软件,尤其是无需常关机,空格快速预览文件,“开盖即用,关盖即走”(macbook),命令行一气呵成式的安装软件等等。知乎上有很多关于Windows和 OS X的对比分析,有兴趣的请自行翻找。

工作中遇到操作系统级别不爽的操作,一定要去Google一下,很可能别人也需要类似的问题,并且有了解决方案。比如OS X 上finder里拷贝文件路径不方便,其实早就诞生了XtraFinder这样的系统插件用于解决此类问题,另外它还提供了大量其他人性化的功能。

另外,使用Windows习惯了的人,希望一切软件都是免费的,甚至使用盗版。这是一种不正常的心理,同样身为软件工程师,却不支持别的软件工程师的工作成果,如何能促使软件的进一步完善?通常收费软件的质量会比同类免费软件的质量要高一些,如果一款收费软件能够真正为你带来价值,那么支持一下有何不可?这是我的常规情况状态栏:

应该还不算多的,专业人士的状态栏上运行的常用工具早就不是一行能显示的下的了。其中第一个manico(国人开发)和第三个sizeup,都是我最近购买过license的,分别用于快速切换应用与快速调整窗口大小,这对于软件工程师来说真是太贴心了!

九、耐心帮助他人解决问题

这个其实也不用多说,非特殊情况,就没有理由拒绝别人的求助,说不定你自己也能从中学到一些东西。即使是比你差的人问你你已经倒背如流的知识点,在你解释它的过程中,你也很有可能温故而知新,所谓“最好的学习方法就是教别人”,不是没道理的。帮助他人,某种程度上也是提升自己。我之前学习Angular的时候,加入了一个QQ群,当我自己渐入佳境的时候,也会经常帮助群里的初学者,甚至在某些在线共享代码平台展示我的代码。有些问题,我自己也只能说是一知半解,经过一番研究,补上了相关疏漏知识点,这是双赢的结果。

十、建立自己的实验室工程

这个与前端本身的门槛低有点关系,“一个记事本,一个浏览器,就可以边写代码,边看效果”,搭建前端入门环境如此简单。所谓“实验室工程”,就是一个专门用于试验各种想法的代码工程,也可以理解为一个工程模板,每当你有一个念头一闪而过的时候,可以迅速打开这个工程进行验证,说不定一个伟大的框架就此生根发芽。试验所需的类库/框架,可以通过bower或npm安装。比如浏览器环境的试验,可以快速建立一个简单的HTML页面,里面已经引用了常用的类库/框架,你只需直接编写你想试验的代码,然后在浏览器中打开预览即可。如果是node环境的试验,简单的情况,一个js文件就够了。这两种情况,webstorm很好的满足了我的需求。由于取文件名是件麻烦事,所以我干脆就以当天的日期命名试验文件,上个图:

 

总结

虽然上面提到这么多,我自己也并没有每条都做到,人性骨子里始终还是有惰性存在的(好像是在给自己找借口囧),或者说我的意志力还不够强,所以我很钦佩当过兵的人,部队里从来都是纪律严明,训练过的意志力是可以过度到学习中来的。但做总比不做好,积少成多,水滴石穿,谨以此文激励自己不断前进,也希望对看到这篇文章的读者能有一定积极的作用。

从“程序员”到“工程师”,从菜鸟到大牛,需要经历很长很坎坷的路,比别人要付出几倍数十倍的努力。然而,只要我们要保持正确的心态对待我们的工作,或者说是我们的事业,最终一定可以实现工程师的自我价值。

重温javascript的this指向

前几天,听同事讨论起javascript的this指向问题,趁此机会复习一下这个知识点。

翻了下犀牛书,在8.2.2节(第6版p171)提到了this的指向问题:

需要注意的是,this是一个关键字,不是变量,也不是属性名。JavaScript的语法不允许给this赋值。

和变量不同,关键字this没有作用域的限制,嵌套的函数不会从调用它的函数中继承this。如果嵌套函数作为方法调用,其this的值指向调用它的对象。如果嵌套函数作为函数调用,其this值不是全局对象(非严格模式下)就是undefined(严格模式下)。很多人误以为调用嵌套函数时this会指向调用外层函数的上下文。如果你想访问这个外部函数的this值,需要将this的值保存在一个变量里,这个变量和内部函数都同在一个作用域内。

(以上是LD亲手敲的奥,赞一个- -)
对着上面这段话提到的场景解释一下:
嵌套的函数不会从调用它的函数中继承this

1
2
3
4
5
6
7
8
var Outer = function () {
this.foo = 'outer value';
function fnInner(){
console.log(this.foo)//如果继承了外层,那么会打印outer value
}
fnInner();
};
new Outer();

答案是undefined,也就是说不会继承外层this,这个应该是最好理解的。那么如何访问外层this下的属性呢?很简单,且看:

1
2
3
4
5
6
7
8
9
var Outer = function () {
this.foo = 'outer value';
var that = this;//将this赋值给一个局部变量
function fnInner(){
console.log(that.foo);//访问that即是外层函数的this
}
fnInner();
};
new Outer();

说起that,关于这个局部变量的命名有三大党派:

  1. that
  2. self
  3. me
    你更喜欢哪一派呢?

再看下一个:

如果嵌套函数作为方法调用,其this的值指向调用它的对象。

1
2
3
4
5
6
7
8
var Outer = function () {
this.foo = 'outer value';
this.fnInner = function (){
console.log('nested func: ' + this.foo);//this即为刚刚创建的Outer实例对象
};
this.fnInner();//方法调用
};
new Outer();

理解这个应该也不难。最后一个场景:

如果嵌套函数作为函数调用,其this值不是全局对象(非严格模式下)就是undefined(严格模式下)。

1
2
3
4
5
6
7
8
var Outer = function () {//非严格模式
this.foo = 'outer value';
function fnInner(){
console.log(this);//此this为全局对象,在浏览器中就是window,在node中是一个global全局对象
}
fnInner();//函数调用
};
new Outer();

浏览器:

node:

再看:

1
2
3
4
5
6
7
8
9
var Outer = function () {//严格模式
'use strict';
this.foo = 'outer value';
function fnInner(){
console.log(this);
}
fnInner();
};
new Outer();

浏览器:

node:

嗯,大致有数了。

PS:严格模式是ES5推出的标准,开启这个模式(函数首行添加’use strict’;),可以防止很多由于javascript本身的设计缺陷导致的隐形bug(比如这里的this指向全局对象,可能导致全局变量污染),帮助我们及早发现问题。
 

上述只是犀牛书中提到的关于this的一部分相关内容,其实还远远不够。

在我理解来看,大致上分为以下四大场景:

一、函数仅作为函数被调用

即直接在函数名后加圆括号调用,或在高阶函数里调用函数类型的形参,甚至使用匿名立即执行函数,它们的this都指向全局对象。

好吧,好像又多出了几个小场景囧。不过无论全局函数还是局部函数,这都成立。上demo:

二、传给setTimeout、setInterval等全局函数的回调

这些回调内的this也是全局对象,只不过浏览器和node有些区别(我也刚发现- -)。

三、函数作为对象方法被调用

这种场景,就属于面向对象编程了,this的指向很好分辨,当前方法的调用者即为this的指向。在这个例子里,this指向刚刚创建的Foo的实例对象,因为是通过这个实例对象“点”someMethod()的,也就是说谁“点”了someMethod(),谁就是this。顺便提一下,这样调用是等价的:

四、函数与call,apply,bind结合使用

这个场景是最复杂的,也是几乎所有框架都会使用的技巧。

这三者都属于函数的原型方法,都可以改变函数(方法)的this指向(或者叫做改变执行上下文)。

call与apply更接近,他们会立即执行目标函数;而bind是ES5种新增的标准,用于预处理函数,事先绑定this指向。一图胜千言:

另外,我自己也好奇,如果调用boundAdd时,也用call会怎么样呢?如果你也一样好奇的话,就自己动手敲一敲代码吧,我也是希望加深你的印象~

另外提一下,call与apply的适用场景。个人认为,apply是比call强大一些的,举个复杂一点的栗子:

如果你能完全理解这个栗子的话,说明你已经对call和apply理解透彻了(其实还包含了闭包的知识点)。

至于bind的话,可以在场景二中这样使用:

总结

关于this的话题,其实还有不少,尤其在面向对象编程的领域,更加重要,需要更加深刻的理解,想要在javascript上有所造诣,这块一定要啃下。

PPS:这是换了Pro之后写的第一篇博客,这屏幕太赞了,回去再看看Air,瞬间变“渣屏”(不过比起一般的windows兼容机还是好得多的)。我用了两年零八个月Air退居二线了,希望新Pro能让我告别卡机死机的日子~科科。
 

 

使用webstorm远程开发

在前端开发过程中,有时候,我们本地开发环境无法模拟真实环境,比如没有真实的后端服务(虽然可以用nodejs模拟,但毕竟是假的),又或者只有一部分真实环境,甚至有了全套真实环境,但数据不够真实,只能在【远程的】较真实的环境上开发,即通过不断的将本地代码应用到远程来预览效果。

比较古老的远程开发方式大致有两种:

  1. 本地代码提交到版本控制,然后通过ssh等方式登陆到远程机器,执行代码更新操作,然后浏览器刷新预览
  2. 手动通过ftp将代码传输到远程机器,然后浏览器刷新预览
    这两种方式无疑都很繁琐,不像我们本地开发时,改完代码直接切换到浏览器刷新(甚至可以实现Live Reload),就能看到效果。

接下来,该主角上场了。请注意上面的第二种方式,我使用了【手动】这个字眼。本文分享的方式,即为基于第二种方式,事先做一定配置后,即可实现近乎本地开发体验的远程开发!

一、开启远程配置

打开你的webstorm,Tools -> Deployment -> Browse Remote Host,界面如图:

二、新建远程配置

如果你还从来没使用过这个功能,左侧列表将会是空的,点击左上角的“+”,弹出一个小对话框,输入任意名字,确认。

三、配置ftp

随后在新建的远程配置中输入ftp服务所在的host地址、端口与用户名密码,并测试。

如果不成功的话,考虑切换为被动模式:

四、配置Root Path

Root Path是用于选择ftp映射的根目录,比如ftp上开启的目录是/webapps/a/b/static/…,而你本地的工程目录是从static开始,static下面的目录结构基本一样,那么你就应该把Root Path设置为/webapps/a/b/static。只有当你选择的根目录与你本地的基本一致时,远程开发才能顺利进行。

五、配置mappings

选择顶部的mappings标签

如果你希望本地工程的根目录与ftp上的某一层目录相对应即可的话(通常为同名目录),那么这里的Deployment path on serve on ‘’设置为“/”即可。

如果你希望你工程下的某一级目录跟ftp上的某一级目录对应,那么就需要设置Local path了。

点击“Use this serve as default” 按钮将这个远程配置设为默认远程主机。

六、设置自动上传

前五步已经完成了远程主机的配置,点击右下角的确定。然后菜单 -> Tools -> Deployment -> Options

将图中的下拉框选择为Always(建议)或On explicit save action(按下保存键时上传),其中Upload external changes用于配置【非手动修改时,发生改变的文件,是否自动上传】,比如less自动编译为css的时候,就非常有用。

点击确认,然后就是见证奇迹的时刻啦!观察webstorm右侧是否有Remote Host这样的一个侧边按钮,如果没有,双击shift,弹出全局搜索,输入remote,出现Remote Host选项,选择它,然后就会出现侧边栏了。

如果你上述所有的配置都正确的话,就看到类似下面这样的界面,其中绿色背景表示是被正确映射的目录/文件。

然后,随便打开一个你本地的一个文件,修改并保存,很快你就将看到,底部的状态栏,出现了:

打开浏览器, 访问你的远程主机部署的服务,检查是不是真的上传成功了。

就这样经过一番配置,我们就可以几乎像本地开发一样,远程开发,每当文件发生改变,就会立即【自动】上传到ftp服务器,换言之,即自动化了,相当便捷!

七、补充

当由于某些意外,你本地工程的代码与ftp上不一致了,我们还可以通过在左侧文件浏览器里,右键目录或文件,选择

也能够实现ftp上传(选择目录则为批量上传)。

在Remote Host栏,右键也有很多功能,请读者自行去探索,应该会给你很多惊喜。

webstorm作为前端开发神器,实至名归!

这个方法也是曾经的同事分享给我的,屡试不爽,现如今拿出来分享。

其实不仅仅前端可以使用远程开发,后端也可以,不过脚本类语言开发效率会高很多比如PHP,因为不需要编译重启等过程,JAVA就会痛苦的多,科科~