译者:李鑫
本文为极客学院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)规范的一部分。它能实现对可遍历对象(包括 Array
、Map
、Set
等)的循环。
在使用这一新迭代器时,接收的值并不是每次访问一个元素的 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 已清除的属性:CONTEXT
、SUPPORT
和 SELECTOR
jQuery 3 清除了 context
、support
和 selector
属性。如前所述,如果项目中仍然使用着这些属性,或者某个插件仍在依赖这些属性,那么更新到 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 都可以下载到它。
- 未压缩版本:https://code.jquery.com/jquery-3.0.0-beta1.js。
- 压缩版本:https://code.jquery.com/jquery-3.0.0-beta1.min.js。
利用 npm 也可以下载它,命令如下:
npm install jquery@3.0.0-beta1
6 总结
许多人宣称 jQuery 已死,认为现代 Web 开发已经不需要它了。但 jQuery 的开发仍在继续,而且统计数字显示,前100万个网站中,采用这一技术的网站占到了 78.5%,从而驳斥了上述反对言论。
本文只是列出了 jQuery 3 所带来的一些主要改变。你可能会注意到,这一版本更新不会对已有项目产生太大的影响,因为没有引入太多破坏性的彻底变革。尽管如此,仍然需要注意一些因素,比如 Deferred
对象的改进。就像更新第三方依赖所经常要面的那样,对项目一定要做一个复查,从而防止意外行为或功能崩溃的情况出现。