离线下载
PDF版 ePub版

极客学院团队出品 · 更新于 2017-09-25 14:00:37

jQuery 3 中的新变动

译者:李鑫

原文:What’s New in jQuery 3

本文为极客学院Wiki组织翻译,转载请注明出处。

时间:2016.3.11

十年前 jQuery 的出现震撼了整个 Web 开发,如今它的一些优秀特点仍非常适用。利用 jQuery,用户可以方便地与 DOM 进行交互,执行 Ajax 请求,创建动画,等等。另外,与 DOM API 不同的是,jQuery 实现了复合模式(composite pattern)。正因为这一特点,你可以在一个 jQuery 集合中调用一些 jQuery 方法,而不用担心集合包含的元素数量(没有、只有一个或很多)。

随着 jQuery 3 的发布,jQuery 会到达一个重要的里程碑。该版本修复了很多 Bug,添加了一些新方法,不建议采用或干脆清除了一批函数,并改变了一些函数的行为。本文将重点介绍 jQuery 3 所带来的一些关键改动。

1 新特性

下面就将逐条介绍 jQuery 所新增的一些关键特性。

1.1 for...of 循环

jQuery 3 现在允许利用 for... Of 来遍历 jQuery 集合的 DOM 元素。这种新的迭代器是 ECMAScript 2015(也就是 ECMAScript 6)规范的一部分。它能实现对可遍历对象(包括 ArrayMapSet 等)的循环。

在使用这一新迭代器时,接收的值并不是每次访问一个元素的 jQuery 集合,而是一个 DOM 元素。这一迭代器稍微改变了对 jQuery 集合执行操作的方式。

下面举例来介绍这种迭代器的工作原理。假设页面上的每一 input 元素都需要指定一个 ID。jQuery 3 之前的做法是:

var $inputs = $('input');

for(var i = 0; i < $inputs.length; i++) {
   $inputs[i].id = 'input-' + i;
}

到了 jQuery 3,你只需这样写:

var $inputs = $('input');
var i = 0; 

for(var input of $inputs) {
   input.id = 'input-' + i++;
}

1.2 $.GET()$.POST() 的新签名

jQuery 3 为 $.get()$.post() 这两个工具函数添加了新的签名,为的是跟 $.ajax() 对等。新的签名是这样的:

$.get([settings])

$.post([settings])

settings 是一种能够执行很多属性的对象,和提供给 $.ajax() 的对象相同。关于详细介绍,请参考 $.ajax() 页面的内容。

跟传递对象给 $.ajax() 相比,当传递对象给 $.get()$.post() 时,其唯一区别在于 method 属性一直被忽略。原因在于 $.get()$.post() 各有一种预设的 HTTP 方法来处理 Ajax 请求($.get()GET$.post()POST)。一般说来,不能用 $.get() 发送 POST 请求。

考虑下面这段代码:

$.get({
   url: 'https://www.audero.it',
   method: 'POST' // 该属性被忽略   
});

尽管有 method 属性,该语句还是不能发送 POST 请求,只能发送 GET 请求。

1.3 动画可以使用 REQUESTANIMATIONFRAME()

所有现代的浏览器,包括 Internet Explorer 10 及更高版本,都支持 requestAnimationFrame。而在这背后,jQuery 3 将在执行动画时使用该 API,从而实现动画更平滑,减少 CPU 的工作压力。

1.4 UNWRAP()

jQuery 3 为 unwrap() 添加了可选的选择器参数。这一方法的新签名为:

unwrap([selector])

有了这一变动,就能将一个包含选择器表达式的字符串传入父元素进行匹配查找。如果存在匹配,那么与之匹配的子元素将解包,否则操作无法完成。

2 已更改的特性

下面是 jQuery 3 已经调整了的一些特性行为。

2.1 :VISIBLE:HIDDEN

新版 jQuery 更改了 :visible:hidden 过滤器的含义。如果元素有布局框,包括那些宽度和/或高度为0的情况,则元素被认为是:visible。比如说,br 元素和没有内容的内联元素将可以通过 :visible 过滤器进行选择。

所以,假如页面有如下标记:

<div></div>
<br />

如果运行了下面语句:

console.log($('body :visible').length);

那么在 jQuery 1.x 和 2.x 时,结果是 0,而到了 jQuery 3,结果就是 2。

2.2 DATA()

另一改动就是跟 data() 方法的行为有关。调整主要是为了让该方法符合 Dataset API 规范。jQuery 3 将所有属性的键都改为驼峰式大小写形式。先看下面这个例子。

<div id="container"></div>

如果使用 3 之前的版本写了下列代码:

var $elem = $('#container');

$elem.data({
   'my-property': 'hello'
});

console.log($elem.data());

控制台上的结果如下:

{my-property: "hello"}

而在 jQuery 3,结果为:

{myProperty: "hello"}

所以再次重申:jQuery 3 时,属性名都是驼峰大小写,没有中间的短划线(-);而使用 3 之前的版本,则依然采用全部小写字母的写法,词之间带有短划线。

2.3 Deferred 对象

jQuery 3 还改变了 Deferred 对象的行为(该对象是 Promise 对象的前身),改善了它与 Promise/A+ 提案的兼容性。该对象及其历史非常有意思,你可以读读官方文档,也可以看看我写的书 《jQuery 实战,第 3 版》中有关 jQuery 3 的章节内容。

在 jQuery 1.x 和 2.x 时,传入 Deferred 中的回调函数中的一个未捕获异常会导致程序停止执行。与原生的 Promise 对象不同的是,抛出异常会逐层传播,直到它抵达 window.onerror 为止(往往是这样)。如果不能为该事件(虽然并不常见)定义一个函数,则会显示异常消息,程序终止执行。

jQuery 3 遵循原生的 Promise 对象的模式。因此,抛出的异常将被视为一个 rejection,从而执行失败回调。完成之后,进程继续,继续执行后续的成功回调。

为了让你理解这其中的差异,先来看一个小例子。如下所示:

var deferred = $.Deferred();

deferred
  .then(function() {
    throw new Error('An error');
  })
  .then(
    function() {
      console.log('Success 1');
    },
    function() {
      console.log('Failure 1');
    }
  )
  .then(
    function() {
      console.log('Success 2');
    },
    function() {
      console.log('Failure 2');
    }
  );

deferred.resolve();

在 jQuery 1 和 jQuery 2 时,只执行第一个函数(抛出错误的函数)。另外,因为没有为 window.onerror 定义处理器,所以控制台将输出消息:“Uncaught Error: An error”(未捕获的错误:发生错误),程序不再继续执行。

而在 jQuery 3,行为则完全不同了,控制台将显示 “Failure 1” 和 “Success 2” 两个消息。由第一个失败的函数来管理异常,一旦被处理,则继续执行下面的成功函数。

2.4 SVG 文档

jQuery 各个版本(包括 3)都没有对 SVG 文档有过官方的支持。但实际上很多方法都适用,另外一些方法,比如操作类名的方法,已经在 jQuery 3 中进行了更新,因此也适用。因此,在未来的版本中,应该可以使用 addClass()hasClass() 这样的方法处理 SVG 文档,估计不会出现什么问题。

3 过时不建议采用与已清除的方法及属性

除了前面说的改进,jQuery 3 还除去了一些方法和属性,并且声明了一批不建议采用的特性。

3.1 不建议采用:BIND()UNBIND()DELEGATE()UNDELEGATE()

不久前引入的 on() 方法代替了 jQuery 的 bind()delegate() 以及 live() 方法,提供了一种统一的访问接口。与之类似,jQuery 用 off() 方法来代替 unbind()undelegated()die() 方法。bind()delegate()unbind()undelegate() 今后不建议使用,也不会再支持它们。

jQuery 3 将所有这些方法声明为过时,并打算在未来版本中清除它们(有可能是 jQuery 4),所以今后一定要在项目中坚持使用 on()off() 方法,以便适应将来的变化。

3.2 已清除的方法:LOAD()UNLOAD()ERROR()

jQuery 3 完全弃用了已被宣布为过时的方法:load()unload()error()。这些方法已经过时很长时间了(从 jQuery 1.8 起),但仍一直存在着。如果某个插件依赖其中的一个或多个方法,那么更新到 jQuery 3 时,代码就会出错,因此一定要在更新时多注意一下这个问题。

3.3 已清除的属性:CONTEXTSUPPORTSELECTOR

jQuery 3 清除了 contextsupportselector 属性。如前所述,如果项目中仍然使用着这些属性,或者某个插件仍在依赖这些属性,那么更新到 jQuery 3 时,代码就会出错。

4 修复的 Bug

jQuery 3 修复了前一版本的一些重大 Bug。下面介绍两个,此次修复将会对你的编码产生重大影响。

4.1 width()height()

此次修复了 width()height() 以及其他连带方法中的 Bug。这些方法再也不会四舍五入到最近的像素了,因为在某些情况下,这样做很难定位元素。

举例来说明这一问题。假设宽度为 100 px 的 container 元素包含着 3 个子元素。

<div class="container">
   <div>My name</div>
   <div>is</div>
   <div>Aurelio De Rosa</div>
</div>

在 jQuery 3 之前的版本,获取子元素宽度的代码应该是下面这样吧?

$('.container div').width();

这样一来,结果就是 33。因为当时 jQuery 会将结果 33.33333 四舍五入。而在 jQuery 3 中,这个 Bug 已经得到修复,你的结果会更精确(比如会得到浮点数)。

4.2 WRAPALL()

jQuery 3 还修复了一个将某个函数传入 wrapAll() 方法时常会出现的 Bug。在 3 之前的版本中,当把某个函数传入 wrapAll() 时,会将 jQuery 集合中的元素分别包装。换句话说,它的行为表现得就像将函数传入 wrap()

除了修复这个问题外,因为这种函数在 jQuery 3 中只会被调用一次,所以jQuery 集合元素的索引不可能被传入。最后,该函数上下文(this)将指向 jQuery 集合中的第一个元素。

5 下载 jQuery 3 beta 1

如果此文让你产生了兴趣,你可以试试 jQuery 3 的第一个 beta 版。通过下面两个 URL 都可以下载到它。

利用 npm 也可以下载它,命令如下:

npm install jquery@3.0.0-beta1

6 总结

许多人宣称 jQuery 已死,认为现代 Web 开发已经不需要它了。但 jQuery 的开发仍在继续,而且统计数字显示,前100万个网站中,采用这一技术的网站占到了 78.5%,从而驳斥了上述反对言论。

本文只是列出了 jQuery 3 所带来的一些主要改变。你可能会注意到,这一版本更新不会对已有项目产生太大的影响,因为没有引入太多破坏性的彻底变革。尽管如此,仍然需要注意一些因素,比如 Deferred 对象的改进。就像更新第三方依赖所经常要面的那样,对项目一定要做一个复查,从而防止意外行为或功能崩溃的情况出现。