jQuery进阶,$.Deferred() 延迟对象

JS里面有大量的异步方法,写着写着,代码就会变得>>。多层嵌套的回调,很影响后续代码的维护,也许今天你还记得这块回调逻辑,明天你就很有可能被这回调姿势给坑了。

那么,今天就介绍一种抹平回调的方法,jQuery.Deferred。

$.Deferred() 是什么?

$.Deferred() 从字面上理解,就是一个延迟对象。它是jQuery出的,为了解决回调嵌套,方便开发者的一种函数。

好像好高深,其实我们很早就有接触,并经常在用到。

jQuery的$.ajax()本身就支持Deferred,它可以链式补上 .done()  .fail() 等方法来处理不同状态的结果。

$.Deferred()有什么用?

例如动态获取一张图片的宽度

当调用 getImgWidth() 的时候,其返回值没法获取到正确的宽度,而随后当图片加载完成触发load事件后,alert出来的宽度才是正常的。

那么,我们改怎么修改这个方法呢?

这段升级后的函数,再获取的宽度的时候,就可以使用如下方法轻松获得

看完这段改造后的代码,也许有人会说,这个作用不大呀,和直接给 getImgWidth(callback) 加多一个回调函数没什么区别。

嗯,从这里来看,貌似是这样,但是,当我们要同时处理多个异步的时候,$.Deffered()的威力就体现出来了。

比如,需求是同时加载完两张图片,得到两个宽度之后,才开始执行后续逻辑。

传统的回调要怎么写?反正我是晕了。

用$.Deferred()就很简单,getImgWidth()的定义不变,使用$.when()方法来处理同时完成的事件。

怎样,有没发现突然晴空万里,以前的业务逻辑里面各种为了解决多个异步条件的setTimeout()是不是瞬间变得很没用。

$.Deferred() 小结

拥抱Deferred,抛弃那些不可控的setTimeout()吧。

最后引用阮一峰的《jQuery的deferred对象详解》里面的小结吧:

  • $.Deferred() 生成一个deferred对象。
  • deferred.done() 指定操作成功时的回调函数
  • deferred.fail() 指定操作失败时的回调函数
  • deferred.promise() 没有参数时,返回一个新的deferred对象,该对象的运行状态无法被改变;接受参数时,作用为在参数对象上部署deferred接口。
  • deferred.resolve() 手动改变deferred对象的运行状态为”已完成”,从而立即触发done()方法。
  • deferred.reject() 这个方法与deferred.resolve()正好相反,调用后将deferred对象的运行状态变为”已失败”,从而立即触发fail()方法。
  • $.when() 为多个操作指定回调函数。
  • deferred.then() 有时为了省事,可以把done()和fail()合在一起写,这就是then()方法。

使用jQuery.data()查看元素上绑定的事件

最近遇到一个诡异的问题,发现我添加在一个HTMLElement片段上面的事件绑定,会在后续的流程中,无故丢失了。但是,我不知道它是什么时候丢失的。

所以我需要要一步步逼近定位到问题。

最先想到的是浏览器面板上面的,可以选中元素,看元素上面的事件绑定。

但浏览器上面看到的是结果量,也就是看到的是已经丢失了事件的元素,但我还是不知道什么时候丢失的。

估一路断点,观察、回溯调用栈(Sources面板右侧的Call Stack)。

然后问题来了。

我可以断点取到每个阶段的HTMLElement元素的状态,但是,这个时候,我却找不到观察其事件绑定情况的方法。

谷歌好久,发现JS原生是没法查看事件绑定情况的。

还好,我们都是用的jQuery,用的$.on()。

而jQuery自身事件绑定,额外添加了一层事件数组。(也是这个原因,$.on()可以重复给一个元素的同一个事件绑定多个handler,而直接addEventListener则只能绑定一个,后面的会覆盖掉前面的)

扯了这么多,show me the code:

然后,就会返回这个元素上面绑定的所有事件。如下图

jQuery.data(‘events’)

检测是否IE

从jQuery的jQuery.browser里面拿出来的,jQuery从1.9开始废弃这个方法,改用jQuery.support来检测浏览器支持的特性。

jQuery的说法是,使用 navigator.userAgent 检测不准确,容易被伪造欺骗。

但我还是觉得,这玩意检测成本低,挺有价值的。至于开发者去伪造它,就让他们伪造去,我只是用来做比较暴力的降级处理。

PS:

预告,下篇文章分享一下使用Git的Branch来维护同一个项目中的差异化代码,最近一个项目用到,挺管用的。

jQuery validate 表单验证插件

最近写了两个组表单提交的页面,好久没用jQuery,在写的时候总遇到一些莫名其妙的为难题,这里记录一下。

如果表单通过前端JS来先做预判断,然后通过JS来post到后端脚本的,则表单form标签可以不填action和method等信息。

validate初始化部分

validate验证、提交部分

之前一直没写return false,导致总是出现个问题,例如alert()会一闪而过,后台会记录两次提交的,提交有时GET给了表单页面自己等…

后来怀疑是submit()的问题,查了一下手册,才发现有这么个东东。

jQuery Select菜单二级联动

应用:

参考地址:
http://wlog.cn/javascript/jquery-select.html

但文中代码只是在UI上实现了要求,在功能上,还会遇到问题。

假如这是一个表单,那么,在提交的时候,POST里面,会有多组city所对应的值。

解决方法:

1、给city所在的select去掉name标签,使其无法提交到POST
2、给选中的city的select添加name标签,使其该选中的city的值可以通过POST等方法进行传递

代码重现:

通过该方法,POST中就会得到city的唯一值