标签: jQuery

  • 前端框架点评

    前两天被人@,提问前端框架的问题。这还是第一次在微博上被陌生人提问,感觉有点小激动。今天写篇小文章,简单点评一下我用过的前端框架,希望对大家有所帮助。

    本文涉及的范围

    本文要点评的前端框架,都是我用过的,以JavaScript框架为主,也可能包括一些工具类库。由于前端的特殊性,弱语言HTML和CSS是必不可少的工具,运行机制导致很多成熟的工程学方法没法用,必须用工具库补充。烦请大家不要抠字眼,我一向很马虎,呵呵。

    Bootstrap

    一定要先推荐Bootstrap。它由Twitter的两位工程师首创,当前版本2.3.1,涵盖了文本、布局、表单、工具,除了暂时没有日期选择器之外,几乎包含了网页所需的一切。我们知道,网页出现是为了传递信息,而成熟的印刷业对其影响很大,表现出来就是,HTML中很多标签,比如H1~H6p等,都是有具体语义的。但很多前端框架并未给予他们足够的重视,所以往往需要我们重置或者自己动手写。Bootstrap则不是这样。它不仅包含大量组件,还帮助我们给每种可能用到的语义标签都定义了样式,又设计出很多helper;而其网格系统也能帮我们出色完成排版工作。总而言之,使用它几乎足以满足任何网页开发需求。

    值得一提的是,Bootstrap的组件和Widget都基于HTML标签构建,非常好用;而响应用户操作则基于对document的侦听,所以几乎不会对我们其它代码逻辑造成影响,我们可以放心大胆的在项目当中使用。当然,Bootstrap依赖jQuery,后者近期遭遇到一些纷争。不过我还是要强烈推荐这个框架。

    jQuery UI

    比较遗憾的是,虽然号称UI,但jQuery UI只能算作一个组件库。因为缺少基础排版支持,所以既想使用jQuery UI,又想和自己的样式保持一致会有些困难,需要花费不少时间做修改。

    抛开这一点,jQuery UI也是个很好的工具,几个widget都很实用,文档丰富详实,如果项目本身对交互要求不高,只是个别地方需要一些功能补充,jQuery UI确实是不错的选择。尤其当我们需要draggablesortableresizable这几个功能时,选择的余地真的不大。

    HTML5 Boilerplate

    这个工具力图给开发者提供一个舒适的起点。他们为项目建立了标准化的目录结构,并且把常用的资源都整理在合适的位置,这样我们只需要替换它们就能保证项目对所有浏览器都有完美表现。同时,他们重置了CSS,引入了GA统计,在页面中标记了合适的输入点,这样我们能尽快投入到项目逻辑的开发中。

    但这个工具的问题也很明显,它努力达成的目标,是消弭浏览期差异。假如我们只需要统一的环境就能开展工作,那H5B就足够了;而实际上,我们通常需要更多,比如排版、比如组件。所以,这个工具对我来说,学习的意义大于使用的意义。

    HTML KickStart

    我见过的前端框架里只有这个跟Bootstrap的覆盖面接近。它的设计更好,更鲜艳更有活力,不过最近的开发好像慢了下来。我并没有真正使用它,因为它的组件太少了。

    Backbone

    非常好的MV*框架,真的像根脊柱一样,把被jQuery拆的七零八散的js统一在合理的框架内,让整个项目都变得协调了。引入Collection真的很天才,结合其出色的View设计——其实Backbone的View并不是传统意义上的View,更像mediator——可以看出,Backbone的设计者对Web开发有着深刻理解。哦,差点忘了,Router还能帮我们很好的整理单页应用的逻辑。

    不过js毕竟是一门很烂的语言——或者让我换种表述方式,缺陷很多,所以它尚无法做到像AS3的Robotlegs那样好。不过,如果我们希望把代码组织的更好,Backbone类的框架是不可或缺的。

    Rachet

    Rachet的目的和架构,很像Bootstrap,不过它瞄准在移动端。Rachet现在仍处于比较低级的阶段,组件太少,开发起来不太方便,最多相当于Kickstart把。可惜的是,移动端移动框架普遍较弱,在我看来,基于它的Junior仍然是不二之选。

    Zepto

    说到移动端开发就不能不提Zepto。它力图实现一个十分类似jQuery的库,不过只考虑支持移动端,所以体积会小很多,速度也会快不少。Zepto的升级频率最近也不高,不过还是到了1.0。新版Zepto放弃了ruby,使用coffee作为编译工具,支持使用者自由组合功能模块,相当贴心。

    不过具体使用时,还是会有一些函数的用法和jQuery不同,需要注意。举个例子,css函数,jQuery里支持数字,比如$('div').css('height', 100),会把页面中所有div的高度设置为100px;而Zepto不行,必须$('div').css('height', '100px')才会正常工作。

    jQuery Mobile

    强大的jQuery团队最失败的作品。贪恋于风光的过去,迷信“全覆盖”,使得jQuery Mobile步履蹒跚,在移动平台上无法取得足够好的性能表现(早期版本甚至不支持固定底部)。而这直接带来了对HTML在移动端的质疑。有很多本不擅长前端开发的人,看到Phonegap,就直接上jQuery Mobile,结果发现性能不行,体验很差,便在各种渠道大放厥词,说HTML不行。这种行为直接伤害了HTML和Hybrid应用。

    jQuery Mobile失败不仅在于此。jQuery本身方便快捷,使用它很容易养成不重视代码组织的习惯;而在移动端,单页应用占据主流,这意味着,使用jQuery Mobile很可能无法良好的组织代码,直接带来项目维护成本的提高。另外,早期版本的设计也不可避免的带有大量Web痕迹,导致实用性不足。所以直到今天,jQuery Mobile都还是个悲剧。

    不过,jQuery 2.0已经beta2了,我们知道,jQuery 2.0里放弃了对IE678的支持,性能会得到不小的提升;jQuery Mobile 1.3已经引入了对hash的支持,组织代码好多了;同时,随着3次小版本更新,越来越多适用于移动应用的组件加入进来,大大扩充了军备库。我认为,未来的jQuery Mobile,值得一试。

    Sencha Touch

    大家可能还记得,Facebook闹过一阵,说HTML5不够好,还把他们的手机客户端用原生重做了一遍。之后Sencha的两位工程师表示不服,以HTML5为基础开发了功能几乎完全一样的客户端,他们用到的框架就是Sencha Touch。据说,它的性能比jQuery Mobile好不少。

    但是,真正用了就知道,sencha touch实在太不“前端”了。它里面几乎没有给HTML和CSS留下太多位置,明明十分强力的布局样式工具,被封装成了单薄的接口;但是没少往JS框架里加内容。结果就是用起来非常复杂,随时需要看文档;自定义困难,它里面甚至有一个属性叫“html”,用来填入大段文本类型的html;数级嵌套起来的对象也很让人头疼,而且感觉维护也不会太容易。所以我做了一半就还是放弃了。劝大家也别去尝试了。

    如果有哪位高人愿意以实际经验教育我的,我洗耳恭听。

  • 诡异BUG之:IE下表单必须提交两次

    做前端遇鬼是常事儿,比如今天,就遇到个:

    1. IE6~10
    2. jQuery 1.8.3
    3. Backbone 0.9.2
    4. HTML5头
    5. 一个Backbone.View,内部有一个formView托管formsubmit事件,根据classaction进行不同的操作,或者验证数据提交表单
    6. 第一次提交,验证通过,return true,没反应
    7. 第二次提交,验证通过,return true,表单提交
    8. 其它浏览器表现正常

    提炼这些Bug描述就花了不少时间,反复Google也没有什么结果。比如,StackOverflow上类似问题的解答是:submit原本不会冒泡,所以应该直接侦听form;但实际上jQuery1.4之后已经支持submit事件的托管了,我的实验也支持这个结果。

    至于导致问题的原因,我还没想明白也没测出来,留着以后再做吧。最后用Hack的方式暂时解决:

    if ($.browser.msie && isIEFirstSubmit) {
      isIEFirstSubmit = false;
      setTimeout(function () {
        form.submit();
      }, 50);
    }

    有了解这个的高人还请不吝赐教。有感兴趣的同学可以去试试:http://www.dianjoy.com/dev/#/user/updateuser

  • 使用免费CDN加速JavaScript的加载

    做前端的,基本都会用上各种开源的框架、类库。在项目中引用它们,就可能需要把用到的文件纳入版本库,这样每次类库更新,我们也得跟着更新文件,比较麻烦。而且,我们知道,浏览器对同一个域名下的资源同时加载的数量是有限制的,加载页面时光类库的CSS和JS就得搞半天,整体速度也会被拖累。

    好在很多仁人志士已经提供免费的CDN分流服务,帮助我们托管类库。我用到的主要有这些:

    jQuery

    jQuery流行度毋庸置疑,所以微软和Google都提供了jQuery系列,包括UI和Mobile的CDN,Google的CDN还包括一些其它类库,比如prototype和Mootools等。

    微软:http://www.asp.net/ajaxlibrary/cdn.ashx#jQuery_Releases_on_the_CDN_0

    Google:https://developers.google.com/speed/libraries/devguide

    Bootstrap

    Bootstrap是由来自twitter的两名“Nerd”工程师创建的前端框架,非常棒,刚好覆盖了网站页面所需,组合使用无往不利。BootstrapCDN为我们提供了相应的服务:

    http://www.bootstrapcdn.com/

    Underscore和Backbone

    cdnjs.com 这种业界良心提供了最丰富的CDN资源,还包括了每种类库的官网或者其在github上的链接(好吧,很多时候他们就是一回事儿),我觉得甚至可以把这个站点当成学习的出发点。肉大师项目中用到的Underscore和Backbone就取自这里,感谢他们。

    值得一提的是他们的域名也很好记~

  • 使用jQuery托管事件对阻止冒泡的影响

    使用jQuery托管事件对阻止冒泡的影响

    列表范例
    移动App中常见的列表

    jQuery托管事件是个好东西,减少侦听器的数量,还能降低内存泄露的风险,尤其在列表类的应用比较常见。

    想象一个如右图所示的下载列表,点击各列表项会展开详情,用户可以在里面查看详细信息;不展开的话也可以直接点击右边的下载按钮,就会直接下载应用。使用jQuery来写代码大概是这样的:

    $('#app-list li').on('click', function (event) {
      // 显示/隐藏详情
      $(this).toggleClass('active');
    });
    $('#app-list .download-button').on('click', function (event) {
      // 下载通过超链进行
      // 这时为了不让详情展开,需要阻止事件冒泡
      event.stopPropagation();
    });
    

    假如列表里有20个选项,那么这样就会添加40个侦听器。在PC浏览器里这样做问题不大,但是移动设备内存比较少的话可能会引发问题。另外,如果我们还引入了“上拉读取更多”和“下拉刷新”的功能,那么就要为内容的更新添加更多的代码,以避免内存泄露。所以这时,就应当将事件托管到ul去处理。( 关于jQuery事件托管可以参考其文档(http://api.jquery.com/delegate/)。)

    $('#app-list').on('click', 'li', function (event) {
      $(this).toggleClass('active');
    });
    $('#app-list').on('click', '.download-button', function (event) {
      event.stopPropagation();
    });
    

    可以看到,我没有修改事件处理函数。这样做,我们只添加了2个侦听器,并且不管#app-list里的内容如何变化,都不需要重新注册侦听器。这给代码减了不少负。

    不过接下来我发现,点击按钮后,详情仍然会被展开收起,似乎阻止冒泡的代码没有生效。仔细一想,对了,我已经把事件注册到#app-list上了,所有的事件其实都是冒泡上来的,所以点击按钮,冒泡必然经过上层节点。于是继续修改代码,改变事件处理函数的逻辑:

    $('#app-list').on('click', 'li', function (event) {
      // 如果事件始于下载按钮,则退出
      if ($(event.target).is('.download-button')) {
        return;
      }
      $(this).toggleClass('active');
    });
    

    这样便万事大吉了。

  • Backbone.js笔记

    关于事件

    • 使用Backbone里,我们可以继承Backbone.View,并且侦听UI事件。这些操作是通过jQuery或者Zepto的事件委托实现的,所以很重要的一点就是:这些事件都是UI事件,loaderror这些事件是无法在events属性里注册并被侦听到的。
    • 因为是托管的事件,事件处理函数最好用event.currentTarget来寻到节点
    • model的事件都会被collection转发,所以可以直接侦听collection;同理,除非remove并等待垃圾回收的model,也不应简单的调用off(),因为这会使collection没法侦听到事件,漏掉一些处理。

    路由解析规则

    这点文档中说得不算太详尽,我摸索如下:

    1. 路径分析以#/为起始,所以链接应该如#/app/add
    2. /是很重要的分隔符,末尾的/会被认为有下一级参数,比如app/list/的规则就不适用于http://domain.com/#/app/list这样的路径
    3. 规则只匹配一次,不会多次执行
    4. 刷新页面的方法:
      Backbone.history.loadUrl(Backbone.history.fragment);

    其它关于Backbone.js的文章

    Backbone.js经验两则

    重写Backbone.js的加载动作

  • 使用PhoneGap+jQuery Moblie开发蜂鸟镜头库手机App

    蜂鸟镜头库app效果图
    蜂鸟镜头库app

    自从春节期间在家尝试了PhoneGap之后,一直想做点实际的东西,好总结点经验,以备不时之需。可惜后台苦手,数据源是个问题。后来想起来以前做蜂鸟镜头库的时候有两个接口,可以取得完整的数据,于是便动起手来,开始做这个app。

    开发本身并不复杂,大概花了一天时间搞出雏形,加上翻页基本就能发布了。不过还是遇到不少问题,今天简单总结下踩过的坑,以免以后再踩。
    (更多…)

  • 诡异的Chrome插件事件机制

    最近尝试开发Chrome插件,自然使用JQ来当基础。结果遇到一个问题:

    我使用“程序注入(Programmatic injection)”的方式执行代码,试图实现自动填写表单的功能。因为目标网页的表单比较智能,前面的选项会影响后面选项的内容,所以必须在val(value)之后广播change事件来触发后面表单内容的填充。

    结果失败了。直接在浏览器里使用控制台运行代码,没有问题,所以代码本身应该正确;确认需要的JS文件已经一一加载。于是我开始了漫长而挫折的调试之路。多次失败之后,我打开《英雄无敌三》换换心情……玩了一会儿游戏意外退出了,而我灵机一动,会不会是JQ广播事件的问题?在控制台调试没有问题,但是在content script里就不行,很可能是chrome把两段代码放在彼此隔离的环境中运行导致的。于是我放弃直接$(selector).change(),改用原生的dispatchEvent,结果,运行成功!

    于是我猜,应该是JQ和Chrome的插件机制稍有冲突。可能以后做插件的话,还是Closure Library好些吧。

    PS:写插件的好处是不用考虑兼容性,朝着Chrome写就行了。

  • JavaScript实现命名空间(绑定在jQ)

    不支持命名空间一直是JS开发里比较严重的问题。不过大家想出了各种手段来绕过这个坎,比如YUI的namespace。可惜的是jQuery尚未提供一个合适的解决方案,不过这并不难,可以人肉给它添加这个方法。稍加搜索,找到两个地址介绍此方法,附在最后。

    (更多…)

  • 使用Aptana进行基于jQuery框架的开发

    慢慢的,Aptanta Studio已经升级到3.0.6,新版本具体更新哪些内容我也没在意——我只是追新而已——不过我终于发现了增加类库支持的方法。

    Aptana Studio 2.0的时候,要使用什么类库就直接添加引用(Reference)就好了,非常方便;和其它开发工具同类型的操作方式也很相似,用起来很舒服。可是3.0升级后取消了这一功能,搞得大家很不适应,开发者承诺会让这个功能回归,结果确是另一副样子:添加对应sdocml文件到项目当中,而且得是物理添加,但是在我的环境中怎么搞都不成功。

    从3.0.4起Aptana增加Start Page,介绍一些Features和Bug修复信息。我就是从里面的“Adding JavaScript libraries to your projects”了解到上面功能的。这次升级后我随手点开,发现“JavaScript Library Support”指向的是另外一个地址,里面提到,从3.0.5之后,可以直接通过添加包的方式来增加jQuery类库支持,方法如下:

    1. Commands > Install Bundle > jQuery
    2. 右击项目,选择Properties > Project Build Path,然后勾上jQuery 1.6.2的复选框
    这样操作起来简单得多了。
    PS:3.0.6之后,不再需要步骤2
    PS2:在“Install Bundle”时我还发现其它一些包,比如WordPress和Github,有机会试用一下。
  • 推荐很好用的jQuery UI

    jq用的很多,有天闲来无事在jq官方网站上闲逛,偶然发现他们还做了一套自己的组件库,并且提供多种不同的皮肤,甚至支持自行搭配输出特定组合的组件库。于是赶忙试用,发现效果非常不错。

    地址:http://jqueryui.com/

    jqui继承了jq一贯的简单实用,涵盖绝大部分可能用到的功能,比如拖拽、排序、缩放、各种效果;并且提供各种功能的demo,使用的时候看一遍demo找到想要的功能然后直接查看源码,简单方便。比如我想让某个窗体可以通过顶部进行拖动,只需要$(‘#window).dragable(‘.titlebar’);即可。

    不过resizable就必须容器有ui-widget-content这个class才行。