jQuery源码阅读(八):事件-基础

Author : lovecicy

JavaScript是一种事件驱动型的语言,事件是JavaScript的基础,jQuery的事件无疑也是jQuery的核心之一。jQuery是强大的,jQuery源码是复杂的。一直觉得看jQuery源码是要勇气的,而要看事件处理的源码,更是需要勇气,都已经解读到这里了,就让我们硬着头皮上吧。jQuery中关于事件的代码有多少呢?从2650行一直到3669行,整整1000多行的代码,慢慢来吧。 这一篇,将不会涉及到太多源码的东西,更多的是对jQuery事件的一些基础介绍。关于事件,我之前写过一篇JavaScript事件的文章,里面简单介绍了JavaScript的事件基础知识,有兴趣的可以先看看这篇文章。而关于jQuery的事件处理方法的总结,也有之前的一篇文章——jQuery事件处理方法小记。 关于事件基础,看完上面两篇,其实应该对事件的使用没什么问题了,但是这样以来,这篇文章的篇幅就……所以,让我们再来看看另一个话题吧:jQuery是如何处理事件的。 我最熟悉的看代码方式就是,从我们平时用的接口入手,一步步剖析代码,这次也不例外,由于所有的事件绑定最终都是通过.on()和.off()两[Read More]

standard

jQuery源码阅读(七):Deferred API(下)

Author : lovecicy

上一篇,我们讲到了Deferred对象,让我们来看看如何使用它吧。 好了,最简单的用法就是这样。但是在现实中,这么干完全没意义。那么,来点有意义的代码吧。 这是Deferred对象(准确的说应该是promise对象)最常用的用法,非常实用,而且方便,能够为AJAX请求绑定多个回调函数。 再来看看复杂一点的情况,如果我们需要通过多个请求获取数据,然后同时对这些数据做一些操作呢?很自然得,我们会想到可以这么干: 我们可以尽情的嵌套AJAX请求,jQuery都能正常执行。但是这么干有个缺陷,就是浪费时间,这两个请求之间是没有依赖的,这样写仿佛第二个请求依赖第一个请求的结果了,本来可以并行的请求,现在只能通过串行的方式了。 这个时候,我们的$.when()闪亮登场了。先来看看jQuery的文档怎么说: Provides a way to execute callback functions based on one or more objects, usually Deferred objects that represent asynchronous events. 所以上面的例子可以改为:[Read More]

standard

jQuery源码阅读(六):Deferred API(上)

Author : lovecicy

聊完了Callback API,接下来我们来聊聊Deferred API吧。 一、什么是Deferred API? 按个人的理解,Deferred API是用来实现一下功能的:某个事件的执行过程是异步的,需要等待一段时间,这时我们可以把这个事件称作延迟事件,我们用一个Deferred对象来表示它,为它添加成功、失败以及正在处理中的事件处理方法,当事件成功或者失败后,调用对应的处理方法。比如要通过AJAX获取一段内容,这个过程需要一定时间,在这段时间内我们不应该阻塞后面代码的执行,而是返回一个Deferred对象,为它添加成功与失败的回调函数,然后让代码继续执行。如果AJAX调用成功,则执行成功的回调函数,比如改变界面显示;如果AJAX调用失败,则调用失败的回调函数,比如提示用户获取内容失败。 二、谁在用Deferred API? 在jQuery内部,有以下功能使用到了Deferred API: AJAX 动画 DOM Ready $.fn.promise() 三、拆解Deferred API Deferred API的代码量还是比较少的,总共才80多行,但是信息量还是挺大的,这里我们分[Read More]

standard

jQuery源码阅读(五):Callback API

Author : lovecicy

上一篇讲述了jQuery Callback API的一个bug,这一篇我们言归正传,来介绍一下Callback API。 Callback API于1.7版本引入,它提供了一种强大的方式来管理一系列的回调函数,可以添加,删除,触发或者停用回调函数。 可能我们在平时使用中不太会用到Callback API,但是在jQuery内部,Callback API可是发挥了很大的作用的。在jQuery的Ajax API和Deferred API中都有用到,而我们的$(calback)方法,依赖于Deferred API,其实也是依赖Callback API的。而且,在平时我们自己写代码的过程中,我们同样可以用Callback API来管理我们的回调函数。 交代完了它的背景,让我们来看看真实的代码吧。 其实在写这篇文章前,我已经看过了前端狮子对于Callback API的解读,虽然我们解读的并非同一个版本的jQuery,但是狮子的文章在一定程度上帮我理解了这部分代码,并且狮子的解读与文章或多或少对我的解读产生了影响,所以,在写这篇文章时,我的内心也在纠结,如果写出类似的文章,那写的意义何在;而如果不[Read More]

standard

jQuery源码阅读(四):jQuery Callback的bug

Author : lovecicy

这两天在看jQuery Callback API的代码,无意中发现了一个jQuery的bug,这个bug存在在目前所有的主流版本中,除了最初引进Callback API的1.7版本,从1.8到2.1,都存在。 先来说说这是一个怎么样的bug,看下面的代码: 在jQuery的文档中是这么描述disable()方法的: Disable a callback list from doing anything more 因此,执行disable()方法后,对这个Callback对象的所有操作都应该被禁止了。但是如果在调用disable()之前,没有调用fire(),那么通过调用empty()方法,我们可以重新添加callback函数,然后成功调用fire()方法。之后,虽然add方法可以再次被调用,但是无法再成功调用fire()方法。 我们可以直接从代码入手,看看这个问题的原因: 当我们调用fire()的时候,在内部实际上是在调用fireWith()方法。而fireWith()能被成功调用的前提是list存在,并且fired为false或stack存在。而disable()被调用以后,list[Read More]

standard

jQuery源码阅读(三):jQuery DOM Ready

Author : lovecicy

一直以来,各种JS最佳实践都会告诉我们,将JS放在HTML的最后,即</body>之前,理由就是:JS会阻塞下载,而且,在JS中很有可能有对DOM的操作,放在HTML的最后,可以尽可能的保证JS的执行在DOM加载完成之后。而如果放在onload事件中执行,如果页面有很多图像,那么页面的onload事件要过很久才会触发,因此DOM Ready事件就是最好的执行JS的时间了。 所以,如果有个DOM Ready事件就好了,虽然现代浏览器已经支持DOMContentLoaded事件,但是我们还是得处理那些老旧的浏览器,于是DOM Ready事件就成了各个JS框架的必备功能啦。 先来看看jQuery DOM Ready事件的用法吧,jQuery的DOM Ready事件用法很简单,大家都用过,下面的三种语法都是可用的: $( document ).ready( handler ) $().ready( handler )(不推荐) $( handler ) 还有一种方式:$(document).on(‘ready’, handler);,已经在1.8版本里被废弃了,但是你还可以这么用。[Read More]

standard

jQuery源码阅读(二):jQuery方法

Author : lovecicy

第一篇介绍了jQuery对象,这一篇来看下jQuery对象是怎么生成的。下面的代码是生成jQuery对象的源码,我把用到的代码取了出来,加了注释: 前面正则的示意图: /^<(\w+)\s*\/?>(?:<\/\1>|)$/ /^(?:[^#&lt;]*(&lt;[\w\W]+&gt;)[^&gt;]*$|#([\w\-]*)$)/ 下面来看一下init函数中接受的参数类型: null, undefined, false, “”这些为空的值,直接返回this DOM Element, 单个的DOM元素,则将context和jQuery对象的第一个元素设为DOM元素 字符串 HTML Tag或未指定context的ID选择器 未指定context或context为jQuery对象 指定了非jQuery对象的context,等同于$(context).find(expr) 函数,等同于DOM Ready,亦即$(document).ready(fn); HTML Collection或者jQuery对象,如果是[Read More]

standard

jQuery源码阅读(一):jQuery对象

Author : lovecicy

开篇先来讲述一下平时使用最多的jQuery对象到底是什么。(这里的jQuery对象指的是$(selector)返回的对象) jQuery最擅长的就是DOM操作,也是其流行的原因之一,用$()方法选择要操作的DOM元素,然后进行各种操作。 以下面的代码为例: 无论是通过标签名选择多个元素还是通过ID选择唯一的元素,只要元素存在,上面的代码总能正确得输出’li’,而且length也是正确的。 这么看来,jQuery似乎返回了一个数组,到底是不是,我们可可以通过下面的方法检验: 所以,jQuery其实返回了一个对象,而非数组。 让我们再来看下这个对象的结构: q.fn.q.init[3] |- 0: li#test |- 1: li |- 2: li |- context: document |- length: 3 |- prevObject: q.fn.q.init[1] |- selector: ‘li’ 原来就是一个拥有length属性,并且属性名为数字的对象,而非数组,大家都亲切的称它为类数组对象 -_-! 。 好了,知道了这个对象的[Read More]

standard

巧用JS数组方法

Author : lovecicy

当我们用jQuery选择元素之后,如果要取到第一个元素,我们会用类似下面的方法 $(‘div’)[0]; 很自然的,我们会以为jQuery返回的是一个所有符合选择器条件的DOM元素的数组,因为我们不但可以通过$(‘div’)[n]这种方式获取,也可以获取jQuery返回对象的length属性。但是今天看了篇文章,发现其实jQuery返回的是一个对象,而不是数组。我们可以通过$(‘div’)[0]这种方式获取是因为jQuery对象在模拟数组对象。 看了些网上的文章,发现jQuery这种做法其实是对数组方法的巧妙使用,我们来看下面的代码: var aPush = Array.prototype.push; var testObj = {0:’a’,1:’b’}; testObj.length = 2; aPush.apply(testObj, [‘c’,’d’]); console.log(aPush); 查看控制台,可以看到下面的输出: Object {0: “a”, 1: “b”, 2: “c”, 3: &#822[Read More]

standard

监听输入框的实时变化的解决方案

Author : lovecicy

在做文本输入的时候,会碰到需要检测输入框实时变化的事件。除了blur、keyup、keydown事件,并不能完全满足我们的要求,比如用户持续按一个键,只会触发一个keydown事件,但是会输入很多字符。这时候就需要用到oninput和onpropertychange事件了。 oninput是HTML5标准事件,但是旧版的IE(<IE9)并不支持,不过IE也提供了专有的onpropertychange事件来监听输入框的变化。 oninput事件在检测 textarea, input:text, input:password 和 input:search 这几个元素内容变化时非常有用,在内容修改后立即被触发,不像 onchange 事件需要失去焦点才触发。 各浏览器对oninput的支持情况: Chrome (yes) | FireFox 2 | IE9 | Opera 10 | Safari (yes) 用jQuery实现的代码如下: $(selector).bind(‘input propertychange’, function() { //do something }); 不[Read More]

standard