Git Product home page Git Product logo

blog's Introduction

Hey

blog's People

Contributors

imsobear avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

blog's Issues

初识polymer

原本只是想了解 polymer ,结果被代入一个又一个新的概念中,主要是 web components 内容。

web components 主要包括:Templates(模板), Decorators(装饰器), Custon Elements(自定义标签), Shadow DOM(不会翻译), import(HTML导入)。主要通过 HTML5 ROCKS 这个网站了解学习的,都是大牛们在写,质量灰常高。下面是一些文章的链接:

感觉 Shadow DOM 的概念最为抽象,不知道怎么翻译,概念现在也还是模模糊糊的,但是对于封装、隐藏细节来说,它又是最重要的一点,所以还要慢慢深入了解。

好了,概念了解的差不多了,可以去折腾下 polymer

《1984》

《1984》这本书放在书架上有一个多月了,看一两页丢弃,然后重复……就是这种感觉,全然没有看《动物庄园》时那种轻快的感觉。最近也是强迫自己看下去的,看完后才明白为什么当时看不下去。
这本书前面差不多三分之一的部分都是围绕一个主人公说的,没有什么主线和情节,就是一些零零散散的小故事以及主人公的心理描写,不得不说,对于心理描写感觉跟《平凡的世界》差不少,也可能是翻译的问题,总之,前三分之一作者就是在不断的交待那个时代的背景,并让读者能深切感受体会之,于我个人来讲,过于繁琐。

过了三分之一,当爱情出现,当反抗出现,我才真正的有了读下去的兴趣,却不知,男女主人公刚站到反抗者的阵容里,还未有任何实质性的行动和贡献就被老大哥发现了,这又是一个三分之一。

最后的三分之一,就是主人公在折磨下的抗争,然后屈服,接着再抗争,最终还是在**上屈服。

怎么说呢,无论是从作者乔治奥威尔,还是此书的饱受盛誉,我都不敢去说这本书不好,只能说是跟想象中的不一样,看完《动物庄园》时对这本书预期很高,想象着会忘我的用一天或者半天看完的。

要问有什么收获,从个人角度讲,除了知道了老大哥、新話、双重**这些词语的意义,除了记住了那几句经典的话语,如自由即奴役,如老大哥在看着你,如自由就是每个人可以说二加二等于四,其他的收获,微之甚微。

或许是因为自己图样图森破了吧,碎碎念一篇。

NODE_ENV 介绍

NODE_ENV 是什麽

NODE_ENV 是系统的一个环境变量,用来标识 node 运行的环境,Node 应用运行时可以读取系统的环境变量,所以我们可以根据这个变量值做一些差异性的配置。

NODE_ENV 使用场景

最常用的场景应当是应用的 config,通常情况下,我们会用不同的机器,如开发环境、生产环境,那我们就可以在不同的机器上设置对应的 NODE_ENV 值来区分啦,然后在 config.js 里加以判断:

var dev = {
  db: {
    database: 'test',
    host: '10.xx.xx.xx'
  }
}

var production = {
  db: {
    database: 'app_sql',
    host: '10.3.34.xx'
  }
}

var env = process.env.NODE_ENV;
module.exports = env === 'production'? production: dev;

这样我们就可以在不同的环境里自动使用不同的配置项啦。

怎么设置 NODE_ENV

设置 NODE_ENV,其实就跟设置系统的环境变量一样,有时间了操作以下。

编程语言君们

系科普文,比较浅显,所以不要有太高期望。

摘要:话说你还记得用C语言怎么输出’hello world’的代码没?就当你没忘记吧。这个世界到底有多少种编程语言?我们一起来数数吧。

事实上我根本没法把所有的编程语言罗列出来,这里只简单介绍一些相对主流的语言,什么Pascal, perl, self, VB这些年龄略大或者Lisp, Haskell这种大牛级别的语言,我就不说了,一来是不懂,二来价值不大。

1. C and C++

语言排行榜分列1,3名。C语言是大学基础课,大家相对了解多一些,上过C语言课的人多会问这玩意能干啥,C语言属于比较底层的语言,因此比较高效,所以多用以开发系统内核、嵌入式、高效算法,比如说Linux的内核就是用C语言编写的,但高效的同时会伴随着很多复杂的知识点,比如大家众所周知的指针。随着计算机硬件性能的不断提高,语言的执行效率问题会越来越不突出,而开发效率会越来越重要,因此没有啥特殊需求的话,C语言还是蛮伤不起的。C++可以理解为面向对象的C语言,面向对象的知识择日再讲吧。

2. Java and C

排名分列2, 5位。Java属于企业级的编程语言,稳定但不高效也不够灵活,很多公司在用,学懂了Java基本不愁工作,但前提是你对这个语言有兴趣。Java主要的应用有:桌面应用(不多),大型网站(阿里巴巴、twitter等),Android应用。C#(读C sharp)语言特性跟Java类似,是微软为了对抗Java而推出的编程语言,不是很多的企业在用,这个不很确定。

3. Python and Ruby

排名分列8、10位左右。这两者都属于动态语言,像前面所说的C、C++、Java和C#都属于静态语言,区分静态语言与动态语言最简单直观的方法就是数据类型的问题,比如在C语言中声明一个整型需要int a,字符要char a,而在动态语言中无论是整型、字符还是数组只需要var a.当然两者的区别没有这么简单,只能说这是一种比较简单直观的方法,希望你们看懂了。
Python 和 Ruby区别不大,放在一起说吧,高级动态语言,执行效率没有静态型高,但开发效率要提高很多倍,多用于网站搭建,例如豆瓣、知乎后台都是用的Python。

4. HTML、CSS and JavaScript

前面放在一组的语言都是特性比较接近,而这三种语言属于应用的地方都一样——网站前端,只是三者负责的功能不同。在一个网站的页面中,HTML负责显示内容,例如一个标题,表格或者是图片、链接之类的;CSS则负责内容显示的样式,比如说一段话的字体颜色、字号大小、背景颜色;JavaScript负责交互功能,例如点击一个按钮弹出个对话框,或者是动画之类的,当然现在JavaScript的应用已经从前端延伸到后台,而且HTML、CSS和JavaScript三者之间的职责重叠的越来越多,这里就不展开讲了。

5. Objective-C

为苹果应用而生的语言,应用于开发各种苹果产品的应用,很火很赚钱,语言特性我不了解,不敢多嘴了。

6. 奇葩语言:易语言

我见过的最牛逼最奇葩的语言,没有之一。单一个特点足以秒杀一切,用汉语写代码,没错,是汉语。比如说C语言中的if(2>1),在易语言中是这样的:如果真 (2>1)…这也算是国人在编程领域的一次尝试,是有点可爱还是。。。

差不多就讲这么多吧,没有太多的技术性名词,理论上理解难度不大吧,希望对诸位有点用。

Change or die

额,我承认我是一个标题党。

想起这个话题是因为前两天看到网易新闻客户端吐槽百度抄袭,我想说吐得漂亮,但结果却让我小跌眼镜。刚才专门搜索了一下,微博已经删除了,简单回顾一下:网易客户端的主题基本是红白为主,但百度通常时候是蓝白相间,然后百度最近的一次更新,主题和图标突然给成了红白色的了,所以网易小编就耐不住了,我表示吐槽过程很欢乐。

其实我是想黑百度的,上面只是个引子。**互联网三大巨头,阿里、腾讯、百度,几乎毫无争议,但是随着移动互联网的到来,这一格局是否会改变?腾讯自不用说,有你正用的这款应用,算是一个很大的入口了;接着阿里,即便阿里不跟新浪微博合作,也没多大问题,除了没有社交入口,淘宝,支付宝,天猫,一淘and so on,业务覆盖面应有尽有,与微博的合作只能说是如虎添翼,就看怎么拿小白鼠试验了;再说百度,以搜索起家,但搜索在移动端显然没有在PC端的威力,放眼望去,百度的手机App数量现在该有一个半屏幕那么多了吧,什么百度贴吧、百度新闻、百度旅游…额,仿佛也是应有尽有,其中也有好的应用,比如百度输入法和百度地图,但这两款应用,用户的概念很弱,所以几乎没有黏性可言,其他的应用我是挑不出来了。

百度,绰号度娘,于1999年在美国硅谷成立,继谷歌于2010年被政府赶出**后几乎垄断国内搜索市场。垄断是个可怕的词语,任何一个行业、一个部门一旦处于被垄断状态,那么它进步的速度一定跟用户的最大忍耐度相等,如铁道部的购票系统,如铁道部的服务,如各种叫不上名字的扯淡部门,从来不会主动寻求进步,寻求高效。垄断即有唯一的话语权。当然,互联网行业亦是如此,我很少用百度,也从来没有感觉到进步,有人可能会说:我觉得百度的搜索挺好用的啊。对,没跳出井的青蛙,一直觉得井底的天其实也蛮大的。

OK,继续说垄断搜索行业,有人垄断,就要有人打破,这次是360。其实我也是相当讨厌360的,但360的魄力是值得敬佩的,当所有人都觉得有百度的垄断在**几乎是没法做搜索了,360推出so.com,接着就是各种攻击了,360树敌太多,百度稍一呼应,各种漫天报道360窃取用户隐私。唉,这些互联网公司哪个不是啊,还不都是五十步笑六十步嘛。无论如何,希望360搜索能够在一定程度上打破垄断,走向良性竞争的道路。

额,貌似脱题了,脱就脱了!!!

随着移动互联网热浪袭来,各大巨头都开始在移动端布局自身的生态系统,百度当然也不甘落后,但效果相当不显著,去年网曝百度CEO李彦宏发给员工的信件说道鼓励狼性,淘汰小资。试问狼性何在?若有狼性,怎连新浪微博这块肉都不敢啃一口?还是新浪嫌你嘴臭,主动向阿里投怀送抱?

很多大公司都在收购小的有前途的创业团队,但是有一点就是:自身的创新基因不够,收购再多的团队与产品也是糟蹋资源。

最后,我可不会大言不惭的说百度会死怎么样的…一个与政府关系这么好,几乎垄断一个行业,目前收入在国内互联网公司中稳居前三的公司,怎么会这么容易死!

—–正文完—-

电子阅读在未来多少年后会根本性的取代纸质阅读?你觉得呢,是根本性的取代,不是完全性的取代。

每日推荐:
你们知道为啥百度叫“度娘”吗?
答案是这样的:话说百度贴吧里有羊吧、狗吧、猪吧等十二生肖吧,但唯独没有X吧(X自行猜测),所以就叫做度娘了。。。

从产品说起

从产品说起


《人人都是产品经理》,不知道这本书坑害了多少人,尤其是这个书名,看到这个名字最容易联想到的书就是《21天学会XXOO》,很多人以为看完《21天学会某编程语言》就算学会了这门语言,同样的,很多人以为看过几本书就可以成为产品经理。事实上我没看过这本书,也不知道这本书写的到底怎么样,只是为那些持有看完什么书就算掌握了某种知识这种观点的人感到遗憾。

最近的实习经历,让我对以前对于做产品的观点有了更加深刻的理解,事实上我的实习职位是前端,呵呵。最近参与的项目是一个引导用户如何使用淘宝购物的平台,这个产品的用户群体是来淘宝的新手,核心目标是教新手怎么购物,或者怎么使用淘宝。但在做的过程中,我看到这个产品越来越复杂,事实上它发布的时间并不长。这让我不禁想起了之前看到的一个故:小和尚对老和尚说,哦不对,是年轻的程序员对资深的程序员说:“现在这么多编辑器,vim,emac,sublime,notepad,学习成本太高了,我要做一个更牛逼的编辑器,包含这些所有编辑器的功能,这样,码农们只用学习这一种编辑器就好了”。资深程序员说,原话忘记了,大体是这样的,“你这样做的话,程序员又要多学习一个编辑器了”。好吧,我表示资深程序员的原话还是蛮幽默的,OK,我们本身是要做一个工具让新手学会怎么用淘宝,可现在的事实是新手先要学会怎么去用这个平台,作为一个半只脚踏入互联网这个圈子的人,觉得其中的逻辑不够明了且过于复杂冗余,那么新手会怎么去看待这个问题呢?

看了上面的话,千万不要觉得自己中枪了,一来说的不见得对,二来即使恰好被你认同了,这本身也不是某个人的问题。在一个产品的设计过程中,只要是有话语权的人都会去提出自己的想法,产品、运营并且觉得这些方法是对的,同时也会努力说服大家把他的想法加进去,于是一个产品会变得越来越复杂。题外话,在这里,我不得不表示对于微信产品团队的佩服,如此强的克制力实属难得。在产品从简单到复杂的一个过程中,我想起了曾经看过的一本书,不是《人人都是产品经理》,是《Get Real》,出自37signals之手,如果你单是去看书,可能觉得书中的观点过于激进,但如果是在参与一个产品设计开发的过程中,书中的观点可谓金玉良言,「永远记住产品的目标群体和核心需求,有胆量去砍掉任何鸡肋功能」,表示这本书需要重新认真研读一下。

同时对于视觉或者交互上的设计貌似也是同样的境况,忘记目标用户,忘记核心需求,单纯的以为功能越全面越好,什么如果用户鼠标没有滚轮怎么办,用户进到页面不知道干什么。不要把用户想的那么蠢,他们只是菜鸟,但不是**。诸如「从用户的角度讲,巴拉巴拉巴拉...所以这个功能是有必要的」,既没有深入研究过心理学,又没有大规模的实践(放心,这两点我都没有),这个从用户的角度讲中的用户到底是哪个路人甲啊。这里又想到一个算是无关的东西吧,《Don't Make Me Think》这本书中说到:「去掉每个页面上一半的文字,然后把剩下的文字再去掉一半」,其实应该把按钮的数量也加进去,当然,渣浪微博需要把原话中的比例提升一下,比如砍掉三分之二?

我们都自以为是,其实我们都是错的,比如上面那一堆话。

写在最后,因为最后这段话是对的。互联网从业者们,赶紧放弃IE6吧,别盯着那百分之几的PV了,用维护IE6的时间可以产出N倍的价值。哦,我说的放弃指的是强制提醒升级,而不是在最后加个「继续浏览」,要我的话,果断继续浏览了,升级多麻烦啊。最后这段话是对前端工程师这个职位的唏嘘,当别人已经各种响应式、多终端、各种高级属性搞得飞起的时候,我们竟然还要去维护12年前发布的IE6,那个年代还没有前端这个职位吧。对于那些声称研究兼容性问题是个很有挑战的任务,我对这个太特么感兴趣了。妈蛋,别扯淡了!

其实我不是在吐槽,真的不是。

边看边学:MongoDB基本操作

按照上一篇的方式先启动mongo shell,这时候会使用名为test的默认数据库,你可以在启动时通过添加参数或者用use指令切换数据库,例如要使用名为tutorial的数据库,可以这样启动:mongo tutorial ,也可以在正常启动后键入use tutorial

这时候我们就需要做一些最基本的CRUD操作了,我们以users集合为例,Mongo中的一个集合跟MySQL中的一个数据表类似:

1. 插入数据(Create):

db.users.insert{name: "smith"} 或者 db.users.save{name: "smith"}
注:save既可以插入数据也可更新数据,带有_id参数时会更新对应id的数据,如db.users.save({'_id': '1', name: 'ben'})

2. 更新数据(Update):

db.collections.update()需要两个参数, 第一个指明要更新的文档,第二个定义如何更新。如:

  • 更新或添加属性($set):db.users.update({name: 'sobear'}, {$set: {age: 22}})
  • 删除属性($unset):db.users.update({age: 23}, {$unset: {name: 1}})

3. 查询数据(Read):

db.users.find():找出users集合里的所有文档;
db.users.find({name: /s/}):name里含有s的所有文档;
db.users.find({hobby.sports: ’basketball‘}):爱好运动里有篮球的同学们。

4. 删除数据(Delete):

db.users.remove(condition):删除满足condition的文档;
db.users.remove():不带参数,清空集合包含的文档,但不删除集合;
db.users.drop():删除集合以及他它的全部索引。

MongoDB基本的CRUD操作就这些了,后面会尝试搞懂索引这个东东。

----正文完----

App升级:

作为一个普通用户,觉得App升级是门艺术,有不少讲究的地方。

  • 注重升级文案:升级文案的排版、将重要的改动放在前面、避免使用bugfix之类的术语;
  • 掌控升级频率:私以为三个月是个不错的频率,PM需要思考、运营需要思考、程序员也需要思考,更重要的是不要频繁的去试错,不要过多的打扰用户;
  • 规范版本号:比较好的版本号应该是x.y.z这种的吧,感受一下。

碎碎念:
以前有个习惯,无论是看电影还是美剧都不喜欢快进,最近从第一集开始追海贼王(已出700多集),这个习惯必须要改啊,朋友说他追动漫的时候直接开四个窗口,不知道是智商差距还是神马原因,尝试了一下,完全跟不上节奏,放弃这种速成的方法了。

简单来说,好的页面设计是这样的

  1. 动画一致性:比如 hover 的效果,动画的运动方向;
  2. 颜色的搭配:不需要太多的颜色;
  3. 合适的字体:不要动不动就微软雅黑,很多设计师不知道 12px 的微软雅黑渲染有多糟。

最好的案例天猫首页,基本上图片的 hover 效果都是向左滑动。

抛弃IE6

记得前不久看到一个前端的大牛说:无论你承不承认,前端所面临的最大问题绝不是各种组件以及MVVM框架。

那么,前端面临的最大问题是?我个人的思考是,向后兼容,也就是ie6、7、8所带来的各种问题。就像Ruby2.0或者Python3000的发布,各个平台会迅速支持,从而为开发者带来福音,但前端不然,HTML5、CSS3以及ECMAscript5.0的发布,是的,chrome、firedox甚至ie也都迅速支持,但是,没用啊,你还是需要考虑ie低版本的兼容问题,因为据说**有20%的ie6用户。如此,新技术所带来的影响就大打折扣了,甚至是增加了工作量。

这个时候,大家都会齐聚一堂吐槽ie,吐槽微软。有时候会想,这是微软的问题吗?微软也在努力普及win8和ie10啊,难道就没有开发者的责任? 开发者或者大公司为什么总是要绞尽脑汁的兼容各种低版本浏览器,而且还将之视为技术高低的标准。如果阿里,腾讯,百度这些公司都宣布不再支持低版本浏览器,并且建议用户升级浏览器,一来在用户数上不会有多大损失,因为用ie6的人必然找不到这些产品的替代品;二来这样做之后会大大的改变前端的工作环境,对于所有的前端开发人员都是福音。

那么,何乐而不为呢?
我觉得可能是错误的价值观所导致的,对于大公司来说,已经养成这样的一个风格或者节奏,处于一种麻木的状态,而对于小公司,则可能多是出于跟风的节奏。(瞎扯嫌疑)

找实习的这段时间,面了也有好几个公司了,大部分时间都花在ie兼容上,神马ie下的盒模型,事件模型等等等等。我自以为对于技术的考察不应该是这样的。

最坑爹的是有的招聘信息写什么觉得研究兼容性问题是件很有挑战的事情。技术是为了更好的服务于生活,不是为了秀你的各种hack。

前端菜鸟一枚,不喜就尽情喷。

抛弃IE6之后

写在前面:上篇文章说到抛弃IE6, 这种略显激进的观点肯定会有很多不同的意见,很正常,我也觉得有些激进,但**现在不就需要做些激进的改变吗?还好人微言轻,否则前端界可能就炸开锅了,呵呵。

上篇说到,开发者应该抛弃IE低版本,那么抛弃了低版本IE之后到底有哪些好处呢?我从HTML、CSS和JS这三方面大体说一下吧。

  1. HTML5:

简洁强大的DTD:不用担心版本,不用担心怪异模式,只需要;
更加语义化的标签:放心使用header、nav、section、article、aside、footer这些更具语义化的标签,把div和span标签仅用于布局。
丰富的表单属性:停止使用JS繁琐的验证表单,HTML5对此做了足够的支持,新的属性:placeholde、required、autofocus、min、max等,新的input type: email、url、date、tel、range等。
流媒体的使用:video、audio,这里各浏览器的支持格式不统一,因此还要注意兼容性问题。
新的API:主要有本地资源存储,获取地理位置等,没有用过,就不卖弄了。
2. CSS3:

选择器:CSS3提供了跟jQuery类似的选择器,相邻、属性、nth-child等各种新的选择器。
动画:这应该是最令人兴奋的特性了,用transform、transition、animation做动画比jQuery简单且高效,具体可以参考我做的这个DEMO;
更加丰富的盒模型:flex-box
第三方字体:@font-face,但因为中文字体的制作难度和工作量都高出西文字母很多,因此这一特性目前作用并不大。
3. JavaScript(待详细补充):

使用ECMAScript 5.0的新特性:
选择器:羡慕jQuery简单强大的选择器?HTML5给出了解决方案:querySelectAll(“a .next”),除了方法名长了点,更高效自不用说。
事件模型:直接使用addEventListener().
Ajax封装:
总结:之前区分HTML、CSS、JS的任务标准是:HTML负责内容,CSS负责样式,JS负责行为。那么在HTML5和CSS3逐渐标准的情况下,我觉得这三者的分工有了一定变化:HTML依然是以负责内容为主,而CSS则不仅负责样式,而且要负责动画以及一些交互,这样的话JS就专注于逻辑层面的控制以及数据的处理。

动画初探

动画初探

最近要做动画有关的东西,看了两天动画有关的知识,零零散散的先记录下来。

业界动画引擎:


FPS:

动画间隔决定了动画的每秒帧数(FPS),一般的,FPS越高,动画就表现得越流畅,FPS偏低,动画就会不流畅、卡顿。JQuery中,动画间隔默认为13ms,也就是说理想状态下,动画的每秒帧数是70(1000/13)多。

但是动画间隔并非越短就越流畅,因为浏览器需要渲染的时间,所以间隔一方面必须足够短,从而使不同的动画都能流畅的进行,别一方面还要足够长,使得浏览器可以完成渲染。没有找到官方的文档,网上的文章大多倾向于13ms。

参考:


requestAnimationFrame:

setIntervalsetTimeout 的缺陷:

  • 无论是setInterval()还是setTimeout()都无法达到精确,这个延迟即你指定的第二个参数仅仅表示何时代码会添加到浏览器的可能被执行的UI线程队列中。如果队列中有其他工作在此之前,那代码将会等到他完成才会执行。简而言之,毫秒级的延迟不是表示何时代码会执行,而是表示何时代码会添加进队列;
  • 当相应的浏览器窗口最小化,JavaScript 计时器在背景标签仍然持续运行,消耗CPU和电池。

CSS transitionsanimations 的优势在于浏览器知道哪些动画将会发生,所以得到正确的间隔来刷新UI。而javascript动画,浏览器不知道动画正在发生,所以催生了requestAnimationFrame,对于延迟做了很大程度的优化。

  • 仅绘制用户可见的动画,这意味着在页面不可见时不会绘制动画,节省 CPU 和电池;
  • 绘制动画不可能出现多个排队的回调函数,或者阻塞浏览器;
  • 由于浏览器准备好时(空闲时)才绘制帧,不会有等待绘制的帧,没有多余的帧绘制,因此动画更平滑,CPU 和电池使用被进一步优化。

注意:在有多个动画时,出现一个可见一个不可见,requestAnimationFrame 会导致动画不同步,所以, 指定一个参数确保所有需要同步的动画状态,不受可见程度的影响(如一组动画从开始以来经过的时间),而不是根据每个动画的前一帧。

兼容各浏览器的 requestAnimationFrame 方法:RAF.js


总结:

目前的动画库基本通过两种方式:css3canvas,css3难度相对小一些,但降级方案成本比较大,canvas学习成本会高一些,具体的降级方案还有待研究。

在做之前,需要先确认好具体要支持哪些需求,别人怎么使用,然后再选择一个最优的方案。

CSS3 Animation属性与事件

Animation的属性介绍基本上到处都有,这里只介绍一下,重点是第二点中的animation相关事件。

目前,IE10+以及火狐、webkit支持该属性,并且IE和火狐已不需要前缀,只有chrome和safari需要webkit前缀。

1. animation参数说明:

.anim{
     animation: name duration timing-function delay iteration-count direction play-state;
}
  • duration: 动画执行时间,默认为0;
  • timing-function: 动画速率控制,默认为ease:
    • linear: 速率相同;
    • ease: 默认值,快-慢-快;
    • ease-in: 慢-快;
    • ease-out: 快-慢;
    • ease-in-out: 慢-快-慢。
  • delay: 动画延时,默认为0;
  • count: 动画重复次数,默认为1,设置为infinite表示无限重复;
  • direction: 播放方向:
    • normal: 默认值,正常播放;
    • reverse: 反向播放;
    • alternate: 先正向再反向;
    • alternate-reverse: 先反向再正向。
  • state: 控制动画播放暂停:
    • running: 默认;
    • paused: 暂停动画;

附加:还有一个animation-fill-mode属性,目前还没有成为标准,但支持animation的浏览器都支持这个属性,
属性值为forwards时表示动画结束后停在最后一帧。

2. Animation 事件:

为了实现动画的一些逻辑控制,比如动画结束时触发另一个动作,Animation 提供了一些与JavaScript有关的事件:

  • animationstart: 动画开始时触发的事件;
  • animationiteration: 当设置一个动画重复几次的时候,每次结束时触发的事件;
  • animationend: 整个动画结束时触发的事件。

这样我们就可以在JS中为动画 DOM 添加相应的事件了,同样webkit内核的需要添加前缀:

$('.animElem').on('animationend webkitAnimationEnd', function() {
     // 动画结束后触发的动作
});

以上代码基于KISSY,原生或者jQuery什么的同理。

DEMO,直接是线上的例子,首页的所有地标循环跳动用的就是这个知识点。

--over---

node.js 学习笔记

1. node.js 模块化

// math.js
var math = {
    add: function (a, b) {
        return a + b;
    }
};

module.exports = math;
// use.js
var math = require('./math');

console.log(math.add(1, 2));

《批判官员的尺度》

若批评不自由,则赞美无意义。

《批判官员的尺度》,先前就知道是一本不错的书,但没想到,我被序言吸引了。被序言吸引的原因有二:一来是译者引起我的好奇心;二来是我把序言看了一半的时候才意识到我看的是序言,而非正文。

本书译者何帆,毕业于武汉大学法学院、**人民大学法学院,现为最高人民法院法官。坦白来讲,我个人对于体制内的人一直有一种不认可,所以我看了译者的介绍后,心想深入体制的这样一个人,到底能把这本宣扬言论自由的书翻译成什么样子?摘抄序文中的几句话:

当然,美国宪法能够沿用至今,并被誉为“活的宪法”,靠的是最高法院大法官们与时俱进,适时根据社会情势变迁,通过灵活解释,不断赋予宪法条文新的含义。

对言论进行适当限制,当然大有必要,但是,从操作角度看,依法禁止某种言论并不可怕,可怕的是禁止者不给出明确的认定标准,想查禁什么言论,就随意给某种言论贴上禁止“标签”。

看了这些话,改变了我以前那种略有偏激的观点,证明了体制内有很多有想法、有能力、也在不断努力的人,但同时我们必须认识到,有这些人的努力,为什么依然没有突破?或者说**的宪政历程到底有没有期限?我想,除了那些你我他皆不能左右的原因外,我们每个个体需要不断的去提升自己,胡适之先生有句话说:给你自由,你不独立,仍是奴隶。即便当下的自由不是想象的自由,我们依然可以从独立做起。

好了,这个话题貌似不适合展开下去,先写这么多吧。

update

前面写过一篇对这本书译者的看法,然后不知道是事太多还是怎么的,花了很久时间才看完这本书。

看的过程,总感觉有一种力量在心底,作者那种对于国家的信任与希冀,以及民众对于公众事件的高参与度皆是我们需要学习的。我们一天总在说着正能量,但心里还是各种负能量,每段时间都要有一些公众事件,不断打破我们好不容易建立起来对于社会主义伟大事业的美好愿望,看不到改变,真的看不到,只学到了新的词语:休假式治疗、轮流发生性关系,又一个**特色。

这一界领导人上台的时候,看着CCAV新闻对于各种贪污腐败的大力报道,群民齐呼:看来这届领导班子是要狠抓贪腐了!这次我竟然很清醒,事实证明我这次的清醒的确不是装B,不出两月,上天的上天,携夫人出访的也屡试屡爽,永远都是三分钟的热度,撩拨撩拨群民多年压抑的欲望与不满,刚脱下衣服,政府说这次没吃药,下次再来吧。群民本以为久旱逢甘霖,却不料老天爷只是撒泡尿,之后就跟剧本里写的一样了,腐败不反了,CCAV也噤声了,然后民众继续积累压抑以供下一届继续撩拨。

说一切都在变好,我总感觉一切都在走下坡路,经济、就业、90后的价值观走向,更勿须提什么**与自由,这词语创造出来就是立牌坊的。

摘抄书中的几句话:

  1. 联邦主义,是美国政治权力架构的基本原则,决定了联邦政府与各州政府的权力划分。
  2. 联邦制度的一大优点在于,只要得到选民支持,任何一个州都可以成为实验室,尝试各种新兴的社会与经济实验,却不会对国家造成任何危险。
  3. 自由很重要,但新闻工作者更应该具有责任感。
  4. 知识将永远**愚昧:人民若想当家做主,必须用知识的力量武装自己。
  5. 政府必须容忍一个不断找茬的新闻界,一个顽固倔强的新闻界,一个无处不在的新闻界?
  6. 如果我们想确定一种**是否真理,就应让它在**市场的竞争中接受检验。
  7. 自由的最大威胁,是思维僵化、消极冷漠的民众。
  8. 言论的一大职能,就是将人们从非理性恐惧的桎。中解脱出来。
  9. 那些通过革命,为我们争得独立者并非懦夫。他们不是畏惧政治改革。他们不会仅为维持秩序,就牺牲人民的自由。
  10. 如果有检查言论的权力,那也应当是人民检查政府的权力,而不是政府检查人民的言论。
  11. 然而,宪法的生命力之所以能恒久延续,源自法官们在适用与解释上的不断创新,以适应制宪先贤们未能预测到的社会变迁。

愿一切真能变好!

Best way to find an item in a JavaScript array?

原文stackoverflow

1. Array.indexOf()

function include(arr,obj) {
    return (~arr.indexOf(obj));
}

该方法出自ECMAScript 5,因此IE 6、7、8不支持,所以在IE低版本下需要自己做猴子补丁:

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function (obj, fromIndex) {
        var index = fromIndex || 0;
        for(var i = index, l = this.length; i < l; i++) {
            if (this[i] == obj) {
                return i;
            }
        }
        return -1;
    };
}

其他实现方式参见原文。

2. jQuery.inArray()

直接参考官方文档即可

Chrome开发工具介绍

本文部分内容参考 浏览器开发工具的秘密,原文所有主流浏览器都有讲,范围也很宽泛,我主要针对chrome介绍一些平时经常用的功能。

1. 插件推荐:

先推荐几个方便开发的插件:

  • ColorZilla: 用于在页面上取色、网页颜色分析、甚至设置渐变颜色。
  • Window Resizer: 很方便的在各个浏览器下查看网页的效果,方便调试。
  • MeasureIt: 随时在网页上测量元素间的测试。
  • WhatFont: 再也不用打开开发工具查看字体了,鼠标点到哪里,显示哪里的字体、大小、行距。

2. 开发工具使用技巧:

  • **引用当前元素:**选中一个元素后,在控制台输入 $0 即可输出选中元素的html,同时用 $1-$4 可以选择当前元素之前的其他元素;

  • **改变CSS值:**大家基本都知道选中属性值后,通过上下键可以增减1个单位,另外,Shift + up/down 可以增减10个单位,Alt + up/down 可以增减0.1个单位,Shift + pageup/pagedown 可以增减100个单位;

  • 改变元素的 :active :hover :focus :visited 样式:在开发工具中右键点击元素选择Force Element state

  • **禁用浏览器缓存:**对于开发者,每次清楚缓存比较麻烦,可以在开发工具的右下角点击圆形齿轮,里面有个 Disable cache (while DevTools is open) 选项;

  • **格式化颜色值:**将所有的颜色值都直接转换成统一格式,同样可以按照上面的步骤找到这个选项;

  • 重新发送XHR数据: 选中请求到的数据,右键选择 Replay XHR

  • 模拟其他内核,跟上边的差不多,但感觉不太靠谱,等使用后再总结吧。

先总结这么多,有了再补充。

兴趣与职业

一旦你决定好职业,你必须全心投入工作之中,你必须爱自己的工作,千万不要有怨言,你必须穷尽一生磨练技能,这就是成功的秘诀,也是让人家敬重的关键。

《寿司之神》,关于小野二郎,关于二郎寿司的一个纪录片,但绝不仅仅是如此。小野二郎,一个将一生奉献给寿司的人,虽在盛誉之下,依然精益求精,与之对应的是,一个朴素无比,只能容纳十人的寿司店,但正是这小小的店面,顾客需要提前一个月去预约,没有小菜茶水,只有寿司,最低消费三万日币。看起来很神奇,但当你了解之后,一切又是那么理所当然。

我不了解寿司,也谈不上了解小野二郎,所以仅仅说一些我对这个纪录片的感悟。

很幸福的一件事就是你的职业刚好是你的兴趣所在,但这是何其难的一件事。或许当你把兴趣仅当做兴趣看待时,兴趣才是真正的兴趣,一旦你有幸一日,从事了一个正好是你兴趣的职业时,那这样的兴趣或多或少的会加载着生存的压力,这样兴趣就慢慢的变成事业。

Geek的数字之42

有人问:请用一句话证明你是一个geek.
答曰:42.

当时看到就蒙了,42?geek?扯淡呢吧…开通帐号这么久了,也没人正儿八经问一下42是啥意思,我说是装B你们还真信啊。

42,源自著名英国科幻小说作家道格拉斯·亚当斯所著《银河系漫游指南》,小说中讲到许多百万年前,老鼠是一种超智慧生物,它们建造了一部超级电脑深思,它们问超级电脑,生命、宇宙以及任何事情的终极答案是什么,经过一段长时间的计算,深思告诉老鼠的后人:答案是42,深思解释它只能计算出答案是什么,但答案的原因必须由另一部更高智能的电脑才能解释,而该部电脑就是地球。不料此时地球却被渥罡人毁灭了…

这差不多就是42这个神奇数字的来源了,看起来很无厘头,但没办法,就这样流传下来了,咱接着用就是。既然42象征着geek,我们两个运营者也自诩为初级入门的geek,注意不是gay!那这个公众帐号自然就应该有点geek的气息了,不是感情专家连岳,不是民族愤青李大眼,不是青年导师李开复,是一个与IT、技术、产品、互联网有关的小茶馆!

关于42就解读到这里,再扯点iOS7的东西,如果你这两天被iOS7的科技文章看得想吐,那…就再吐一点吧。

前天,苹果一年一度的WWDC(苹果电脑全球研发者大会)在加州举行,发布的产品中能稍微与咱有点关系的也就iOS7了,MacBook神马的离学生党太远,借着前不久正炒得火热的扁平化设计将取代拟物风格的趋势,几乎所有人都以这一观点吐槽或者赞美iOS7的icon,当然我也是。吐槽的说:我发现在看了真货后,非官方的设计实在是太漂亮了!果粉说:图标的美观不美观并不是最终目的,最终目的应该是系统的易用性。话说把图标搭配的漂亮点会影响系统的易用性?毫无疑问,苹果很很很牛叉,iOS7也有很多革命性的东西,很多亮点,但这样的图标的的确确是十足的槽点啊,真是如某知友所说:让Jony Ive到Dirbble逛一圈,他就知道这样的图标有多么差劲。不得不承认这种现象,小米魅族用了某种设计,然后被集体吐槽,到Apple这里,总有一批人倒戈,说什么你们不懂设计云云。

他很伟大,但一样需要批评,苹果都不急,你们这些粉急啥。我相信,苹果在秋季发布的正式版iOS7必然会有很大的改进,但那不仅仅是因为苹果多么能创新,更重要的是外界的批评与质疑,肯定与促进。

必要的名词解释:
Jony Ive—苹果公司最重要的高管之一,负责了苹果多款产品的设计,其中就包括此次的iOS7.
Dribble—聚集全球最顶点的各种设计师与作品的网站。

gulp.js:不仅仅是更快

gulp.js

如果你曾经抱怨过 Grunt 执行任务太慢,厌烦了用配置的方式去写任务,那么或许可以来尝一尝这一大杯可乐:gulp.js。

更快:

相比于 Grunt 频繁的IO操作,gulp 采用了 node 中的 stream API,速度得到了大幅度提升。简单来讲,主要是用了 fs.createReadStream 这个方法,当我们要把一个文件 copy 一份的时候,最直观的方式是先将文件所有的内容先读取到内存中,然后写入新的文件:

var fs = require('fs');

function copy(src, target) {
    fs.writeFileSync(target, fs.readFileSync(src));
}

copy('./test.txt', './test1.txt');

如果我们采用 stream 的方式,就可以这样写了:

var fs = require('fs');

function copy(src, target) {
    fs.createReadStream(src).pipe(fs.createWriteStream(target));
}

copy('./test.txt', './test2.txt');

stream 与传统方式的区别,以及它自身的特点,可以参考这本小书stream-handbook

更直观的配置:

快是 gulp 的亮点,但对我来讲,gulpfile.js 更加直观、更加贴合程序员思维的书写方式才是对我的最大吸引。

Gruntfile.js 与 gulpfile.js,一个走的是配置路线,另一个走的是编码路线,孰优孰劣,自是因人而异,至少我是更加喜欢 gulp 比较直观的编码方式,这两种方式就好比写文章时的两种工具:富文本编辑器 or Markdown,事实是很多技术人员选择了Markdown。同时,较之以前初次使用 Grunt,这次试用 gulp 的上手速度快了很多。

如下,为一段配置程序:

var gulp = require('gulp');

var sass = require('gulp-sass');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var cssmin = require('gulp-minify-css');
var changed = require('gulp-changed');
var rename = require('gulp-rename');
var clean = require('gulp-clean');

// 编译sass
gulp.task('sass', function() {

  // 只需要编译index.scss就可以了
  gulp.src('./src/*.scss')
    .pipe(sass())
    .pipe(gulp.dest('./src/'));

});

// 压缩css
gulp.task('cssmin', function() {

  gulp.src('./src/index.css')
    .pipe(rename({ suffix: '.min' }))
    .pipe(cssmin())
    .pipe(gulp.dest('./build'));

});

// 压缩js
gulp.task('jsmin', function() {

  gulp.src('./src/index.js')
    .pipe(rename({ suffix: '.min' }))
    .pipe(cssmin())
    .pipe(gulp.dest('./build'));

});

// clean
gulp.task('clean', function () {
    gulp.src('build/*', {read: false})
        .pipe(clean());
});


// 监听
gulp.task('watch', function() {
  gulp.watch('./src/**/*.js', ['jsmin']);
  gulp.watch('./src/**/*.scss', ['sass']);
});

gulp.task('default', ['clean', 'sass', 'cssmin', 'jsmin']);

结论:

目前来说, Grunt 和 gulp 各有优势,Grunt 的插件相对比较齐全,也经过了各种大小项目的历练,更加成熟,而 gulp 的快速以及更加直观的配置是其亮点,但后续插件的开发速度还要依赖社区的发展。

综上,大家可以在自己的小项目中先尝试一下 gulp,等到有比较成熟的方案后可以慢慢在大项目中推动。

以上。

随便记点什么好了

  1. http 响应头可以设置 Content-Security-Policy 这个参数,用来控制页面可以引入哪些域下的资源,可以防止被 XSS 攻击,详情参考:https://www.imququ.com/post/content-security-policy-reference.html

  2. 启动浏览器时使用 disable-web-security 这个参数可以绕过各种跨域限制,参考:http://ucren.com/blog/archives/432

  3. mysql:

    批量把一个字段值设置为另一个字段值:update tablename set name=description
    批量给某个字段+1:update tablename set score=score+1

  4. curl --head url 可以查看 url 的响应头

JavaScript-Tips

1. 扩展内置对象的原型时:

一般情况,尽量不要打猴子补丁,如有需要,最好按照下面的格式:

//Object可以是Array String Object Function等
if(typeof Object.prototype.method !== "undefined") {
  Object.prototype.method = function() {
    //方法代码
  }
}

2. 当以new操作符调用构造函数时,发生了:

  • 创建一个空对象并且this变量引用了该对象,同时还继承了该函数的原型。
  • 属性和方法被加入到this引用的对象中。
  • 新创建的对象由this所引用,并且最后隐式的返回this(如果没有显示的返回其他对象)。

当调用构造函数时未使用new操作符,会导致this指向错误(全局对象),在ES5的严格模式下,this不会指向全局对象。

3. 判断对象类型:

function isArray(obj) {
  return Object.prototype.toString.call(obj) ==== "[object Array]";
}

function isString(obj) {
  return Object.prototype.toString.call(obj) ==== "[object String]"; 
}
//其他对象同理
function classOf (obj) {
    if (obj === null) return 'Null';
    if (obj === undefined) return 'Undefined';
    return Object.prototype.toString.call(obj).slice(8, -1);
}

4. 小tips:

  • 将数字转换为字符串:n + "" // 也可以用 String(n) Number.toString()
  • 将字符传转换为数字: str - 0 // 也可以用 Number(str),前面的都比较严格,无法转换“123abc”这种的,这时候可以用 parseInt()parseFloat()
  • null 在布尔环境中转换为 false,在数字环境转换为0,在字符串环境中转换为"null"
  • undefined: 未声明的变量;已声明但未赋值的变量;不存在的对象属性。用于布尔环境时转换为 false,用于数字环境时转换为 NaN,用于字符串环境时,转换为 "undefined"

5. Object.create():

ES5 定义了Obejct.create()这个方法,它创建一个新对象,其中第一个参数是这个对象的原型。
可以通过传入 null 参数来创建一个没有原型的对性,如 var obj = Object.create(null); , obj 没有继承任何东西,也不包括任何基础方法。

在ES3中封装这个方法:

function inherit (p) {
    if (Object.create) {
        return Object.create(p);
    }
    var type = typeof p;
    if (type !== 'object' && type !== 'function') {
        return false;
    }
    var f = function () {};
    f.prototype = p;
    return new f();
}

var obj = inherit(obj1);

6. mixin obj1 and obj2:

经常要用到一个方法就是把obj2(用户自定义的配置) 与 obj1(默认配置) 进行合并,并在属性名同名的情况下将 obj1 的属性覆盖,看代码:

function mixin(obj1, obj2) {
    for (o in obj2) {
        obj1[o] = obj2[o];
    }
    return obj1;
}

var a = {a: 1, b: 2},
     b = {a: 1, b: 4, c: 5};

console.log(mixin(a, b));

7. 定义 ES5 中的 map 方法:

var map = Array.prototype.map
          ? function (a, f) { return a.map(f); }
          : function (a, f) {
                var resualts = [];
                for (var i = 0, l = a.length; i < l; i++) {
                    if (i in a) {
                        resualts[i] = f.call(null, a[i], i, a);
                    }
                }
                return resualts;
          };

JavaScript 阻止页面关闭

场景:经常会看到一些需要编辑的页面,在关闭页面时会触发一个弹窗的事件,询问用户是否确定关闭,这个事件就是今天要说的beforeunload

在 jQuery 中提供了一个叫unload的事件,号称这样用:

$(window).unload(function() {
     return '确定要关闭?';
});

但实际上经测试这玩意不靠谱啊,不信你试试,社区没人吐槽这事吗....后来发现jQuery提供的事件叫beforeunload,奇怪的是在jQuery的官网里是搜不到这个API,但是能搜到unload...jQuery封装的这个方法跟原生的JS实现其实差不多,甚至说原生的JS更好用一些,jQuery中是这样定义的:

beforeunload: {
      postDispatch: function( event ) {

      // Support: Firefox 20+
      // Firefox doesn't alert if the returnValue field is not set.
      if ( event.result !== undefined ) {
            event.originalEvent.returnValue = event.result;
       }
    }
}

// 使用 beforeunload
$(window).bind('beforeunload', function() {
      return 1;
})

实际上在原生的JS中使用这个事件是非常简单的:

window.addEventListener('beforeunload', function (e) {
       return '您正在编辑的 issue 还没有提交,确定要离开?';
});

事实上我本来想实现的功能是关闭页面时弹出自己自定义的浮层,样式都写好了:
1
然后我想的方式,是触发这个事件时,阻止事件的默认行为(不显示默认的系统框,但不关闭页面),显示自定义的框,然后点击「确认离开」后关闭页面。理想是丰满的,现实是残酷的。遇到的问题:

  1. 无法实现关闭页面时不显示默认的系统框,目前无解,后面的工作无法进行,所以如果见过哪个网站的这种框是自定义的,求通知一下...
    PS:开发者无法自定义这个默认框的样式。
  2. 点击「确认离开」时不再重复触发这个事件。刚才想的方案是定义一个参数,通过判断参数值确认是否触发beforeunload事件:
var close = doc.querySelector('.close'),
     isSure = false;

$(window).bind('beforeunload', function(e) {
    if (!isSure) {
        return '确认关闭?';
    }
})

close.addEventListener('click', function() {
    isSure = true;
})

但是现在第一个问题解决不了,后面想的就是扯淡...如果有什么思路,还望指明哈~

CSS 编写指南

注:本文来自译文

通用 CSS 笔记、建议与指导


原文

在参与规模庞大、历时漫长且参与人数众多的项目时,所有开发者遵守如下规则极为重要:

  • 保持 CSS 便于维护
  • 保持代码清晰易懂
  • 保持代码的可拓展性

为了实现这一目标,我们要采用诸多方法。

本文档第一部分将探讨语法、格式以及分析 CSS 结构;第二部分将围绕方法论、思维框架以及编写与规划 CSS 的态度。

目录

第一部分

第二部分


CSS 文档分析

无论编写什么文档,我们都应当尽力维持统一的风格,包括统一的注释、统一的语法与统一的命名规范。

总则

尽量将行宽控制在 80 字节以下。渐变(gradient)相关的语法以及注释中的 URL 等可以算作例外,毕竟这部分我们也无能为力。

我倾向于用 4 个空格而非 Tab 缩进,并且将声明拆分成多行。

单一文件与多文件

有人喜欢在一份文件文件中编写所有的内容,而我在迁移至 Sass 之后开始将样式拆分成多个小文件。这都是很好的做法。无论你选择哪种,下文的规则都将适用,而且如果你遵守这些规则的话你也不会遇到什么问题。这两种写法的区别仅仅在于目录以及区块标题。

目录

在 CSS 的开头,我会写一份目录,例如:

/*------------------------------------*\
    $CONTENTS
\*------------------------------------*/
/**
 * CONTENTS............You’re reading it!
 * RESET...............Set our reset defaults
 * FONT-FACE...........Import brand font files
 */

这份目录可以告诉其他开发者这个文件中具体含有哪些内容。这份目录中的每一项都与其对应的区块标题相同。

如果你在维护一份单文件 CSS,对应的区块将也在同一文件中。如果你是在编写一组小文件,那么目录中的每一项应当对应相应的 @include 语句。

区块标题

目录应当对应区块的标题。请看如下示例:

/*------------------------------------*\
    $RESET
\*------------------------------------*/

区块标题前缀 $ 可以让我们使用 [Cmd|Ctrl]+F 命令查找标题名的同时将搜索范围限制在区块标题中

如果你在维护一份大文件,那么在区块之间空 5 行,如下:

/*------------------------------------*\
    $RESET
\*------------------------------------*/
[Our
reset
styles]





/*------------------------------------*\
    $FONT-FACE
\*------------------------------------*/

在大文件中快速翻动时这些大块的空档有助于区分区块。

如果你在维护多份、以 @include 连接的 CSS 的话,在每份文件头加上标题即可,不必这样空行。

代码顺序

尽量按照特定顺序编写规则,这将确保你充分发挥 CSS 缩写中第一个 C 的意义:cascade,层叠。

一份规划良好的 CSS 应当按照如下排列:

  1. Reset 万物之根源
  2. 元素类型 没有 class 的 h1ul
  3. 对象以及抽象内容 最一般、最基础的设计模式
  4. 子元素 由对象延伸出来的所有拓展及其子元素
  5. 修补 针对异常状态

如此一来,当你依次编写 CSS 时,每个区块都可以自动继承在它之前区块的属性。这样就可以减少代码相互抵消的部分,减少某些特殊的问题,组成更理想的 CSS 结构。

关于这方面的更多信息,强烈推荐 Jonathan Snook 的 SMACSS

CSS 规则集分析

[selector]{
    [property]:[value];
    [<- Declaration ->]
}

[选择器]{
    [属性]:[值];
    [<- 声明 ->]
}

编写 CSS 样式时,我习惯遵守这些规则:

  • class 名称以连字符(-)连接,除了下文提到的 BEM 命名法;
  • 缩进 4 空格;
  • 声明拆分成多行;
  • 声明以相关性顺序排列,而非字母顺序;
  • 有前缀的声明适当缩进,从而对齐其值;
  • 缩进样式从而反映 DOM;
  • 保留最后一条声明结尾的分号。

例如:

.widget{
    padding:10px;
    border:1px solid #BADA55;
    background-color:#C0FFEE;
    -webkit-border-radius:4px;
       -moz-border-radius:4px;
            border-radius:4px;
}
    .widget-heading{
        font-size:1.5rem;
        line-height:1;
        font-weight:bold;
        color:#BADA55;
        margin-right:-10px;
        margin-left: -10px;
        padding:0.25em;
    }

我们可以发现,.widget-heading.widget 的子元素,因为前者比后者多缩进了一级。这样通过缩进就可以让开发者在阅读代码时快速获取这样的重要信息。

我们还可以发现 .widget-heading 的声明是根据其相关性排列的:.widget-heading 是行间元素,所以我们先添加字体相关的样式声明,接下来是其它的。

以下是一个没有拆分成多行的例子:

.t10    { width:10% }
.t20    { width:20% }
.t25    { width:25% }       /* 1/4 */
.t30    { width:30% }
.t33    { width:33.333% }   /* 1/3 */
.t40    { width:40% }
.t50    { width:50% }       /* 1/2 */
.t60    { width:60% }
.t66    { width:66.666% }   /* 2/3 */
.t70    { width:70% }
.t75    { width:75% }       /* 3/4*/
.t80    { width:80% }
.t90    { width:90% }

在这个例子(来自inuit.css’s table grid system)中,将 CSS 放在一行内可以使得代码更紧凑。

命名规范

一般情况下我都是以连字符(-)连接 class 的名字(例如 .foo-bar 而非 .foo_bar.fooBar),不过在某些特定的时候我会用 BEM(Block, Element, Modifier)命名法。

BEM 命名法可以使得选择器更规范,更清晰,更具语义。

该命名法按照如下格式:

.block{}
.block__element{}
.block--modifier{}

其中:

  • .block 代表某个基本的抽象元素;
  • .block__element 代表 .block 这一整体的一个子元素;
  • .block--modifier 代表 .block 的某个不同状态。

打个比方:

.person{}
.person--woman{}
    .person__hand{}
    .person__hand--left{}
    .person__hand--right{}

这个例子中我们描述的基本元素是一个人,然后这个人可能是一个女人。我们还知道人拥有手,这些是人体的一部分,而手也有不同的状态,如同左手与右手。

这样我们就可以根据亲元素来划定选择器的命名空间并传达该选择器的职能,这个选择器是一个子元素(__)还是亲元素的不同状态(--)?

由此,.page-wrapper 是一个独立的选择器。这是一个符合规范的命名,因为它不是其它元素的子元素或其它状态;然而 .widget-heading 则与其它对象有关联,它应当是 .widget 的子元素,所以我们应当将其重命名为 .widget__heading

BEM 命名法虽然不太好看,而且相当冗长,但是它使得我们可以通过名称快速获知元素的功能和元素之间的关系。与此同时,BEM 语法中的重复部分非常有利于 gzip 的压缩算法。

无论你是否使用 BEM 命名法,你都应当确保 class 命名得当,力保一字不多、一字不少;将元素命名抽象化以提高复用性(例如 .ui-list.media)。由此延伸出去的元素命名则要尽量精准(例如 .user-avatar-link)。不用担心 class 名的数量或长度,因为写得好的代码 gzip 也能有效压缩。

HTML 中的 class

为了确保易读性,在 HTML 标记中用两个空格隔开 class 名,例如:

<div class="foo--bar  bar__baz">

增加的空格应当可以使得在使用多个 class 时更易阅读与定位。

JavaScript 钩子

**千万不要把 CSS 样式用作 JavaScript 钩子。**把 JS 行为与样式混在一起将无法对其分别处理。

如果你要把 JS 和某些标记绑定起来的话,写一个 JS 专用的 class。简单地说就是划定一个前缀 .js- 的命名空间,例如 .js-toggle.js-drag-and-drop。这意味着我们可以通过 class 同时绑定 JS 和 CSS 而不会因为冲突而引发麻烦。

<th class="is-sortable  js-is-sortable">
</th>

上面的这个标记有两个 class,你可以用其中一个来给这个可排序的表格栏添加样式,用另一个添加排序功能。

I18n

虽然我(该 CSS Guideline 文档原作者 Harry Roberts)是个英国人,而且我一向拼写 colour 而非 color,但是为了追求统一,我认为在 CSS 中用美式拼法更佳。CSS 以及其它多数语言都是以美式拼法编写,所以如果在 .colour-picker{} 中写 color:red 就缺乏统一性。我以前主张同时用两种拼法,例如:

.color-picker,
.colour-picker{
}

但是我最近参与了一份规模庞大的 Sass 项目,这个项目中有许多的颜色变量(例如 $brand-color$highlight-color 等等),每个变量要维护两种拼法实在辛苦,要查找并替换时也需要两倍的工作量。

所以为了统一,把所有的 class 与变量都以你参与的项目的惯用拼法命名即可。

注释

我使用行宽不超过 80 字节的块状注释:

/**
 * This is a docBlock style comment
 * 
 * This is a longer description of the comment, describing the code in more
 * detail. We limit these lines to a maximum of 80 characters in length.
 * 
 * We can have markup in the comments, and are encouraged to do so:
 * 
   <div class=foo>
       <p>Lorem</p>
   </div>
 * 
 * We do not prefix lines of code with an asterisk as to do so would inhibit
 * copy and paste.
 */


/**
 * 这是一个文档块(DocBlock)风格的注释。
 *
 * 这里开始是描述更详细、篇幅更长的注释正文。当然,我们要把行宽控制在 80 字以内。
 *
 * 我们可以在注释中嵌入 HTML 标记,而且这也是个不错的办法:
 *
    <div class=foo>
        <p>Lorem</p>
    </div>
 *
 * 如果是注释内嵌的标记的话,在它前面不加星号,否则会被复制进去。
 */

在注释中应当尽量详细描述代码,因为对你来说清晰易懂的内容对其他人可能并非如此。每写一部分代码就要专门写注释以详解。

注释的拓展用法

注释有许多很先进的用法,例如:

  • 准修饰选择器
  • 代码标签
  • 继承标记

准修饰选择器

你应当避免过分修饰选择器,例如如果你能写 .nav{} 就尽量不要写 ul.nav{}。过分修饰选择器将影响性能,影响 class 复用性,增加选择器私有度。这些都是你应当竭力避免的。

不过有时你可能希望告诉其他开发者 class 的使用范围。以 .product-page 为例,这个 class 看起来像是一个根容器,可能是 html 或者 body 元素,但是仅凭 .product-page 则无法判断。

我们可以在选择器前加上准修饰(即将前面的类型选择器注释掉)来描述我们规划的 class 作用范围:

/*html*/.product-page{}

这样我们就能准确获知该 class 的作用范围而不会影响复用性。

其它例子如:

/*ol*/.breadcrumb{}
/*p*/.intro{}
/*ul*/.image-thumbs{}

这样我们就能在不影响代码私有度的前提下获知 class 作用范围。

代码标签

如果你写了一个新规则的话,可以在它上面加上标签,例如:

/**
 * ^navigation ^lists
 */
.nav{}

/**
 * ^grids ^lists ^tables
 */
.matrix{}

这些标签可以使得其他开发者快速找到相关代码。如果一个开发者需要查找和列表相关的部分,他只要搜索 ^lists 就能快速定位到 .nav.matrix 以及其它相关部分。

继承标记

将面向对象的思路用于 CSS 编写的话,你经常能找到两部分 CSS 密切相关(其一为基础,其一为拓展)却分列两处。我们可以用继承标记来在原元素和继承元素之间建立紧密联系。这些在注释中的写法如下:

在元素的基本样式中:

/**
 * Extend `.foo` in theme.css
 */
 .foo{}

在元素的拓展样式中:

/**
 * Extends `.foo` in base.css
 */
 .bar{}

这样一来我们就能在两块相隔很远的代码间建立紧密联系。


编写 CSS

之前的章节主要探讨如何规划 CSS,这些都是易于量化的规则。本章将探讨更理论化的东西,也将探讨我们的态度与方法。

编写新组件

编写新组件时,要在着手处理 CSS 之前写好 HTML 部分。这可以令你准确判断哪些 CSS 属性可以继承,避免重复浪费。

先写标记的话,你就可以关注数据、内容与语义,在这之后再添加需要的 class 和 CSS 样式。

面向对象 CSS

我以面向对象 CSS 的方式写代码。我把组件分成结构(对象)与外观(拓展)。正如以下分析:

.room{}

.room--kitchen{}
.room--bedroom{}
.room--bathroom{}

我们在屋子里有许多房间,它们都有共同的部分:它们都包含地板、天花板、墙壁和门。这些共享的部分我们可以放到一个抽象的 .room{} class 中。不过我们还有其它与众不同的房间:一个厨房可能有地砖,卧室可能有地毯,洗手间可能没有窗户但是卧室会有,每个房间的墙壁颜色也许也会不一样。面向对象 CSS 的思路使得我们把相同部分抽象出来组成结构部分,然后用更具体的 class 来拓展这些特征并添加特殊的处理方法。

所以比起编写大量的特殊模块,应当努力找出这些模块中重复的设计模式并将其抽象出来,写成一个可以复用的 class,将其用作基础然后编写其它拓展模块的特殊情形。

当你要编写一个新组件时,将其拆分成结构和外观。编写结构部分时用最通用 class 以保证复用性,编写外观时用更具体的 class 来添加设计方法。

布局

所有组件都不要声明宽度,而由其亲元素或格栅系统来决定。

坚决不要声明高度。高度应当仅仅用于尺寸已经固定的东西,例如图片和 CSS Sprite。在 puldiv 等元素上不应当声明高度。如果需要的话可以写 line-height,这个更加灵活。

格栅系统应当当作书架来理解。是它们容纳内容,而不是把它们本身当成内容装起来,正如你先搭起书架再把东西放进去。比起声明它们的尺寸,把格栅系统和元素的其它属性分来开处理更有助于布局,也使得我们的前端工作更高效。

你在格栅系统上不应当添加任何样式,他们仅仅是为布局而用。在格栅系统内部再添加样式。在格栅系统中任何情况下都不要添加盒模型相关属性。

UI 尺寸

我用很多方法设定 UI 尺寸,包括百分比,pxemrem 以及干脆什么都不用。

理想情况下,格栅系统应当用百分比设定。如上所述,因为我用格栅系统来固定栏宽和页宽,所以我可以不用理会元素的尺寸。

我用 rem 定义字号,并且辅以 px 以兼容旧浏览器。这可以兼具 em 和 px 的优势。下面是一个非常漂亮的 Sass Mixin,假设你在别处声明了基本字号(base-font-size)的话,用它就可以生成 rem 以及兼容旧浏览器的 px。

@mixin font-size($font-size){
    font-size:$font-size +px;
    font-size:$font-size / $base-font-size +rem;
}

我只在已经固定尺寸的元素上使用 px,包括图片以及尺寸已经用 px 固定的 CSS Sprite。

字号

我会定义一些与格栅系统原理类似的 class 来声明字号。这些 class 可以用于双重标题分级,关于这点请阅读 Pragmatic, practical font-sizing in CSS

简写

CSS 简写应当谨慎使用。

编写像 background:red; 这样的属性的确很省事,但是你这么写的意思其实是同时声明 background-image:none; background-position:top left; background-repeat: repeat; background-color:red;。虽然大多数时候这样不会出什么问题,但是哪怕只出一次问题就值得考虑要不要放弃简写了。这里应当改为 background-color:red;

类似的,像 margin:0; 这样的声明的确简洁清爽,但是还是应当尽量写清楚。如果你只是想修改底边边距,就要具体一些,写成 margin-bottom:0;

反过来,你需要声明的属性也要写清楚,不要因为简写而波及其它属性。例如如果你只想改掉底部的 margin,那就不要用会把其它边距也清零的 margin:0

简写虽然是好东西,但是注意切勿滥用。

ID

在我们开始处理选择器之前,牢记这句话:

在 CSS 里坚决不要用 ID。

在 HTML 里 ID 可以用于 JS 以及锚点定位,但是在 CSS 里只要用 class,一个 ID 也不要用。

Class 的优势在于复用性,而且私有度也并不高。私有度非常容易导致问题,所以将其降低就尤为重要。ID 的私有度是 class 的 255 倍,所以在 CSS 中坚决不要使用。

选择器

务必保持选择器简短高效。

通过页面元素位置而定位的选择器并不理想。例如 .sidebar h3 span{} 这样的选择器就是定位过于依赖相对位置,所以把 span 移到 h3 和 sidebar 外面时就很难保持其样式。

结构复杂的选择器将会影响性能。选择器结构越复杂(如 .sidebar h3 span 为三层,.content ul p a 是四层),浏览器的消耗就越大。

尽量使得样式不依赖于其定位,尽量保持选择器简洁清晰。

作为一个整体,选择器应当尽量简短(例如只有一层结构),但是 class 名则不应当过于简略,例如 .user-avatar 就远比 .usr-avt 好。

**牢记:**class 无所谓是否语义化;应当关注它们是否合理。不要强调 class 名要符合语义,而要注重使用合理且不会过时的名称。

过度修饰的选择器

由前文所述,过度修饰的选择器并不理想。

过度修饰的选择器是指像 div.promo 这样的。很可能你只用 .promo 也能得到相同的效果。当然你可能偶尔会需要用元素类型来修饰 class(例如你写了一个 .error 而且想让它在不同的元素类型中显示效果不一样,例如 .error{ color:red; } div.error{ padding:14px;}),但是大多数时候还是应当尽量避免。

再举一个修饰过度的选择器例子,ul.nav li a{}。如前文所说,我们马上就可以删掉 ul 因为我们知道 .nav 是个列表,然后我们就可以发现 a 一定在 li 中,所以我们就能将这个选择器改写成 .nav a{}

选择器性能

虽然浏览器性能日渐提升,渲染 CSS 速度越来越快,但是你还是应当关注效率。使用间断、没有嵌套的选择器,不把全局选择器(*{})用作核心选择器,避免使用日渐复杂的 CSS3 新选择器可以避免这样的问题。

译注,核心选择器:浏览器解析选择器为从右向左的顺序,最右端的元素是样式生效的元素,是为核心选择器。

使用 CSS 选择器的目的

比起努力运用选择器定位到某元素,更好的办法是直接给你想要添加样式的元素直接添加一个 class。我们以 .header ul{} 这样一个选择器为例。

假定这个 ul 就是这个网站的全站导航,它位于 header 中,而且目前为止是 header 中唯一的 ul 元素。.header ul{} 的确可以生效,但是这样并不是好方法,它很容易过时,而且非常晦涩。如果我们在 header 中再添加一个 ul 的话,它就会套用我们给这个导航部分写的样式,哪怕我们设想的不是这个效果。这意味着我们要么要重构许多代码,要么给后面的 ul 新写许多样式来抵消之前的影响。

你的选择器必须符合你要给这个元素添加样式的原因。思考一下,「我定位到这个元素,是因为它是 .header 下的 ul,还是因为它是我的网站导航?」这将决定你应当如何使用选择器。

确保你的核心选择器不是类型选择器,也不是高级对象或抽象选择器。例如你在我们的 CSS 中肯定找不到诸如 .sidebar ul{} 或者 .footer .media{} 这样的选择器。

表达清晰:直接找到你要添加样式的元素,而非其亲元素。不要想当然地认为 HTML 不会改变。用 CSS 直接命中你需要的元素,而非投机取巧。

完整内容请参考我的文章 Shoot to kill; CSS selector intent

!important

只在起辅助作用的 class 上用 !important。用 !important 提升优先级也可以,例如如果你要让某条规则一直生效的话,可以用 .error{ color:red!important; }

避免主动使用 !important。例如 CSS 写得很复杂时不要用它来取巧,要好好整理并重构之前的部分,保持选择器简短并且避免用 ID 将效果拔群。

魔数与绝对定位

魔数(Magic Number)是指那些「凑巧有效果」的数字,这东西非常不好,因为它们只是治标不治本而且缺乏拓展性。

例如 .dropdown-nav li:hover ul{ top:37px; } 把下拉菜单移动下来远非良策,因为这里的 37px 就是个魔数。37px 会生效的原因是因为这时 .dropbox-nav 碰巧高 37px 而已。

这时你应该用 .dropdown-nav li:hover ul{ top:100%; },也即无论 .dropbox-down 多高,这个下拉菜单都会往下移动 100%。

每当你要在代码中放入数字的时候,请三思而行。如果你能用一个关键字(例如 top:100% 意即「从上面拉到最下面」)替换之,或者有更好的解决方法的话,就尽量避免直接出现数字。

你在 CSS 中留下的每一个数字,都是你许下而不愿遵守的承诺。

条件判断

专门为 IE 写的样式基本上都是可以避免的,唯一需要为 IE 专门处理的是为了处理 IE 不支持的内容(例如 PNG)。

简而言之,如果你重构 CSS 的话,所有的布局和盒模型都不用额外兼容 IE。也就是说你基本上不用 <!--[if IE 7]> element{ margin-left:-9px; } < ![endif]--> 或者类似的兼容 IE 的写法。

Debugging

如果你要解决 CSS 问题的话,先把旧代码拿掉再写新的。如果旧的 CSS 中有问题的话,写新代码是解决不了的。

把 CSS 代码和 HTML 部分删掉,直到没有 BUG 为止,然后你就知道问题出在哪里了。

有时候写上一个 overflow:hidden 或者其它能把问题藏起来的代码的确效果立竿见影,但是 overflow 方面可能根本就没问题。所以要治本,而不是单纯治标

CSS 预处理器

我用 Sass。使用时应当灵活运用。用 Sass 可以令你的 CSS 更强大,但是不要嵌套得太复杂。在 Vanilla CSS 中,只在必要的地方用嵌套即可,例如:

.header{}
.header .site-nav{}
.header .site-nav li{}
.header .site-nav li a{}

这样的写法在普通 CSS 里完全用不到。以下为不好的 Sass 写法:

.header{
    .site-nav{
        li{
            a{}
        }
    }
}

如果你用 Sass 的话,尽量这么写:

.header{}
.site-nav{
    li{}
    a{}
}

从入门者的角度:怎么学习前端

最近,一直有学弟在问,前端的知识体系应该怎么学,那么从一个入门者的角度,做一些个人的总结吧。恰好明天答应师姐试做一下今年的前端笔试题,今天写下来也算是为了避嫌了 😄

不谈前端,不谈某个具体的知识领域,在我看来,大学生必备的一个能力是「筛选信息」。具体来讲,当你想要涉及某个领域时,你至少能够通过书籍、网络对这个领域做个大概了解,在这样的基础上你再去询问那些相对专业一点的人才能有所收获。

筛选信息的方式有很多种:读书、互联网、交流等,这其中最重要的又属「利用互联网」。对于一个初学者来说,网络能给你很大的帮助,现如今,网上的资源俯拾皆是,当听到你个陌生的概念时,你应当有搜索的意识。通常来说,你付出的成本越低,获得的价值也会相对越少。搜索即是如此,键入关键字,敲击回车键,所以要想获得更有价值的信息,必然又会回到筛选信息上。怎么筛选?没有多少技巧,学会使用工具,熟能生巧。工具如谷歌、知乎和相关的论坛。

OK,回到正题:怎么系统的学习前端知识?如果你对前端有一些了解,你再看下面的内容。

打好基础:

对于一个初学者来说,打好基础最重要,需要避免的一个误区就是刚开始学时就拿了一本《用JS实现N种效果》、到处不分青红皂白的复制粘贴其他网站的代码,切记这个阶段最重要的是基础,具体来说,你或许可以按照以下的顺序学习:

  1. 了解并掌握 HTML 语义化;
  2. 熟练使用 CSS 的常用属性值,掌握一些重要概念:盒模型、常用布局等;
  3. 熟悉掌握 JavaScript 的常用语法以及 DOM 操作。

通常这方面的面试笔试题会很多的,例如:

  • 给你一个解析后的HTML样式(例如一个表格、一个列表),然后写出符合语义的HTML标签结构。
  • 简述 CSS 中的 position 属性都有哪些值,不同的值在布局时有哪些特点?
  • 写一个兼容 IE6+ 的 getElementsByClassName() 方法,这个问题解法诸多,坑也很多。
  • 说一些你所知道的 IE在CSS上的 Bug 以及解决方法。
  • 简述DOM事件模型,并描述IE低版本与其他浏览器的差异,再尝试写一个兼容IE6+的 addEventListener() 方法。

诸如此类的,多是基础问题,但很多人过不了这一关,所以基础很重要,推荐几个资源:

然后结合实践,多实践书上的代码,多做总结,最好能记录在博客中。无论你信不信,这些基础在笔试面试中出现的几率很高,闭包、DOM操作、基本布局、常见的 IE bug...所以很多东西都要反复去看,加深理解。

实践 + 深入 + 拓展:

实践:一方面去实践代码,钻研某个知识点;另一方面做一些个人的小项目,做出一些简单的成品。

深入:对于概念的深入理解,如原型、闭包。

拓展:了解并选择性的深入理解下面的知识点,

  • 新技术:HTML5、CSS3、ECMAScript5、响应式,这里需要一定深入的学习;
  • 前端常用的库:jQuery、Sass;
  • 模块加载,AMD?CMD?sea.js or require.js;
  • 前端构建工具:grunt,gulp,Yeoman;
  • 后端技术:Commanjs,Node.js...
  • 了解前端的各种 MVV* 框架,如Angular、Backbone...
    ...

无论你的技术处于哪个阶段,视野是最重要的,关注一些业界牛人的微博、博客,从头到尾的阅读感兴趣的博客文章,在 github 上关注相关的人,找一些比较感兴趣的 repo,阅读别人的代码,都是很好的方式。

推荐几个博客吧:

-----完-----

边看边学:初识MongoDB

对于数据库我并没有了解多少,之前接触过MySQL,但很多东西只是浅尝辄止,最多是了解一些SQL语句、关联表的设计、索引诸如此类的。近来一直想把后端的技术补上来,因此就从Mongo开始了,毫无疑问,我们都喜欢新的炫的东西,那么分布式、NoSQLJSON格式这些叠加起来的MongoDB刚好符合胃口,于是乎先选一本好书:《MongoDB 实战》,然后就可以步履蹒跚的上路了。

初识当然是要讲环境的搭建了,对于后台想关的技术,原则上使用Ubuntu会省去很多麻烦,但因为平时要照顾IE,又懒得再去搞双系统,所以就硬着头皮在Windows上搞了,过程倒也还好,没有想象中的那么艰辛,大体步骤如下:

  1. 下载MongoDB: 平时学习使用,下载32位和64位都无妨;
  2. 将下载好的zip解压到D:/下,大概是这个样子D:/mongodb
  3. 建立数据库目录:D:/mongodb/data
  4. 建立日志目录: D:/mongodb/logs/mongo.log
  5. 添加环境变量: 我的电脑-属性-高级-环境变量-系统变量中的path,加上D:/mongodb/bin
  6. 启动服务:在控制台中输入 mongod.exe --dbpath=D:\MongoDB\data,注:dbpath指的就是数据库的路径;
  7. 启动shell: 重开一个控制台输入mongo,然后就可以连上数据库做一些操作了;

这样使用起来比较麻烦,每次都需要开两个控制台,输入长长的命令,windows service可以解决这个问题:

在控制台中输入:
mongod.exe --dbpath=D:\mongodb\data --logpath=D:\mongodb\logs\mongo.log --install

这样以后在控制台中输入net start mongodb就可以启动服务了,然后输入mongo启动shell就可以操作了。如下图所示:

基本的安装过程就这么多,也没多少坑,运气好的话还是蛮顺利的。

MongoDB的优势的话,这方面的文章数不胜数,我个人理解最大的不同就是开发者不需要在schema上花费太多的精力,也不用因为要添加一个字段而消耗大量的沟通成本,另一方面,MongoDB本身就是为web量身定做,在分布式的支持上会比MySQL便利很多。

没有什么技术类的问题,纯属一些个人的记录。

浅谈字体

设计师的生活是战斗的生活,为对抗丑陋而战斗。 ——《传奇字体 Helvetica》

昨日偶然觅得一博客,主题是字体、设计、排版此类,连读了有十多篇文章,顺便参阅了维基资料,算是对字体有个粗浅的认识了,借此刚好给大家简单介绍一下。

字体分类很多,但最常接触的就是衬线类和无衬线类字体。衬线指的是字形笔画末端的装饰细节部分。传统意义上,衬线字体被认为易于阅读,多用于正文印刷,而无衬线多用于标题或短篇文章。但在计算机领域,因为显示器的分辨率问题,衬线字体在显示器上的显示效果不好,所以无论是windows还是Mac都选择了无衬线字体作为系统默认字体,同时大多数网页的字体也都是无衬线字体。

在西文字母中,最常见的无衬线字体当属Helvetica和Arial了,其中前者是由米耶丁格和爱德华德·霍夫曼于1957在瑞士设计的,在80、90年代无尽风靡,海报、指示牌、地铁站无处不在,其中Mac的默认字体就是Helvetica。而Arial的出身就没有如此华丽了,1990年代左右,随着Adobe在苹果和微软的压力之下放弃对PostScript的垄断(PS包含有Helvetica、Times等字体),数种PostScript的克隆品纷纷面市,其中就包括了作为Helvetica替代品的Arial,两者极其相似。此后,windows3.1采用了相比Helvetica便宜很多的Arial,而Mac则选择了原版的Helvetica,题外话:微软和苹果的品味高下立现!之后,windows的盛行也使Arial取代Helvetica的最受欢迎字体位置。2006年8月,Helvetica 拥有者 Linotype 被 Arial 开发者 Monotype 收购。

在汉字中,无衬线字体即黑体,衬线字体即宋体。在英文中无衬线字体的写法是sans serif,sans:无,serif:衬线。 关于字体,我特想了解在各个印刷方式下一套字体完整的制作过程,等我了解了,咱一块扫盲。

最后,关于字体推荐点东西:

文中的博客:Type is Beautiful
书:《西文字体的故事》,排版很漂亮,也不是贵(30元);还有一本《字体故事:西文字体的美丽传说》,很贵(88元),买不起。
电影:《传奇字体Helvetica》,摘要里的那句话就是出自此纪录片的。

IE hack? forget it!

IE hack? forget it!


IE hack,每个前端同学都避免不了的东西,你应该很了解下面的写法:

color: red\9\0; // ie9
color: red\0;  // ie8 & 9
*color: red;  // ie6&7
_color: red;  // ie6

每次碰到不同的 bug 我们总要考虑用那种 hack 处理,今天在 less 中写了一个 color: red\0 这样的 hack 时,打包失败,理论上这是 gulp-less 的 bug,不过问题是在这个 bug 之下我该怎么继续 hack,思考之后觉得这样的 hack 真的是烦透了,这样的解决方案也一定是不够靠谱的,相比来说,IE 条件注释会靠谱很多,那么借助 IE 的条件注释,hack 这件事简单了许多,如下:

<!--[if lt IE 7]>  <html class="ie ie6 lte9 lte8 lte7"> <![endif]-->
<!--[if IE 7]>     <html class="ie ie7 lte9 lte8 lte7"> <![endif]-->
<!--[if IE 8]>     <html class="ie ie8 lte9 lte8"> <![endif]-->
<!--[if IE 9]>     <html class="ie ie9 lte9"> <![endif]-->
<!--[if gt IE 9]>  <html> <![endif]-->
<!--[if !IE]><!--> <html> <!--<![endif]-->

如此的话,虽说 html 的源文件稍微有点恶心,好在 IE 条件注释在其他浏览器压根不会显示,所以这点恶心是可以接受的,之后我们再写 IE hack 就简单了许多,没有了奇葩的语法,csshint 也不会检测出什么问题,hack 写起来更加直观。

所以,忘掉那一堆 IE hack 吧!


扩展阅读:

洗牙一二事

不知道念叨了多少次要去洗牙洗牙,上周末终于去洗了,其实小时候牙齿就不好,自己也不太注意,牙龈出血一直很严重,是那种吃苹果牙龈都会出血的,所以说,娇贵嘛...洗牙的时候有点小小的感慨,记录一下:

  • 洗牙主要是洗掉牙垢,在牙龈跟牙齿接轨的地方,然后洗牙是无法洗掉牙齿上的黄斑,听医生说这个是因为小时候喝的水氟含量比较高而导致的,可以通过美牙干掉,但是比较贵。
  • 关于牙龈出血,大多时候会以为牙龈出血是缺什么东西,事实上跟这个肯定有关系的,但如果严重的话,不妨关注一下是不是因为牙垢引起的,我的就是,牙垢压迫了牙龈的生长甚至萎缩,所以非常容易出血,话说洗牙之后这几天还真的有好转唉。
  • 关于价格:我去的是杭州口腔医院,价格有200多,400多,600多... 因为我的情况比较严重,所以医生果断告诉我200多的是洗不干净的,200、400的区别在于强度,400、600、800的区别在于药水的舒适度,贵一点的药水洗牙过程相对会舒服一点。对于牙齿不好又是第一次洗牙的人,真的蛮痛苦的。
  • 爱护牙齿:一定要爱护牙齿,认真刷牙,坚持每年都去洗一下牙齿,当然一定要去正规的医院,防止传染病什么的。

关于洗牙,就说这么些吧。


小吐槽:

3月份再次来杭州实习了,不过一个月的时间过去了,感觉很不充实,一来团队各种重组,师兄(姐?)去了其他项目组,才磨合一个月又得重新来过,不开心;二来这一个月没做出什么成绩,浑浑噩噩的不知道是什么状况。

必须要改变的。

github 与 博客

风景

如今用github写博客的人越来越多,尤其是在程序员的圈子里,对我个人来讲,这的确是个很便利的东西,下面就介绍一下用github写博客主要的两种方式:

1. jeklly/octopress + github pages:

这种方式是最常见的,我也试过一段时间,虽然说用 markdown 听起来逼格很高的样子,但是每次要在本地 rake deploy 实在是不爽,而且刚开始配置的时候还很麻烦,所以我很早就明智的放弃了这种方式。

2. issues (+ github pages):

在issues里写博客的鼻祖是谁我不了解,我只知道「玉伯」用的比较早,然后下面的评论也很有料,而我现在也是用这种方式,说一下有哪些特点:

  • 编辑简单快速:这是最重要的了,随时可以新开issue写博客,也可以即时修改,方便轻巧;
  • 添加图片方便:新开一个issue后下面会有一个插入图片的功能,添加图片很方便;
  • 体验很好:无论是编辑文章、阅读文章或者评论功能,用起来体验都比较爽,谁用谁知道;
  • 数据安全:记得之前用wordpress托管在一个国外的免费服务商那里,博客被无缘封了我就不说了,数据差点没导出来,虽然说咱也没写出什么有料的东西;
  • 不用备份,速度也不错:访问速度不会受其他因素影响,也不存在被挡在墙外的情况。

有优点当然也有缺点:

  • 过于小众:只有程序员才用这个,不过程序员的圈子也就是程序员了,这点事也不算事;
  • 订阅问题:RSS订阅是不靠谱了,可以选择watch一下项目,不过要是博主哪天抽风,你的timeline会被刷爆的,据说我的朋友有一次收到 github 50多封邮件,因为那天我重新整理了issue列表,然后就被取消关注了~
  • 自动保存:github在线编辑不提供自动保存,这一点还是让我很胆战心惊的,不过胆子是练粗来的。

还有一些tips分享一下:

1. 标签: github issues里本身就有这个功能,你可以很方便的管理文章标签,而且还有不同的颜色标注;

**2. 个人域名:**这个就要结合github pages来用了,可以参考github page

我目前设置的是sobear.me跳转到我的首页,然后sobear.me/blog跳转到issues列表,前者参看文档很容易实现,后者主要的方法是在gh-pages里新建一个目录blog,然后里面有一个文件index.html,在html里实现跳转到issues列表,两种跳转方式:

location.href = "https://github.com/tomayday/MyBlog/issues?state=open";

或者

<meta http-equiv="refresh" content="0;url=https://github.com/tomayday/MyBlog/issues?state=open">

然后输入sobear.me/blog就会直接跳转到issue列表里面。

github写博客的用法差不多就这些,也听说有人用gist,但个人感觉不太爽。然后github其实还有一些有趣的用法,比如前不久有人用github发婚礼请柬,然后今天小伙伴说用github还可以表白,比如去某女神的某项目里open issue,然后blablabla,I Love U~~~

说好的台风没见动静,这让我感到绝望,Miss Dong !

题图来自tumblr

--OVER--

对技术的遐想

越来越清楚自己想学什么,越来越想去学,越来越知道怎么去学。

实习的这段时间,给了我很多实践的机会,不再像以前在学校那样,一段时间在学这个,过一段时间又去学习另一个东西,没有目的,也没有深度。在实践的过程中会学到很多新东西,但有时候也会有一些枯燥,重复着一些琐碎的事情,切页面、写异步接口、渲染页面,当然每次都会学到一些新的东西,但是年轻人心里总觉得不够炫,于是在脑子里给自己搭框架,要用各种各样有趣的技术,做一个好玩又有趣的东西,然后一篇一篇的去总结,我想有一天你会在这里看到这样一个系列的文章:

  • NodeChat 之前端模块化分析
  • NodeChat 之前端MVV*框架浅析
  • NodeChat 之Express框架的使用
  • NodeChat 之Mongodb入门
  • NodeChat 之websocket实践
  • NodeChat 之JavaScript的异步模式
  • NodeChat 之屌丝逆袭之路
    ...

NodeChat,这就是我想做的东西,没有太多价值,纯粹是为了学习实践一些好玩的技术,最基本的功能:在页面上可以实时看到别人发送的文字信息。没有冗余的用户系统,估计初始阶段也不用数据库,你可能来这里发送一句真好玩,然后就再也没访问过这个页面了,那有何妨,就是为了玩嘛。

在基本功能实现的基础上,做一些扩展,比如说对字体颜色的设置、可以发送绘画、图片...其他还没有想好,不过我目前不太关心后续的东西,只想着用合适的技术方案解决最基本的功能。

前端模块化是必须的,在实习这段时间对模块化也有了一些相对更加深刻的认识,不过对 KissyKMD 没有太多的感觉,所以更倾向于使用纯粹的模块化管理工具,80%会用sea.js,也有可能会用jQuery自带的模块化工具,在这个过程中,一来对于AMDCMD两种方式或者理念真正理解,二来通过实践对前端模块化做一些自己的思考,不仅是js,还有sass

MVV*框架的使用,这一块的选择应该是最多的,当然也是最纠结的。90多k的AngularJS、0.9k的riotjs...应该会倾向于后者,实话说AngularJS也太大了吧。可能会有疑问这么简单的网站需要用这种框架吗?难道是为了装逼...其实在找实习的那段时间就想找个这种框架实践一下,只是自己当时基础很薄,需要学习的东西太多,因此也没有多余的时间搞这个。在实习的这段时间,空闲时间不是很多,再加上比较碎片,因此只能关注一下相关的技术。

Expressnode 提供一个RouteMVC的工具,没有太多要说的,至于Mongodb,顺应潮流嘛node + mogo对高大上...同时也是对数据库方面的知识系统学习一下,非科班出身伤不起啊,有机会的话,也会了解一下Redis

JavaScript的异步模式,坚决不要满屏的回调,Promise快到碗里来,这块前后端尽量共用Q.js,顺带把回调、事件监听、pub/sub之类的也做一些了解。

webSocket,HTML5 API里最让我兴奋的一个,再也不用见面握三次手了,也是实现基本功能相对核心的一块,这块会结合socket.io一块使用。之后会也会实践一些canvas相关的。

要涉及的技术还是挺多的,所以自己最近也会制定一个学习+实践的规划,争取在回学校—寒假前把基本功能完成。

看起来像是个技术牛,其实,唉,都是泪...

附图:我也不知道从哪偷的

浅析 NodeJs 的几种文件路径

一、挖坑 & 掉坑:

缘起一段这样的代码:

fs.readFile('./docs/use.md', function (err, buffer) {
    if (err) {
      return console.log('error: ', err);
    }

    console.log('OK');
  });

本地运行时一切 OK,线上部署时却死活找不到 ./docs/use.md 这个文件,后来才发现是因为线上启动应用时不是从当前目录启动了,不过为什么启动脚本的位置也会影响这个路径呢,且往下看。

二、填坑:

Node 中的文件路径大概有 __dirname, __filename, process.cwd(), ./ 或者 ../,前三个都是绝对路径,为了便于比较,./../ 我们通过 path.resolve('./')来转换为绝对路径。

先看一个简单的栗子:

假如我们有这样的文件结构:

app/
    -lib/
        -common.js
    -model
        -task.js
        -test.js

在 task.js 里编写如下的代码:

var path = require('path');

console.log(__dirname);
console.log(__filename);
console.log(process.cwd());
console.log(path.resolve('./'));

model 目录下运行 node task.js 得到的输出是:

/Users/guo/Sites/learn/app/model
/Users/guo/Sites/learn/app/model/task.js
/Users/guo/Sites/learn/app/model
/Users/guo/Sites/learn/app/model

然后在 app 目录下运行 node model/task.js,得到的输出是:

/Users/guo/Sites/learn/app/model
/Users/guo/Sites/learn/app/model/task.js
/Users/guo/Sites/learn/app
/Users/guo/Sites/learn/app

那么,不好意思不是问题来了~T_T,我们可以得出一些肤浅的结论了:

  • __dirname: 总是返回被执行的 js 所在文件夹的绝对路径
  • __filename: 总是返回被执行的 js 的绝对路径
  • process.cwd(): 总是返回运行 node 命令时所在的文件夹的绝对路径
  • ./: 跟 process.cwd() 一样、一样、一样的吗?

我明明记得在 require('../lib/common') 里一直都是各种相对路径写,也没见报什么错啊,我们还在再来个栗子吧,还是上面的结构,'model/task.js' 里的代码改成:

var fs = require('fs');
var common = require('../lib/common');

fs.readFile('../lib/common.js', function (err, data) {
    if (err) return console.log(err);
    console.log(data);
});

在 model 目录下运行 node task.js,一切 Ok,没有报错。然后在 app 目录下运行 node model/task.js,然后很果断滴报错了:

那么这下问题真的都是来了,按照上面的理论,在 app 下运行时,../lib/common.js 会被转成 /Users/guo/Sites/learn/lib/common.js,这个路径显然是不存在的,但是从运行结果可以看出 require('../lib/common') 是 OK 的,只是 readFile 时报错了。

那么关于 ./ 正确的结论是:

require() 中使用是跟 __dirname 的效果相同,不会因为启动脚本的目录不一样而改变,在其他情况下跟 process.cwd() 效果相同,是相对于启动脚本所在目录的路径。

三、总结:

只有在 require() 时才使用相对路径(./, ../) 的写法,其他地方一律使用绝对路径,如下:

// 当前目录下
path.dirname(__filename) + '/test.js';
// 相邻目录下
path.resolve(__dirname, '../lib/common.js');

四、参考链接:

以上:smile:。

输入URL后发生了什么

  1. 输入 URL
  2. 浏览器查询 DNS
    • 浏览器缓存
    • 系统缓存
    • 路由缓存
    • ISP 的 DNS 缓存
    • 遍历搜索
  3. 浏览器发送 http 请求到服务器
    • 服务器根据请求头中的 user-agent,accept,accept-encoding 判断返回内容
    • 如果有的话,每次请求都会发送 cookie 头,包含了键值对
  4. 服务器返回永久的重定向 301
  5. 浏览器得到重定向地址,重新发送请求
  6. 服务器处理请求
  7. 服务器发送响应
  8. 浏览器渲染:
    • HTML Parsing: DOM Tree;
    • CSS Parsing: 也是渲染成一个树的样子,Style Rules;
    • Rendering Tree:根据DOM Tree 和 解析的CSS构建渲染树,其中不可见的元素是不出现在渲染树中的;
    • Layout and Reflow:页面 layout 的变化都会引起 reflow,颜色等变动引起 repaint;
    • Paint: 调用底层API进行绘制。
  9. 浏览器请求 HTML 中的组件
  10. 后续的 ajax 请求

UI 测试之:保证页面滚动到底部

现如今,页面内容越来越丰富,多数页面都有滚动加载之类的功能,在做 UI 测试时,无论是用 webdriver,还是单纯的 Phantomjs,只单纯的测试默认加载的 dom 是远远不够的,更完美的做法应该是打开页面后先注入一段保证页面滚动到底部的 js,然后再去运行测试用例。HOW?

/**
 * 保证页面滚动到底部
 */
function scrollToBottom (callback) {

    var TIMES = 10  // 最多滚动10次,防止无限加载
        , INTERVAL = 600  // 每次滚动之间的间隔时间,太短有可能不会触发懒加载事件
        , delta = 1500    // 每次的滚动距离,太长有可能导致之间有的部分未加载
        , preScrollTop = 0  // 滚动前的 window.scrollTop 值
        , curScrollTOp = 0;  // 滚动后的 window.scrollTop 值

    var scroll = function () {
        preScrollTop = $(window).scrollTop();
        TIMES --;
        $(window).scrollTop(preScrollTop + delta);
    };

    scroll();

    var timer = setInterval(function () {

        curScrollTOp = $(window).scrollTop();

        if (TIMES <= 0 || (curScrollTOp - preScrollTop) <= 3 ) {
            // 滚动结束
            clearInterval(timer);
            return callback();
        }

        scroll();

    }, INTERVAL);

}

看似很简单的10多行代码,期间在各种例子下调整了诸多次,当下的版本应该还算稳定准确,诸位可做参考。

以上。

大学生创业,一点点感想

不知道起怎样一个标题比较合适,我想说的是创业或者是做一款产品的成功因素,但考虑到个人只是参加了一个周期为一年的比赛,做了一个失败的中途放弃的产品,所以,标题还是低调点好。

一年前,大二下学期,为了获得大学生国家创业计划的立项资格,经过跟一个要好的同学多次的讨论分析,决定要做一个面向驴友的社交网站,然后就随意找了几个人组了个团队,然后成功立项。那时候我们什么也不会,从前端到后台,我们把所有的精力都放在完善这个idea上,那时看来,确实很赞。

接着就进入了项目的开发期,然后发现五个人的团队其实只有两个人在把这件事当会事的做,作为队长的我,私以为两个人就两个人呗,怕毛线。然后两个人在暑假就拿起一个php的建站系统去做,大半个暑假过去了,成果倒是有,但没作出自己的东西。我们讨论后得出结论:建站系统难以扩展,php不优雅(其实我们基本不会php)。如此之后,我们又选择了Rails这个框架,然后就是漫长的学习期,期间两个人也因为很多问题争吵,沟通出了问题。

一晃大三上就结束了,大三下,两个人技术都积累的差不多了,就正儿八经的开始搭建网站了,不出一个月,队友因为要考研渐渐的退出了,没错,剩我一个人了,我坚持着把1.0版本做出来然后上线,结果发现我一点推广的热情都没有,因为,我们没有做出特色的东西,一点也没有!接着各种考虑之后我放弃了这个项目,话说当时百度三面时面试官因为这个问题跟我讨论了很多,这也可能是三面后最终没有音讯的原因吧。即使如此,我依然不后悔当时放弃的选择,说说原因吧:

13年跟12年不同了,随着穷游网和马蜂窝的崛起,在零资源的情况下要有所突破难度太大。
我一个人去开发这样一个网站,技术、时间、精力上的投入 ,我都没办法达到。
恩,这段经历是不是有点图样图**的感觉……放弃之后,我先是系统深入的学习了前端的知识,之后跟同学做了两个小东西,这都是后话了,此处不说。我表示终于要到主题了,谈谈我自己收获的东西。

1. 对于大学生创业,idea、团队、技术哪个更重要?

一年前我肯定毫不犹豫说idea,但今天我给出的答案是团队>技术>idea。

  • 关于团队: 成败的决定性因素。
    团队的执行力。虽说一个团队的执行力并非每个成员执行力的简单加和,但每个成员足够强的执行力却是必不可少的;
  • 成员间的沟通。互相信任,互相鼓励,无论怎么牛逼的团队,总会碰上或大或小的挫折,所以时刻充满正能量。
  • 队长的决断与眼界。作为队长,要担当起自己的责任,更多的投入,项目进度的掌控,团队成员的调整, 我做的很差。
  • 关于技术:小心被拖垮。这可能仅是我们的问题,刚开始技术太薄弱,前端、后台、数据库,太长的学习周期,起初对项目的热情被拖垮了。
  • 关于idea:对于大学生来说,做一个产品更多是一个历练的过程,你需要苦思冥想一个牛逼到颠覆互联网的idea么?不需要!而且那也不是想出来的。所以,一个绝好的idea可能很难,但不错的idea还是挺多的,细心观察生活,观察身边的人。

2. 怎样去开发一个互联网产品?

  • 搞清楚你的用户群体,用户的痛点,你为他们解决了什么问题,怎么解决的,也就是明确用户群体和核心功能。
  • 在1的基础上,停止讨论未来的发展方向,盈利模式,添加哪些功能,别浪费时间了。
  • 依照核心功能快速开发,迅速上线。
  • 邀请种子用户,根据反馈不断迭代开发。

恩,就是这样,产品功能是自然而然的需求,而不是苦思冥想的结果。

大抵如此,你可能会觉得看完以后还是觉得图样图森破,没事,这毕竟只是一个大学生在学校这狭小的空间里实践思考而总结出的一点东西。

CSS Tips

整理一些CSS的用法。

1. 清理浮动,出自Nicolas Gallagher

.cf:before, .cf:after {
    content:"";
    display:table;
}
.cf:after {
    clear:both;
}
.cf {
    zoom:1;
}

2. 有float:left/position:absolute撑腰的情况下,display属性就是多余的:

如果给元素设置了float:left/right 或者 position: absolute/fixed,元素自动变为块级元素,但这个时候元素默认情况下宽度是内容的宽度,而不会充满整个父容器,不过因为是块级元素,宽度和上下边距都可以设置。

3. 重置chrome下输入框的默认样式

input, button, select, textarea{
    outline:none;
}
textarea{
    resize:none;
} 

4. z-index属性只有在定位元素上才会生效。

所谓定位元素,在position: absolute的解释里:设置了absolute的元素会根据已定位的父元素布局,已定位的元素指的就是position属性非static,即relative, absolute, 或者fixed的元素

5. iframe在IE8-下出现滚动条:

解决方法:<iframe src="" scrolling="no" frameBorder="0"></iframe>.

6. IE7 下 overflow: hidden 失效:

解决方法:给容器设置 position: relative.

7. css隐藏文字:

通常大家都会用text-indent: -9999px隐藏问在,但是这个方案在IE7和移动端会影响布局,所以推荐的方法是先给元素设置overflow-y: hidden,然后再设置一个比较大的line-height值,这样做还有一个好处就是可以复制这些文字。

8. 根据窗口宽度切换class

function changeClass () {
    var width = document.documentElement.clientWidth;
    if (width >= 1190) {
        return;
    } else if (width >= 990 && width <= 1190) {
        document.body.className = 'screen-width-1190';
    } else if (width < 990) {
        document.body.className = 'screen-width-768';
    }
}
changeClass();
window.onresize = function () {
    setTimeout(function () {
        changeClass();
    }, 500);
};

9. overflow失效:

在IE6、7中,给父元素设置了overflow: hidden;,这时候如果子元素设置了position属性,则隐藏滚动条会失效,解决方案就是给父元素设置position: relative:

body{
    overflow: hidden;
    *position: relative;  /* IE hack */
}
child{
    position: relative;
}

追求与能力

清晨起来,突然感觉幸福感非常强烈,不知道昨晚睡觉的时候发生了什么事,难度是因为昨天发工资了?我从来不承认我是这么世俗的人耶~

有时候幸福离我们很近,一段音乐,一丝阳光,或是一句话,一个眼神,生活全然可以这么简单。

同样的一个人在不同的群体总会有着不同的视野、想法、**深度,这也就是我经常告诉自己要跳出圈子,不要给自己设限。我们在大学里,看着室友玩游戏逃课,自然而然的也慢慢的认可甚至投身这种生活;在实验室里,看着周围的人水平也都那样,自然就没有了努力提升自身能力的欲望或是行动。就是这样,人是群体生活的动物,自然也就趋于被群体认可,要被认可最简单的方法就是大家都一样,所以我们就这样把自己的能力设定在这个限制下,等一天投身另一个群体继续重复这样的生活,当然,不是每个人都是这样,我所说的是大部分人。

OK,我想说的就是人生不设限,看了《寿司之神》这部电影后,这样的体会更加深刻,当有一天你觉得自己已经达到顶点,你一定是自欺欺人。努力去提高自己,努力去过自己想过的生活,这些都不该受你所在的群体影响,人之**独立,大概就在这里体现吧。不要在勉强自己,向现实妥协之后,总拿诸如:「现实就是这样」、「这个社会就是这样」、「周围的人都是这样」,来糊弄自己,你本没有这么懦弱,让别人去谈现实吧,这些都与你无关。

其实今天本来想说的不是上面这些,上面的话都是之前想的没有时间写,好吧,说说今天想说的吧,「追求与能力」。

同样,社会的一个等级其实就是一个群体,这个群体也可以不断的细化,而在每一个群体的时候你都会追求更好或是更高的群体。举个栗子,高考,你的实力和本身的想法都趋向于去一所差不多的一本学校,但是一不小心你考到一所一流的一本院校(淡定,我说的不是「西电」),这时候你就会追求去一所更好的学校读研,人之本能,这样想当然没什么错,但是,你需要提醒自己的是更高的追求需要的是更牛逼的能力,不要整天拿着那些虚无的目标YY,你更需要的是给自己提出新的要求,不断提高自己。

总结一下,不要把自己困在一个圈子里,同时,当你追求一个更好的圈子时,记得首要的认清自己的水平,定下新的目标,并不断提高之。

如是而已。

一些不算观点的观点

回学校整整10天了,琐事比较多,填各种表格,回家看老爸老妈,也没有比较完整的时间coding或者是读书,都是一些零散的思考:

1. 对于App更新频率的看法:

从传统软件行业到如今的web应用,产品、运营、开发者都有了不断试错,快速迭代的机会。从产品或者运营的角度讲,他们有了更多的机会去添加一个功能、删除一个功能、甚至在心情好的时候再添加这个功能;从开发人员的角度讲,他们不需要对每一行代码像曾经那么谨慎,不需要全身心的投入去测试没一个功能是否有bug,因为没准明天这个功能就要下掉,没准今天下班前又会发布一个新版本。

就是这样,快速上线,不停的迭代,我们有犯错的机会,然后我们就在不停的犯错,换言之,我们变得不够谨慎,不停的在行动,却不再长时间的思考。

作为用户,对于在浏览器端呈现的网页,我倒不会很在意这样迅速的迭代,但在App上,我超级反感一个App三天两头的提醒我要升级新版本,比如淘宝客户端和支付宝,没记错的话应该是每个月都会有一次版本更新。

一直不变的一个观点:不要轻易去消耗用户对于产品的信任。升级App需要成本,即使ios7提供了后台自动升级的功能。给App添加一个功能,相信我,这是一件非常非常重要的事,不应该是一次脑爆或者某天夜里的一次YY就能决定了。产品和运营谨慎的把握某个产品需要哪个不需要哪个功能,开发者有足够的时间去把某个功能做好乃至做到极致。我们都需要思考,需要静下心来思考。

那么,就我个人来讲,我自以为App升级的频率设定为3个月是个不错的选择,当然特殊情况特殊对待,如ios7升级或者大型活动之类的。

2. 关于移动支付

从N年前的网上支付到今日的移动支付,对于用户来讲,将关注点更多的放在便捷上,而不再是安全上。当然,安全依然重要,或者是更加重要,只是开发者需要在后台处理好这些事情,不用去展现给用户。

在移动支付上,对于用户通常来说有两个痛点:

    1. 使用银行卡(含信用卡)的人,需要刷卡,输密码,然后签名;
    1. 使用现金的人,需要找零。

按照这两点的话,我认为支付宝是走在正确的路上,而微信的扫码支付谨慎点的说不会是未来,所以支付宝不需要看到微信支付就乱了阵脚。在这样的形势下,突然对PC端转账收费实在让人难以理解,未来的确是移动的,但全然不应该以这样的方式把用户赶到移动端,更科学的方式应该是不断的去优化移动端的支付体验,实际上支付宝在这方面一直做的不错,实际上也有很多提升的空间:当面付的流程做的更加易懂、应用里面没用的赶紧删掉(快的打车,电影票...),还有我一直不理解「充值」的入口为什么那么深。

3. Others

  • 最近订阅了一个不错的博客「IT公论」,IT界的脱口秀,非常赞,你可以关注他们的微信公众帐号,也可以在他们的主页收听:http://www.itgonglun.com/。
  • 12306出App了,体验了一番,估计是为了保持跟官网的体验一致性,依然是很!糟!糕!

很多观点只是个人YY,没有什么实践证明,欢迎指正!

从实习到学校的过渡期结束啦,新生活开始,每天锻炼身体、坚持读书、坚持学习新知识~

css

CSS 九宫格

用 CSS 实现以上的九宫格效果,大概每个前端同学都见过不下5次吧,尤其是在面试中。记得上次看到的时候还是一年前吧,那时候想着实现最后不知道什么事耽搁了,大概是根本就没想清楚吧,前两天再次看到,就尝试了一下,实现起来也是很简单的,直接看代码吧:

<ul class="list">
  <li class="item"></li>
  <li class="item"></li>
  <li class="item"></li>
  <li class="item"></li>
  <li class="item"></li>
  <li class="item"></li>
  <li class="item"></li>
  <li class="item"></li>
  <li class="item"></li>  
</ul>
ul, li {
  list-style: none;
}
.list {
  width: 315px;
  height: 315px;
  padding-top: 5px;
  padding-left: 5px;
  background-color: #ccc;
  /* omission clearfix */
}

.item {
  float: left;
  width: 100px;
  height: 100px;
  border: 5px solid #000;
  margin-left: -5px;
  margin-top: -5px;
}

.item:hover {
  border-color: #f40;
  position: relative;
  z-index: 10;
}
<iframe width="100%" height="300" src="http://jsfiddle.net/pkac0eqe/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>

诺,的确很简单嘛,

实习教会我的

2013-11-09 15 06 45

在淘宝UED实习三个多月了,这三个月来学习到了很多东西,技术方面的、个人成长方面的,很多很多。借着今天的天气这么好,赶紧把这些东西总结一下,趁年轻嘛==

1. 为什么要做前端?

想必面试过前端的人都被问过这个问题,很多人觉得前端发展不成熟,会面临成长瓶颈之类的,我个人倒是觉得现如今前端这个职位发展已经趋于成熟。当然有人会说,前端需要考虑IE6、技术更新快、涉及面比较广,我觉得这是特点,而非缺点。

找实习那会自然是没有考虑这么多的,只是简单的觉得做前端蛮有趣的,在经过这三个月的实习,一方面是对前端职位的更深刻的理解,另一方面自己对做前端更加坚定。我之所以想做前端,说来很简单:想做技术,喜欢产品,想做一些人文关怀的东西。

想做技术:觉得做技术的人比较纯粹,不用去考虑太多杂七杂八的东西,用以前说过的比较装逼的话就是:我觉得做技术更能让我保持独立的人格。人与人之间纯粹的相处,纯粹的交流,不夹杂其他东西。而在实习的这个阶段里,这里的师兄师姐给我的就是这样的感觉,所以,我会坚持我的这个想法。

喜欢产品:不知道从什么时候起给自己贴上的这个标签,不过,这是真的。喜欢产品,但目前来说不想去走做产品的这条路,无论是自身对事物的认识、对产品的理念,还是个人的经历都没有达到想象中做产品的那个水准。但是这并不妨碍去思考一个产品,或者是给别人扯自己的观点,保持思考,对这个世界,和这个世界的每一个事物。

前端处在技术与人文的交汇处,在这个交汇处可以做出很牛的技术,也有机会对产品做很多的改进,甚至去做自己的产品。有一点很遗憾,我曾以为前端可以对视觉交互有很大的影响,但事实是很难,前端说服交互改动一个点的成本太高,因为很多人简单的认为前端就是做页面的,就是单纯的做技术。我曾经固执的认为一个善于思考的前端工程师对于用户体验、对于交互的理解胜过一些专业的交互,现在依然这样固执的认为。当然,我可不会大言不惭的认为我达到那样的级别了。

路方长,怀敬畏之心,不断努力,不断前行。

2. 前端要不要会切图?

在学校的时候也没有搞过什么视觉稿,所以对这种问题都懒得思考,「切图」这种事显然不应该是前端的活,事实是特么的压根就不知道切图是干嘛的。

好吧,我鄙视我的无知,在被鄙视之后,在认识到切图是干什么之后,显然需要重新思考一下,不然总被视觉同学黑太打击自信心了。so 前端为什么需要切图?因为只有前端自身知道哪些图需要切、切多大、从哪个位置切、repeat什么的。然后切图本身也不是什么难事,实践两次就上手了。

事实上前面都不是重点。对于前端来说,与切图相比,另一种能力更加重要:在看到视觉稿后,首先对于整体的布局方式有一个解决方案,其次是每个部分以怎样的方式去布局比较合适,文档流、浮动、相对绝对定位、甚至移动端的flex-box,在这些问题都有一个大体的解决方案后,最后根据这套解决方案决定如何切图之类的。

参考知乎http://www.zhihu.com/question/19769761下「克军」的回答。

3. 视觉review真的真的很重要

刚来的时候,特别反感视觉一个像素一个像素的抠,后来看到一些因为时间紧急没有review的项目后,慢慢意识到这个流程的意义。

当我们说这次项目时间很紧,先发布掉,等一个版本再过细节问题时,结局往往是这些细节最终都成为遗留问题,无人问津。

如果真如某天在路上听到一个疑似运营的姑娘说的那样:前端不就是把一张图片变成网页嘛~那就把这张图片还原的精细一点。对视觉负责,对前端自己负责。

4. 沉淀自己,沉淀生活

生活很长,不要把自己淹没在忙碌的泡沫里。


前不久,看到张公子在知乎上的一个回答,感受很多,问题是:什么样的男人才算成熟?张公子的回答如下:

不需要靠不需要靠一切阿谀外界的行为来获得安全感。
不需要靠一切贬损外界的行为来获得优越感。
不需要靠外界的一切褒扬来获得存在感。
安静公平的面对一切。
确实知道自己该做什么,而且更明确自己不该做什么,以及可以不必做什么。一切阿谀外界的行为来获得安全感。
不需要靠一切贬损外界的行为来获得优越感。
不需要靠外界的一切褒扬来获得存在感。
安静公平的面对一切。
确实知道自己该做什么,而且更明确自己不该做什么,以及可以不必做什么。

具体参见知乎:什么样的男人才算是成熟的男人?

安静公平的面对一切,愿共勉。

附图:晴天下的黄龙,昨天拍的,昨天写的,今天天气突然拉下了脸。

工具初始化

重装一次系统,要去安装配置各种工具,编辑器、版本控制等等,这里就把中间遇到的小问题整理一下:

1. sublime text3 安装与配置:

  • V3 不能用之前的方法安装 package control ,新的方法是 Ctrl + ~ 打开命令行,输入:
import urllib.request,os; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); open(os.path.join(ipp, pf), 'wb').write(urllib.request.urlopen( 'http://sublime.wbond.net/' + pf.replace(' ','%20')).read())

参见 https://sublime.wbond.net/installation

  • 这时候输入 package install 就可以安装插件了,但是有时候会有出错信息 Unable to find git.exe ,在 Preferences -> Package Settings -> Package Control -> Settings - User 添加:
    "ignore_vcs_packages":true
    参见 http://www.ladyloveit.com/sublime/sublime-unable-to-find-git-exe-error/
  • 安装主要的插件:emmet sidebar enhancement and so on ~
  • sublime运行js文件:先安装node,然后在sublime中选择 Tools—> Build system—> New build system,输入:
{
    "cmd": ["node", "$file"],
    "selector": "source.js"
}

保存后,js文件下 Ctrl + b 就可以直接运行了。

2. windows 下 git 的使用:

windows下git的工具可以用msysgit,大部分的 linux 命令都可以使用,不过中文的输入显示会有一些问题,不过我今天装 1.8.4 的时候已经可以输入中文了,所以只剩下 ls 时中文文件名乱码的问题了,解决方案:找到 msysgit 的安装目录,在 git-completion.bash 文件最后添加 alias ls='ls --show-control-chars --color=auto'

如果输入中文也有问题,可参考 http://www.cnblogs.com/liangxiaxu/archive/2012/08/05/2623678.html ,不过我之前的旧版本按照这些方法都没用,所以最好还是升级版本吧。

3. github pages:

本来没github什么事的,结果因为想给博客搞个域名指向,设置DNS -> 新建CNAME文件,看起来很简单的事,却不知道哪里出了问题,搞好了再知晓~

搞好了,请轻戳

--OVER--

焉知非福

因祸得福的时候,要告诉自己「塞翁失马,焉知非福」,遇祸但还没有得福的时候,更要告诉自己焉知非福。

最近一直在纠结转正的事,然后今天得知转正面试没有过,当时心里非常沮丧,因为无论是从做项目的过程,还是团队合作的层面,自认为都做的不错,所以之前可能会觉得差不多应该能顺利转正吧。得知结果后,就是跟师兄聊自己的问题,聊完之后,我想告诉自己焉知非福。

从大三下学期我就发现自己的一个问题:当忙于一件事的时候,很多事情都落下了,也没有什么沉淀。事实上那件事情的确很忙,但能忙到让自己什么事都落下的程度吗?不至于,归根结底还是自己没有去督促自己。而实习的这段时间,也是这个问题,忙着做需求,做项目,忘记了自身理论知识的学习,其实刚来大半个月时就意识到这个问题了。不断的做需求对自身实力的提升是很有限的,重点还是内力的提高。期间也有跟师兄在邮件中提过,师兄没有太在意,而我其实也没有忽视这个问题,脑子里一直想着一定要跟师兄一块规划一下,但因为这样那样的原因都没有去说,而最终基本就是因为对自己的规划问题而挂掉。

焉知非福。如果这次转正就这样通过了,自己可能根本不会注意到这个问题对自己的成长有多么的不利,之后的发展也必然会遇到瓶颈,而那个时候的自己可能根本没有现在的热血了。一次失利,让我更清楚的认识到自己的问题,认识到我必须要通过自身的努力与督促去改变这个缺点。趁年轻,多发现自己的问题,老了就没劲改了。

失利不代表离开。跟师兄商量后还是继续在这边实习,在哪里跌倒,就在哪里站起来,不然多没面啊。不过这次一定要慢慢的沉淀下来,迈过这道坎,风景一定别致。

不丧失信心。


PS:写在最后,前两天一个挺熟悉的实习生被通知转正不通过,当时就在想,一个公司放弃一个实习生时,对公司的影响微乎其微,但对于实习生则很可能是错失了很多校招机会。而这次的转正结果从13号拖到18号,再到26号,然后跪了,很崩溃。

满场正能量,最后却来一段负能量,真是的...


PPS:前两天帮团队转发招聘微博时,我告诉「堂主」,我想到了一个悲伤的故事,其实在我买山地车的时候,我也想到这个悲伤的故事:我在这个城市买了俩山地车准备以后上班骑,然后我被拒了;我帮团队转发招聘的微博,然后我被拒了。尼玛,真是个悲伤的故事。

好在,这不是结局!

JavaScript 实现复制内容到剪贴板

这个问题算是之前项目的一个遗留问题,前不久研究总结了一下,记录在这里。

问题:

如何用 js 实现点击一段文本时将文本复制到剪贴板上?

思路:

1. Flash 实现:

目前有这个需求的网站基本都是这个解决方案,比如说github的这个功能:
copy

我们今天主要说js的实现,所以flash的实现方式就不做介绍了。

2. js 实现:

很遗憾,因为安全方面的考虑,除IE以外的其他浏览器的都不允许js去做这件事,既然不能直接实现,我们只能考虑一下退化方案,我个人的退化方案是:鼠标移到目标文字时,文字被选中,然后提示用户按下 ctrl+c 可以复制。

OK,按照以上的需求,我们需要解决的问题:

  • 如何让文字处于选中状态?

jQuery 提供了一个现成的方法select(),你只需要这样做 elem.select() 就可以搞定。

用原生js实现,需要针对不同浏览器做一些兼容性的处理:

function selectText (element) {
    var text = element,
        range,
        selection;

    if (body.createTextRange) {
        // IE
        range = body.createTextRange();
        range.moveToElementText(text);
        range.select();
    } else if (window.getSelection) {
        // Others
        selection = window.getSelection();
        range = doc.createRange();
        range.selectNodeContents(text);
        selection.removeAllRanges();
        selection.addRange(range);
    } else {
        return false;
    }
}

然后你只需要对相应的元素绑定 mouseenter 的事件,然后响应 selectText() 这个方法就 ok。

可以参考stackoverflow的这个问题

  • 怎么设置选中状态的样式?(可选)

浏览器中文字在选中状态下本身就会有默认的状态,没错,就是那蓝色的一坨,在IE下目前所了解的是不可以自定义这个样式的,但在 chrome 和 firefox 下可以自定义:

/* 选中后的文字样式 */
::selection {
    color: #fff;
    background-color: #1abc9c;
}
::-moz-selection {
    color: #fff;
    background-color: #1abc9c;
}

然后就可以看到这样的效果了:

3. 一点成果:

核心方法就是上文所提及的selectText(),然后一时兴起就把这个东西封装了一下, 还起了一个比较装逼的名字copy.jsdemo

在封装的过程中,我想在上面的基础上,实现用户按下ctrl+c时再给一个「复制成功」的提示,然后碰到了如何监听用户同时按下 ctrl+c 的问题。

event 对象中本身就有altKeyctrlKey这样的标志,所以只需要这样做:

document.addEventListener('keydown', function (e) {
    if (e.ctrlKey && e.keyCode === 67) {
        // 按下 ctrl + c
    }
});

--正文完--

在写copy.js时,需要写兼容IE8-的 getElementsByClassName() 的方法,一个老掉牙的笔试题,再次有了一点新的认识,之后会整理一下,留作下次分享。

整理一些前端笔试题(待)

第一期

  1. 在0级DOM事件模型,通过 onclick 属性来绑定事件,比如: dom.onclick = function(){}; 这个方式最大的缺点之一是每个元素上只能绑定一个事件监听函数。
    请实现一个函数 click, 基于0级DOM事件模型实现,但是可以在一个元素上绑定多个事件监听函数,函数声明如下:
    function click(element, callback) {…}
    var elem = document.getElementById('test');

    click(elem, function() {
        console.log(1);
    })

    click(elem, function() {
        console.log(2);
    })

    elem.onclick = function() {
        for (var i = 0, l = elem.funcs.length; i < l; i++) {
            elem.funcs[i]();
        }
    };

    function click(elem, func) {
        if (elem.funcs === undefined) {
            elem.funcs = [];
        }
        elem.funcs.push(func);
    }
  1. 实现一个字符串格式化函数,function format(str, obj),将str中的 "#{name}"替换成 obj中对应的值。比如:
    format("#{name} say: #{msg}", {name: 'Bob', msg: 'hello!'})
    输出: "Bob say: hello!"

    // By 大果
    function format(str, datas) {
        var reg = /#{\w+}/g,
              matchs = str.match(reg);
        for (var i = 0, l = matchs.length; i < l; i++) {
              str = str.replace(new RegExp(matchs[i]), datas[matchs[i].slice(2, -1)]);
        }
        return str;
    }
    // By 岱浩
    function format2(str,obj){
        var reg = /#{(\w+)}/g,
              rep;
        while(rep = reg.exec(str)) {
            str = str.replace(rep[0],obj[rep[1]]);
        }
        return str;
    }

第二期

  1. 以下两段代码有什么不同?

    setTimeout(function(){
    /* 代码块... */  
    setTimeout(arguments.callee, 10); 
    }, 10); 
    
    setInterval(function(){ 
    /*代码块... */ 
    }, 10);
  2. 判断字符串是否是这样组成的,第一个必须是字母,后面可以是字母、数字、下划线,总长度为5-20。

  3. 实现 Array.prototype.forEach 方法。

  4. 使用Javascript打印出1-10000之间的所有对称数(例如 121 1331等)。

  5. 使用纯CSS实现未知尺寸的图片(但高宽都小于200px)在200px的正方形容器中水平和垂直居中。

一些思考

好久没有写博客了,话说真不是因为我懒,最近博客的事把我搞的实在蛋疼,今天就从博客的事说起吧。

1. 关于博客:

话说刚写博客时,赶时髦的把博客放在github上,用了一段时间后,一来不是很热衷于markdown,二来觉得不能在线修改文章觉得很蛋疼,于是在朋友的帮助下转战wordpress,顺手把博客部署在朋友买的服务器上。OK,这就挺好的,不过年轻人就是爱折腾,觉得那个服务器商速度太慢了,又把博客部署到youhosting这个免费服务商那里,一段平稳的时光,谁知前不久噩耗传来,这货竟然不提前通知就把我的服务给禁掉了,这下才是真的蛋疼了,关键是我之前的十多篇文章也无法导出了,无奈之余用我那蹩脚的chinglish跟youhosting的人死缠烂打,终于是恢复了我的服务,好吧,这服务我是彻底不敢用了,免费的果然是不靠谱啊,赶紧导出数据滚蛋,滚到哪去呢?这次被搞之后认识到数据的重要性,加之github自带的编辑器有个zen mode的模式很爽,所以转了一圈又回来了,前两天刚部署好,还没来得及打扮着小姑娘呢。

小结一下,一来正常情况下免费服务相当不靠谱,二来数据很重要,三来养成的写博客习惯最好不要因为这类事打断,望坚持。

2. 关于实习:

之前还写过一篇找实习的经历,放在Evernote里都懒的发表了,蛮曲折的过程,好歹暑假结束不久略带幸运的搞定了,淘宝UED,恩,听起来很牛逼,不过自己的水平自己知道,要学的东西很多,没有什么值得骄傲的。

来杭州实习半个月了,总感觉没有找到重心,没有一个明确的学习计划,所以感觉提高不是很大。最近师兄让我做一个动画很多的需求,刚来就接手蛮复杂的任务,压力挺大的,心里总想着赶紧把这个做完,做完就能学习新的东西了,但实际上的进展却不如人意,真是一个很纠结的过程。

心里自然清楚,前期遇到的挫折越大,完成之后的幸福感或者成就感就越大,但自身还是希望有一个阶梯,一来成绩是一步一步的很明确,二来也不会很惨的打击到自信心。不过师兄们貌似都是这么过来的,自然也就没有抱怨的理由,所以还是坚持把当前的需求搞定。

不知道想说什么...流水帐!

3. 关于阿里浪:

阿里投资新浪后的第一波成果来了,打通数据,商家可以直接将商品信息分享到微博,并且可以监控各种数据。我想说的是,无论这件事在技术上多么牛逼,在短期内的访问量有多么大的提高,我个人对此是失望的。

阿里投资新浪,在社交上终于有牌可打,终于可以自由的将电子商务跟社交化解结合起来,我当时的想法是:希望阿里不要太急,能耐心的先将新浪微博做成一个优秀的产品。无疑,新浪微博是个非常成功的产品,但谈不上优秀,从产品的方向到前端界面的设计,槽点的确很多,加之现如今微信的冲击,微博需要提高的地方很多,并且微博的确有很多很多提高的地方:砍掉三分之一的功能、将每个页面的链接减少三分之一,前端页面设计,APP的设计...但是阿里没有去做这些事,果然是如大多数媒体所预料的简单粗暴,这种短期的转现只是昙花一现,满足大家的猎奇心理,长远来看,没有多大意义,没有负作用就算不错了。

微博不见得要去学习微信,但微博团队必须学习微信团队对待产品的态度,之前有人说如果让新浪做微信,微信的按钮肯定是现在的六倍以上,我想这不仅仅是一句玩笑话。

好吧,这些是我对这个产品的一点想法,可能很傻很天真,但也算是一家之言。

七夕之夜在这写博客,太特么屌丝了!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.