续,非DOM操作的部分,这里提供了很多小工具,但精华的部分还是关于回调对象和延迟对象。

AJAX事件

全局/辅助方法

  • jQuery 全局 Ajax 事件的所有处理程序,必须附加到 document

    无论哪一个 Ajax 请求被发送,所有 Ajax 全局处理器都将被执行

    $.ajax()$.ajaxSetup() 调用时,global 选项设置为 false 时将不触发全局事件

  • .serialize(JQ对象).serializeArray(array)$.param(obj) 均用来序列化格式:

    $.param(obj) => URL查询字符串或 Ajax 请求
    .serializeArray(array) => 返回 JSON 格式的字符串
    .serialize() => 将表单元素的值编译成字符串

接口及快捷方式

  • 由于浏览器的安全限制,大多数 Ajax 有同源政策限制:该请求不能成功地检索来自不同的域,子域或协议的数据
  • $.get(url [,data][,success(data,textStatus,jqXHR)][, dataType]),相当于

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $.ajax({
    url: url,
    data: data,
    success: success,
    dataType: dataType
    });
    $.get('test.html', function (data) { // 最常见用法
    // do something...
    });
  • $.getJSON(url [, data][, success(data, textStatus,jqXHR)]) 请求 JSON 编码数据

  • $.getScript(url [, success(data, textStatus, jqXHR)]) 请求 JavaScript 文件
  • .load( url [, data] [, complete(responseText, textStatus, XMLHttpRequest)])
    $('#result').load('ajax/test.html');
  • $.post(url [, data] [, success(data, textStatus, jqXHR)] [, dataType])
    1
    2
    3
    $.post('test.php', { name: 'John', time: '2pm' }, function (data) {
    alert('Data Loaded: ' + data);
    });

核心及其他

jQuery对象

  • jQuery()
    • 等价于 $()
    • $(selector [, context]) 通过提供的选择器检索 DOM 元素并返回 jQuery 对象
    • $(this) 可调用 this 指向元素的 jQuery 方法
    • $('span', this) 等价于 $(this).find('span'), 用来为检索元素做限制范围
    • $(原生DOM) 将原生 DOM 转换成 jQuery 对象
    • $('HTML') 将 HTML 转换成 DOM 元素

如 jQuery 对象为空,则 .length 属性为 0,可用于检测 jQuery 对象是否为空

当 HTML 为没有属性的简单标签,一般调用原生 .createElement(),其他情况用 .innerHTML 机制,在此过程中,浏览器可能过滤掉某些元素如 <html> 等。此外 jQuery() 要求 HTML 字符串是以 < 开头的字符串(即文本节点不能出现在HTML字符串前面)

  • jQuery.noConflict([removeAll]) 判断是否从全局作用域中内去除所有 jQuery 变量(包括 jQuery 本身)

    1
    2
    3
    4
    5
    6
    7
    jQuery.noConflict();
    (function ($) {
    $(function () {
    // 继续使用 $ 代表 jQuery
    });
    })(jQuery);
    // 其它库可以使用 $
  • jQuery.when(deferreds) 执行一个或多个对象的回调函数,Deferred(延迟)对象通常表示异步事件

实用工具

  • $.each() 遍历一个数组或对象(原生或 jQuery)
  • $.inArray() 返回一个值在数组中的索引位置。如果该值不在数组中,则返回 -1(类似原生 .indexOf() ,使用严格比较 ===
  • $.trim() 去除字符串两端的空格
  • $.map(array, callback) 将一个数组中的所有元素转换到另一个数组中并返回(结果和原数组长度不一定相同)
  • $.grep() 返回数组中符合筛选的项,不影响原数组
  • $.makeArray() 将类似数组的对象转化为普通数组
  • $.type() 判断对象的类别(函数、日期、数组、正则等)
  • $.isFunction() 判断是否为函数
  • $.isArray() 判断是否为数组
  • $.isNumeric() 判断是否为数字
  • $.isWindow(obj) 判断是否为 window 对象(一般用来确认是否为浏览器窗口操作),
  • $.isXMLDoc(node) 判断是否为 XML 节点
  • $.isEmptyObject() 判断某个对象是否为空(不含包括原型内的任何属性/方法), 而 $.isPlainObject() 判断某个参数是否为用 {}new Object() 建立的对象
  • $.extend() 将多个对象,合并到第一个对象, $.merge() 合并两个数组内容到第一个数组(这两个方法均会改变第一个对象/数组)

    var newArray = $.merge([], oldArray); // 用作拷贝方法

  • $.contains(container, contained) 检查弟二个 DOM 元素是否为弟一个 DOM 元素(原生 DOM)的后代

  • $.noop() 返回一个空函数
  • $.now() 相当于 new Date().getTime()
  • $.parseJSON('JSON') 解析严格的JSON返回JS对象, $.parseXML('XML') 解析XML, $.parseHTML('HTML') 将字符串解析到一个 DOM 节点的数组

DOM元素方法及内部构件

  • .get([index]) 检索匹配 jQuery 对象得到对应的 DOM 元素, 指定了 index 参数则会获取单个元素(类似$('selector')[index],但可以指定负值)
  • .index().get() 正好相反, 接受节点返回其索引值
  • .toArray() 返回一个包含 jQuery 对象集合中的所有 DOM 元素的标准数组。
  • $.fn.jquery 返回当前使用 jQuery 的版本
  • .length.size() 均为返回 jQuery 对象中元素的数量

回调对象

jQuery.Callbacks() 函数返回一个全能的对象,此对象对管理回调列表提供了强大的方式。它能够增加、删除、触发、禁用回调函数

回调对象类似于保存了一个回调函数列表,使用 fire 方法时,将会按列表顺序分别传入参数调用这些函数

  • 回调对象的方法,这些方法均返回绑定它的那个回调对象 this 以实现链式调用

    • callbacks.add( callbacks ) 用来向回调列表中添加一个回调或回调的集合
    • callbacks.remove( callbacks ) 从回调列表中删除一个回调或回调集合
    • callbacks.fire( arguments ) 传入指定的参数调用所有的回调
    • callbacks.disable() 禁用回调列表中的回调
  • $.Callbacks( flags ) flags 的参数代如下(参数可同时传入多个,类似同时满足 &&

    • 'once' 只能执行一次 fire()
    • 'memory' 保存前面 fire 传入的参数,后面加入的新回调会被自动传入前面保存的参数并执行
    • 'unique' 一次只能添加一个回调,回调列表不出现重复回调
    • 'stopOnFalse' 当一个回调返回 false 时中断调用
  • 回调对象的最典型应用是快速实现一个 观察者模式(又叫订阅/发布)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // 定义一个保存自定义事件的列表
    var taskList = {}
    jQuery.Task = function (id) {
    var task = id && taskList[id] // 取出对应任务
    if (!task) { // 若任务不存在,则创建
    callbacks = jQuery.Callbacks()
    task = {
    publish: callbacks.fire,
    subscribe: callbacks.add,
    unsubscribe: callbacks.remove
    };
    // 将任务加到事件列表
    if (id) {
    taskList[id] = task
    }
    }
    // 返回取得或创建的 task
    return task
    }

延迟对象

关于延迟对象的具体用法,请参考 阮一峰jQuery 的 deferred 对象详解

理解 jQuery 的延迟对象,可以从理解 Promise 开始,本质上是对 Promise 的封装实现

延迟对象是 jQuery 很多方法实现的基础,如 AJAX,对异步编程提供了统一风格的 API

如果一个方法的执行依赖于多个请求结果,那么使用延迟对象(Promise)将大大松散代码结构耦合并提高可读性

  • 采用链式写法,因此可以方便地为一个操作添加多个执行回调,按添加顺序执行

    1
    2
    3
    4
    $.ajax("test.html")
    .done(function () {alert("哈哈,成功了!")} )
    .fail(function () {alert("出错啦!")} )
    .done(function () {alert("第二个回调函数!")} )
  • $.when() 方法可以为同一个方法添加多个回调(类似 Promise.all()),它只接受 Deferred 对象作为参数

    1
    2
    3
    4
    // 下面两个 ajax 都成功了才会调用 done,只要有一个失败了就调用 fail
    $.when($.ajax("test1.html"), $.ajax("test2.html"))
     .done(function () { alert("哈哈,成功了!")})
     .fail(function () { alert("出错啦!")})
  • 封装普通函数使其成为 Deferred 对象可以用 deferred.resolve()deferred.reject()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    var wait = function () {
    // 新建一个deferred对象,作为私有变量
    var dtd = $.Deferred() // 这里也可以放在外面,而非闭包方式,但这有可能被外部使用 dtd.resolve() 等触发状态改变
    // 封装一个耗时的请求
    $.get('/someurl', function (res) {
    if (res.code === 200) {
    dtd.resolve() // 请求成功
    } else {
    dtd.reject() // 请求失败
    }
    })
    return dtd // 返回闭包
    // 也可以使用 return dtd.Primose(),这样返回一个新的 Deferred 对象 不能被外部的方法触发改变原来的 dtd
    }
    // 现在 wait() 函数生成一个 Deferred 对象了,可以作为 $.when() 的参数啦
    $.when(wait())
    .done(function (){alert("哈哈,请求成功了!")})
    .fail(function (){alert("请求错啦!")})
  • deferred.promise() 会包装生成一个对象为 Deferred 对象,使其拥有 Deferred 接口

  • 以下是几种 API 的汇总用法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $.when(wait())
    .then(function () {alert("成功时看到我")}, function () {alert("失败时看到我")})
     .done(function () {alert("成功时看到我")})
    // 以下三种失败方法等同,推荐用 .catch,与 ES6 一致
    .then(null, function () {alert("失败时看到我")})
     .fail(function () {alert("失败时看到我")})
    .catch(function () {alert("失败时看到我")})
    .always(function () {alert("成功或失败都看到我")})
  • deferred.state() 用来判断当前的 Promise 状态,返回下列三种字符串

    • ‘pending’ 尚未完成
    • ‘resolved’ 被解决
    • ‘rejected’ 被拒绝

总结

最后总结一下,jQuery 虽然简单易学,但毕竟是一门基于 JavaScript 的库,本质上还是要理解这个语言的核心。实际开发中,个人也进行了不少的思考,毕竟需要兼容低版本浏览器是不二之选。

但也有个血泪的教训就是,很多时候太依赖 jQuery 了,导致经常需要查找手册才知道原生的方法实现(毕竟哲学是 write less,do more)

  • 相关书籍推荐
    • 《锋利的jQuery》,精品国产书,毫无上手难度的一本书,对新手而言极为推荐,有很多精心设计的demo。
    • jQuery基础教程(第4版),图灵出版的精品,虽然是基础教程,但后半部分讲解的内容,很多是需要一定的实战积累才能理解其巧妙,建议作为进阶书籍。