· 构建前端MVC,seajs,underscore.js,backbone.js 等琐碎的其他
· 小结,重整旗鼓
· 分词筛选模块
2011-7-12 13:38:44 阅读20 评论0 122011/07 July12
http://sass-lang.com/tutorial.html
很早就想尝试这个HAML团队的杰作,当放在todo-list里一直做冷板凳,最近手头时间比较宽松终于能拿出来开荤了。
用了半天时间,把当前手上一个项目的css全部转换为scss(是个较大的项目,估计有上2千行),可见其转换过程并不痛苦,我自己感觉也是比较顺畅的,这彻底打消了我在less和scss间做选择的纠结。
语法很简单,看完tutorial就没问题了,Documentation 基本上都不用看。
相比较而言,前段时间尝试的coffescript给我的感觉过于嚣张啦~~
在好多没必要的地方过份包装,不符合我最看重的kissy原则(只做最需要去做的事情),完全把javascript扔到了脑后,让使用者找不到写js的感觉了,可能是作者太喜欢ruby语法了吧。
我觉得coffescript应该秉承一条核心使命,它并需要把js来一个彻底的华丽转身,因为js社区的基础已经非常雄厚,很多人的相关编码经验没必要抛弃。coffescript的使命应该只有一条最简单的:减少javascript的代码行数!
从今年开始,node.js社区的发力,seajs的出世,coffescript、sass项目的成熟标志着前端开发在这一年进步神速。如果这些好项目都今后能够健康发展,未来我们可以称今年为前端开发次世代元年吗?
最后,放一个我用scss实现的一个kissy框架双飞翼布局中的代码生成功能:
http://kissy.googlecode.com/svn/trunk/src/cssgrids/css-generator.html
以前生成双飞翼布局的代码都要跑这个页面去,非常不coder,现在用scss即能够亲松实现代码生成,干完这件事儿后果断把以上地址从浏览器书签中移除了。
/*#region Grids */ body{text-align:center;} .wapper{margin:0 auto;width:960px;position:relative;text-align:left;} .col-main {float: left;width: 100%; min-height: 1px;} .col-sub, .col-extra {float: left;} .layout:after, .main-wrap:after, .col-sub:after, .col-extra:after {content: '\20';display: block;height: 0;clear: both;} .layout, .main-wrap, .col-sub, .col-extra {zoom: 1;} @mixin grid-sxm0($scol) { .main-wrap { margin-left: $scol*40px; } .col-sub { width: $scol*40 - 10px; margin-left: -100%; } } .grid-s4m0{@include grid-sxm0(4);} .grid-s5m0{@include grid-sxm0(5);} .grid-s6m0{@include grid-sxm0(6);} .grid-s7m0{@include grid-sxm0(7);} @mixin grid-m0sx($scol) { .main-wrap { margin-right: $scol*40px; } .col-sub { width: $scol*40 - 10px; margin-left: $scol*40 - 10px; } } .grid-m0s6{@include grid-m0sx(6);} .grid-m0s7{@include grid-m0sx(7);} .grid-m0s8{@include grid-m0sx(8);} .grid-m0s9{@include grid-m0sx(9);} .grid-m0s10{@include grid-m0sx(10);} @mixin grid-exm0sx($ecol, $scol) { .main-wrap { margin: 0 $scol*40 0 $ecol*40; } .col-sub { width: $scol*40 - 10px; margin-left: -($scol*40 - 10px); } .col-extra { width: $ecol*40 - 10px; margin-left: -100%; } } .grid-e6m0s5{@include grid-exm0sx(6,5);} @mixin grid-m0sxx($xx) { .main-wrap { margin-right: $xx + 10px; } .col-sub { width: $xx; margin-left: -$xx; } } .grid-m0s220{@include grid-m0sxx(220);} /*#endregion Grids */2011-6-30 14:59:45 阅读239 评论0 302011/06 June30
公元前399年,哲学家苏格拉底被判死刑。死于全体雅典公民之手,雅典公民民主投票的结果是:280:221。
当年的古希腊是号称民主的起源地,通俗的讲就是纯粹的民主,纯粹的人民意志。
很好听的词儿是吧?其实这里还有个完全相等的词儿:人民暴政。
即等于纯粹的民主。
随着时代的发展与变迁,特别是经历了法国大革命的洗礼,人们终于逐渐学会了,民主是需要控制的(想学学如何控制?推荐这篇贱文:民主共和宪政和黑手党政治),并且越小的集体越容易出现民主暴政,简单的讲就是多数人欺负少数人。如果只有三个人投票,1.8米以上身高的人多争收100%的个税,那三人中另外两个1.8米以下的人会放过这个议案吗?
在人数少的时候,负面道德压力变得更小,而正面道德压力永远都是差不多大,因为,那几乎只是你一个人的内心。
《狗镇》这部电影用最为纯粹、血淋淋的故事,警告了我们一定要看清人性。
其实,当年的鲁迅真的洞悉人性,,,只不过太多的中国人读鲁迅的书只当吃了碗泡面,还自夸自己吃过中国最牛的泡面。
人性之恶已经让我们无数个伟大的思想家,艺术家,政治家吃了鳖。千万别说什么死后被平反之类的事儿。
《狗镇》就像一片刺眼的烈日,虽然说不出的难受,但是,它确实照亮了我们身前身后的道路,虽然这两道风景都是鲜血淋漓。
所有对这个世界抱着天真幻想的人都应该去看看,接受它的洗礼。
那些教会过我们什么叫做恨的人,让我们终于摆脱了愚蠢的傲慢和瞎眼的善良。它让我们知道自己是如何活下来,又将如何活下去。
PS:民主与共和的相互劫持坐庄是目前人类所能探索到的最平整的前进道路……
2011-5-6 13:26:16 阅读17 评论0 62011/05 May6
抽空读了读jquery代码,确实颇有收获。首先放上整体代码结构:
(function (window, undefined) {
var document = window.document;
var jQuery = (function() {
var jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context, rootjQuery );
};
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
init: function (selector, context, rootjQuery) {
// ...
if (selector.nodeType) {
this.context = this[0] = selector;
this.length = 1;
return this;
}
// ...
},
// ...
};
jQuery.fn.init.prototype = jQuery.fn;
jQuery.extend = jQuery.fn.extend = function() {
// ...
};
jQuery.extend({
noConflict:function(){},
Ready:function(){},
// ...
});
// ...
return jQuery;
})();
jQuery.extend({
});
// ...
window.jQuery = window.$ = jQuery
})(window);
首先为何会有两层(function…)()自执行函数的疑问我觉得应该解释为为了更好的模块化开发,在github中有模块化的源码
看过《javasctipt权威指南》应该能更好的理解new语法到底为何物,也就自然能理解为何在jquery中new $()与执行$()结果一模一样
重点:
jQuery.prototype
=== jQuery.fn
=== jQuery.fn.init.prototype
逻辑上此处有矛盾,fn与fn.init.prototype形成了循环包含,但这也正体现了js为值对象语言的特征,一切皆为值拷贝(jQuery.fn.init.prototype = jQuery.fn)
PS:$.extend使用深度copy突破了值拷贝障碍,下节分析,目前$.extend的可读性并不好,充斥着魔鬼数字。
jquery.fn的成员:
平常的 $("#id") 就是 new jQuery.fn.init("#id");
init函数中,返回值this附加上context、length等参数后再附带上jQuery.fn.init.prototype(即jQuery.fn)返回给调用者
以下为init函数注释代码:
init: function( selector, context, rootjQuery ) {
// 参数: selector 选择器
// context 上下文
// rootjQuery 父节点
// 处理 $("")、 $(null) 和 $(undefined)
if ( !selector ) {
return this;
}
// 处理 $(DOMElement)
if ( selector.nodeType ) {
// 直接扔数组中, 就搞定了。
this.context = this[0] = selector;
this.length = 1;
return this;
}
// 处理 $("body") body 元素只存在一次,单独找它
if ( selector === "body" && !context && document.body ) {
// 同样扔数组中, 顺便把 selector 更新更新。
this.context = document;
this[0] = document.body;
this.selector = "body";
this.length = 1;
return this;
}
// 处理 $(HTML 代码 或者是 css 选择器)
if ( typeof selector === "string" ) {
match = quickExpr.exec( selector );
// 检查是否正确匹配
if ( match && (match[1] || !context) ) {
// 处理: $(html) -> $(array)
if ( match[1] ) {
// 获取正文,默认 document
context = context instanceof jQuery ? context[0] : context;
doc = (context ? context.ownerDocument || context : document);
// 如果传入简单的 "<标签>", ( /^<(\w+)\s*\/?>(?:<\/\1>)?$/)
ret = rsingleTag.exec( selector );
// 返回 createElement("tag")
return jQuery.merge( this, selector );
// 处理: $("#id")
} else {
elem = document.getElementById( match[2] );
// 因为有的浏览器 getElementById 不只返回 id匹配的,所以做检查。
return this;
}
// 处理 $("标签")
} else if ( !context && !rnonword.test( selector ) ) {
this.selector = selector;
this.context = document;
selector = document.getElementsByTagName( selector );
return jQuery.merge( this, selector );
//处理: $(选择器, $(...))
} else if ( !context || context.jquery ) {
return (context || rootjQuery).find( selector );
// 处理: $(选择器, 上下文)
// (相当于: $(上下文).find(选择器)
} else {
return this.constructor( context ).find( selector );
}
} else if ( jQuery.isFunction( selector ) ) {
//如果是函数,则执行$(document).ready,这样$(document).ready(func)简为$(func)
return rootjQuery.ready( selector );
}
// 略。
// 如果传入的是一个 Dom列表 ( getElementsByTagName 结果 ) 则转为 jQuery 数组。
return jQuery.makeArray( selector, this );
}
$.extend({
mm: function () { alert('mm'); }
});
$.mm();
$.fn.mm = function () {
alert(this.text());
}
$.fn.extend({
mm: function () { alert(this.text()); }
});
$('h2').mm();
2与3方案一模一样,1与3方案为同一个extend函数,1方案执行宿主会被extend自动判断为不带context的$对象
var opts = $.extend({
val: false
}, options);
返回俩参数合并后的对象,后者覆盖前者 // 可见extend函数有多复杂
贴一下$.extend函数代码:
jQuery.extend = jQuery.fn.extend = function() {
var target = arguments[0] || {}, // 第一个参数是目标
i = 1, length = arguments.length, deep = false, options;
if (target.constructor == Boolean) {// 第一个参数是bool型的
deep = target;// 深度copy
target = arguments[1] || {};// target指向第二个参数
i = 2;
}
// target 是string 型的或?
if (typeof target != "object" && typeof target != "function")
target = {};
if (length == i) {// 只有一个参数?或deep copy 时,两个参数
target = this;// 目标为this
--i;
}
for (;i < length; i++)
if ((options = arguments[i]) != null)
for (var name in options) {
var src = target[name], copy = options[name];
if (target === copy)// 防止死循环
continue;
// 深度copy处理,最深为元素
if (deep && copy && typeof copy == "object" && !copy.nodeType)
target[name] = jQuery.extend(deep, src
|| (copy.length != null ? [] : {}), copy);
else if (copy !== undefined)// 直接copy
target[name] = copy;
}
return target;
};
extend不但支持深度clone,还能支持多个参数的对象clone到一个指定对象,而不是jquery中。
2011-4-28 18:15:45 阅读207 评论0 282011/04 Apr28
这两天完成了前端MVC的完整构建demo,算是一个小里程碑吧。
backbone.js确实是好东西,但还有些别扭的约定,比如el对象的不可控造成设定el的特殊属性比较麻烦。但一切皆权衡,没有完美,总体而言是非常优秀的架构。
模块管理引用了还在pre期间的seajs,非常cool,几乎是我一直以来梦寐以求的架构。相信能借此规避掉很多很多不必要的麻烦。
今天看了完整的underscore.js源码,代码质量相当高。在backbone.js模型中M层个C层都不应该使用jquery,只有在V层才需要它。但js在工具型类库方法上的薄弱还是会很让人头痛,underscore.js是js最好的“tux”,而绝不应该是jquery。
压缩引擎使用closure-compiler,并且使用了IKVM项目在.NET环境中执行,这样可以自动化部署在TFS的team building环节中。
CssGaga功能很强,非常强,但工具的易用性有待加强,至今提交的一个无解bug依然没有回复,不过相信我最终会用好它的,因为它实在太“可爱”了。
2011-3-20 21:28:56 阅读8 评论0 202011/03 Mar20
玩了很多SC2,也看了很多GSL,越来越感受到职业电竞真的是不容易,特别是RTS这种单枪匹马的项目。因为游戏规则的局限性,选手之间的差距可能被无限缩小,一个简单的地图设计或者兵种设计就可以把每天练10小时和练2小时的人差距完全忽略掉,甚至反掉。一个BO3连输掉两场被淘汰后立马就有一堆人说你状态不行了,最近没好好练,开始走下坡路了?blablablabla,搞的你自己都可能开始怀疑自己,我无法想像如果我从事什么职业电竞运动员会在多久时间内崩溃。他们拿了很多奖金?我实在没觉得,有这智商的人去倒卖点小生意赚的不会少,生活还自由,想玩SC照样玩。所以,相比较而言,我作为关注了好多年的电竞观众真的很幸福,电视直播从来都是免费,只挤出10分钟时间看一场选手们要在场下练习上百场才成型的比赛,还有什么好说的呢,,,SC2台服cdkey我买了,国服我也肯定会买的,虽然不对其抱多大期望,plu哪天要交钱看比赛了我肯定也会乖乖交的。最后祝所有坚守电竞行业的人幸福,你们的坚韧和勇气是我无法企及的。
最近比较烦,但我不想责怪任何人,也确实没有理由责怪任何人,还是自己不够,,,那叫什么来着?,,,成熟?
去他娘的。
大概在一年多前,我开始习惯写日记,不是那种写在博客上的“日记”,是写在OneNote中给只自己看还犯贱加了个密码的日记,每天至少一句话(也基本上只有一两句),每周末还会总结一下把觉得写的不错的打个标签方便翻阅。
曾经我以为我的这个做法很成功,人最重要的高级特征之一就是自审嘛。但是现在我发现这很扯蛋,或者说强迫自己自审很扯蛋,自审很可能只能是由内而生的。
我觉得,人之所以活着必须是为了在追求某些东西,这些东西说好听了叫梦想,往俗里面说就是欲望,,,人烦的时候,无非就是感觉自己完全不在追求这些东西的路上,而是被其他乱七八糟的原因牵制住,并且一时间看不到改变现状的可能性。
所以呢,烦就烦吧,因为我也清楚,这只是一时间看不到改变现状的可能性而已,肯定不是永远。太多太多次了,回首以前,一件件大事儿都变成了小事儿,小事儿都成了屁事儿。
PS:就在今天, 我已经下定决心改变了现状。
2011-3-3 17:52:55 阅读12 评论0 32011/03 Mar3
公司项目需要,写的一个web前端分词筛选的模块,大概一年前的东西了,今天想起来把它分离出来,今后要多把工作成果发到博客中,多给自己留点足迹。
http://cid-2dcd432ec78904dc.office.live.com/self.aspx/pub/autodemo.zip
2011-3-3 14:24:46 阅读33 评论0 32011/03 Mar3
Linq章节写的非常清晰有条理,同时也对自己之前长期的理解偏差汗了一下。就在此备记一下:
1.Lambda表达式在预编译阶段就会变成泛型委托的一个匿名实体,这一点很重要,说明linq to sql并不是一撮而就直接翻译为TSQL查询的(虽然VS可以在断点模式直接为我们获取TSQL,至今我对VS依然是拜膜的心态),这也是实现查询参数《预编译linq查询》的基础
2.linq查询返回值并不是那些MSDN中的类型(如IQueryable),而是一类.NET系统级隐式类型,最常用的如where<T>返回的是一个叫做OrderedEnumerable的类,它可以隐式转换为各种可延迟执行查询的类型,如此设计是为了分离用户端(coder)与系统之间的需求耦合,在此又深刻感受到.NET平台优秀的层次设计。
3.因为查询结果的不确定性(可用静态方法封不同装数据源的相同查询逻辑),var是linq的重要组成部分,能大量简化代码,但在除linq以外的场合中原则上不应使用var,它毕竟违背强类型语言的本质。在这个问题上有过纠结,曾经看到实施ASP.NET MVC的团队为了更方便的分离view与control开发而在页面层大量使用var,事实虽然没有完全否定这种做法(项目最终实施的还算可以),但我依然坚持观念,看到本书作者与我一样的想法还是挺安慰的,现在坚定认为即使是编译时的类型推断依然违背强类型语言原则,语言的好坏更多地是看在人的眼里好不好而不是在机器的眼里好不好(执行速度相对比较低效的python获得如此成功不是没有道理),使用此类技术应该仅仅存在于领域语言(DSL,如linq),不适合大范围混搭使用。
4. 非泛型集合类因为没有实现IEnumerable<T>所以没有被扩展linq查询,但却扩展给了一个OffType<T>方法,可以直观地转换为泛型集合类,这也是之前没有料到的,在重构旧系统的时候这个方法应该很有用武之地。
5. linq核心方法Func最多支持16个独立数据源,虽然几乎不可能遇到此瓶颈(之前以为会以二叉树的形式支持无限地数据源)。
耐心看书学习的过程很满足,很充实。如果有机会,很想对以前的自己多劝慰几句:“戒躁,戒躁 …”
2011-2-18 12:02:59 阅读30 评论0 182011/02 Feb18
首先,这里讲的仅仅是是否“需要”,而不是可不可以,以娱乐消遣的心态上豆瓣、QQ空间当然是可以的。
因为今天整理自己浏览器书签的时候看到http://home.cnblogs.com一直放在显要的位置却很少被我访问,所以想起这个问题。
个人经验:在垃圾信息中过滤出有益信息所耗费的精力远远超出想象,所以现在很多公司流行让每个人研究一个课题后教其他人。效率确实很明显,不单是因为有人教,更重要的是在你遇到问题疑惑时(不管是理论还是应用层面)总有一个“专家”解答你。这位专家不一定足够正确,但他一定是足够高效、快速的。至于那些不怎么正确的东西,个人觉得不会是什么大问题,在应用到一定阶段早晚会被你纠正的。
由此我想说:请远离SNS,,,
好多年前,我第一次上CSDN的bbs时,着实被眼花缭乱地标题兴奋到了,我觉得我可以在这地方长期厮混下去。结果确是前前后后我总共发贴不超过10个,回帖没超过20个。
为什么?不是因为他们讨论的技术含量不高不好,只是因为因为太低效了。
这个现象,我觉得其他各类SNS、论坛同样存在。
程序员最好的学习来源应该是这样的(排行分先后):
书、官方文档
身边的同事/朋友
同行博客,当然要做好筛选工作
还有:你自己。在准备上社区寻求帮助前,一定要先寻求自己的帮助
上社区、论坛寻求帮助,只是我迫不得已之举,多数还是因为一些非常诡异的设计、约定或bug所致。所以,还是写好自己的软件,让别人少受点苦吧。
2011-2-7 16:00:28 阅读92 评论0 72011/02 Feb7
在豆瓣上看到的 尊尼获加语路计划,支持一下吧。
其实,也是给自己打气。
我们一定要勇敢,这里的未来是属于我们的。
恰巧看到台湾大众银行今年的形象广告《梦骑士》:
因为梦想,才有活下去的理由,而且一定要好好地活下去,,,
2011-2-5 1:17:02 阅读13 评论0 52011/02 Feb5
我不止一次的在其他场合中表示对云风的敬意,他可以说是国内同行中唯一使我产生敬畏之心的人。原因并非在于他的技术,而在于他的生活。
我以前只能在一些文学圈子了找到这种清澈见底的人性,潇洒、亲松地把身上所有的包袱抖落个干净。这些,一直以来都是我所追求的东西,但回头看看现在的自己,只是一桌杯具。
每年我都会不断地教导自己,哪些是神马,哪些是浮云,哪些才是你真正想要的。但我发现人活着活着就会变贱,不知道什么原因,也许我该找dang国去吧,但我又贱地只敢说不敢做,然后继续蹉跎青春。
说到青春,我一直觉得它就是个P,我说我年轻我就年轻,于你何干?但是这个牛掰的社会就好像宇宙定理一样一次次把你打醒。过年的饭桌上永远都是些闭着眼睛能猜到的话题,而这些话题,都是非常严禁地对应各位的年龄层次的。
好了,让我继续教导我自己:
下一年,我希望我会像乞丐一样追求点自己想要的东西吧。