tuy

移动开发js框架Zepto.js注意细节

注意,本文撰写时 Zepto 版本为 1.0 正式版

由于自己一直希望从事HTML5的开发,包括2013-2014年一直自学,然后也在同年帮乐道科技承接了三个手机项目的前端开发,最后在2015年初离开中控科技,开启自己的移动HTML5之旅;
入职初期, 承接了一个HTML5 微信公众平台项目,开发中使用了Zepto这个著名的 DOM 操作库(感谢浙江万里学院传媒学院的同学-李建超,是他最早推荐给我这款js库).
它给我的第一印象是尺寸,大家看下图:

1

笔者从2011年开始使用jQuery,已经4年的习惯了,为什么这次又要选择Zepto呢,如图,这是在我电脑本地的截图尺寸,如果使用服务器端 gzip 压缩后大小只有5~10K,这对于使用2G网络的手机用户来说,真的速度会提高非常多,虽然我们现在都是4G了….好像几十KB也没感觉,但我们还是假设有很多2G的小伙伴吧…

继续,因为 jQuery 的目标是兼容所有主流浏览器,这就意味着它的大量代码是在处理PC端的query或者动画。而 Zepto 只针对移动端浏览器编写,效率更高,更重要的是,Zepto的选择器语法跟jQuery非常类似,学习成本低低低!

但是在这次微信公众平台建设过程中,我发现Zepto还是有很多注意细节,整理记录了一些个人碰到的问题,以及自己的解决方案,欢迎评论,留下您认为更好的思路,我们一起探讨。

在jQuery中响应鼠标点击只有一个click事件,而Zepto里面有tap跟click两种,不能混用,在特殊情况下会出问题。在手机端的网页,click 事件有 200~300 ms 的延迟,为了更快的响应,最好用 Zepto 提供的 tap 事件,不相信的话,可以用以下代码测试一下

var t1,t2;
$(el).tap(function () {
t1 = (new Date()).getTime();
});
$(el).click(function () {
t2 = (new Date()).getTime();
(t2 - t1);
});




承接上面描述的延时,我们来简单聊聊这个到底是什么,如果引用专业术语的话,这种现象叫'点透'。部分移动设备(包括iPhone)在手指离开屏幕后的200~300 ms,才会找到用户点击的位置,再去触发对应位置最上层元素的click(这个延迟是因为移动设备要确定用户这次触摸屏幕是一次单击还是双击,如果是双击,并且网页头部meta标签里面没有设置user-scalable=no的话,就会将页面放大)

在一些关注交互的场景下,这个300ms会让用户感觉觉得页面响应慢不流畅,许多开发者追求用户体验,使用各种方法让click事件在用户手指一离开页面就触发,zepto的tap事件就是目前能快速响应点击的两个主流库之一,还有一个是fastclick。
tap事件,通过触发目标元素所绑定的tap事件,以达到快速响应的目的。平常使用过程中这样就够用了。但是当你用在特殊交互的时候,你会发现有些不该点击的事件被发生了,对,这里是被动的。

如上图,当我点击智慧医疗的删除菜单时,我的本意只是删除当前菜单,实际情况却是,我不仅删除了菜单,而且第二课堂也被我点击了一次;这就是点透现象,第二课堂的二级菜单默认隐藏的话,就会在这时候展开。后来我查看代码,原来我在删除菜单的地方使用tap,而在下面的二级菜单触发位置又使用click,导致了延时,后来统一改成tap就正常了。

研究zepto的源码发现,它对click没有做特别的处理,tap的实现是通过在body上的touch事件来完成模拟,当有touch事件冒泡到body时,touchstart到touchend手指没有产生位移,就认为是一次tap,然后触发目标元素绑定的tap事件。所以没办法对目标元素的touch事件执行preventDefault来阻止默认的click事件发生(touch事件执行prevenDefault阻止click触发 这一方法,在一些浏览器和html容器中并不完全支持,ios是完全支持的),除非对每个绑定tap的dom都绑定一个touch事件,阻止默认click的发生,这样做成本有点大,而且容易被用户覆盖掉。所以zepto在触发了tap事件后300ms会继续触发click。这样的话如果一旦被tap的元素在300ms内消失(tap事件中令这个元素立马隐藏或者删除了),原点击位置最上层的元素就会触发的click事件。

所以最好一个网站中tap和click不要混用,用了tap就统一使用tap。

看起来好像只要页面统一使用tap事件,click即便触发,也没有对应函数执行,那就不会有问题了。实际上并不是。如果这个位置的元素是有浏览器自带的click默认函数呢?比如是一个input text框,那么就会跳出软键盘;或者一个a标签,那么就会直接页面跳转。

Zepto 对 CSS 选择器的支持,郑重提醒:


:visible :checkbox :last

这些我们在 jQuery 里面经常使用的选择器,Zepto 不支持!原因很简单,jQuery 通过自己编写的 sizzle 引擎来支持 CSS 选择器,而 Zepto 是直接通过浏览器提供的

document.querySelectorAll

这个接口只支持标准的 CSS 选择器,而上面提到的那些属于 jQuery 选择器扩展,所以仔细看看这个网页,注意一下这些选择器。当然也有好消息,就是上面提到的 selector 模块,如果有这个模块的话,能够支持 部分 的 jQuery 选择器扩展,列举如下:

:visible :hidden
:selected :checked
:parent
:first :last :eq
:contains :has

元素的尺寸计算

首先 Zepto 没有 .innerHeight() .outerWidth() 等四个方法,其次,它的 .height()/.width() 方法也不完善,对于display:none的元素,计算出的高宽都是 0,而这在 jQuery 里面是没有问题的,因为 jQuery 针对这种元素,会先设置其 css 样式设置为

position: "absolute", visibility: "hidden", display: "block"

计算完高宽后再恢复,参见https://github.com/jquery/jquery/blob/master/src/css.js#L460

如果遇到这种特殊情况,可以参考 jQuery 写一个类似的方法

.prop() 方法的陷阱,有次我要把一个文本框置为只读,写了这么一行

$('#text').prop('readonly', true)

结果死活不工作,找了半天才发现,正确的写法是这样

$('#text').prop('readOnly', true)

,如果你居然看不出两者的差别,那么悄悄提示你:注意大小写!翻了一下相关的文档,原来只读属性的正确拼法确实是 readOnly,可是在 jQ 里面上一段代码却能正常工作,原来它已经在内部帮我们转换好了!

于是到 jQuery 源码里面一找才发现,还有这么一段https://github.com/jquery/jquery/blob/master/src/attributes.js#L466

jQuery.each([
"tabIndex",
"readOnly",
"maxLength",
"cellSpacing",
"cellPadding",
"rowSpan",
"colSpan",
"useMap",
"frameBorder",
"contentEditable"
], function() {
jQuery.propFix[ this.toLowerCase() ] = this;
});

从这里也能看到,jQuery 的成熟度真是难以超越,因为他把我们都惯坏了……

.show() 的动画效果,如果没有 fx_mehods 模块的话,.show() 方法是不支持动画的,不过有了这模块后,动画的支持还是有点小问题,比如这么一段 HTMl test

如果你调用

$('div').show('fast')

那么动画完成后你看到的不会是一个半透明的元素,而是全黑不透明的,因为 Zepto 的 .show() 动画实现的很简单,没有高宽的变化,而是将透明度从 0 逐渐变为 1,所以元素上原来设置的透明度就被替代了。这种情况下,可以用 .fadeIn() 方法来替代 .show()

.animate() 的动画效果也是不支持的,如果你执行下面的代码:

$('div').animate({left:'100px'});//Uncaught TypeError: $(...).animate is not a function

就会直接报错,但是这在jQ框架里面又是完全支持的方法,幸好现在css3的动画已经支持的比较不错了,简单的动画效果完全可以配合keyframe或者transition直接在css里面去实现了。 

小结:  

整理到这里大家应该也都感觉到zepto确实轻量,但是在移动的复杂开发中,还是有很多注意事项的。现阶段我自己的话后续复杂的项目估计还会考虑继续使用jq框架,一些简单的h5项目也会继续采用zepto,然后继续学习zepto,古人有云良臣择木而栖,zepto跟jQ都是好框架,就看我们怎么去使用啦!

码字很辛苦,转载请注明来自tuy博客《移动开发js框架Zepto.js注意细节》

评论

  1. 高老庄的呆子 #1

    :!: 辉弟现在哪里高就啊?

    回复
    2015-06-16
    • admin
      admin

      @辉哥,在杭州一家做微信H5开发小公司打工 :roll:

      回复
      2015-06-16
  2. wocao
    wocao #2

    wocao

    回复
    2015-07-1
  3. xiaohuihui
    xiaohuihui #3

    :mrgreen:

    回复
    2015-07-2