https://github.com/cssmagic/blog/issues/59 @Aurelio De Rosa
css
jQuery 的横空出世,至今已有十个年头了,而它的长盛不衰显然不是没有理由的。jQuery 提供了极为友好的接口,使得开发者们能够方便地进行 DOM 操做、发起 Ajax 请求、生成动画……不一而足。此外,与 DOM API 不一样的是,jQuery 采用了 “混合模式”。这意味着你能够在任何一个 jQuery 集合身上调用 jQuery 方法,而不用关心它到底包含了几个元素(无论是零个、一个或多个,都没问题)。在将来的几周内,jQuery 就将抵达一个重要的里程碑——正式发布 3.0 版本。jQuery 3 修复了大量的 bug,增长了新的方法,同时移除了一些接口,并修改了少许接口的行为。在这篇文章中,我将为你们重点讲解 jQuery 3 所引入的那些最重要的变化。 jquery
新增特性git
咱们先来讨论 jQuery 3 中最重要的几个新增特性。github
for...of 循环ajax
在 jQuery 3 中,咱们能够用 for...of 循环语句来迭代一个 jQuery 集合中的全部 DOM 元素。这种新的迭代方法是 ECMAScript 2015(即 ES6)规范中的一部分。这个方法能够对 “可迭代对象”(好比 Array、Map、Set 等)进行循环。npm
当使用这种新的迭代方法时,你在循环体内每次拿到的值并非一个 jQuery 对象,而是一个 DOM 元素(译注:这一点跟 .each() 方法相似)。当你在对一个 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++;
}
(译注:其实 jQuery 本身是有个 .each() 方法的,可读性也不赖。)
$.get() 和 $.post() 函数的新签名
jQuery 3 为 $.get() 和 $.post() 这两个工具函数增长了新签名,从而使得它们和 $.ajax() 的接口风格保持一致。新签名是这样的:
$.get([settings])
$.post([settings])
settings 是一个对象,它包含多个属性。它的格式和你之前传给 $.ajax() 的参数格式是同样的。若是你想更清楚地了解这个参数对象,请参考 $.ajax() 页面 中的相关描述。
$.get() 和 $.post() 的参数对象与传给 $.ajax() 的参数相比,惟一的区别就是前者的 method 属性老是会被忽略。缘由其实也很简单,$.get() 和 $.post() 自己就已经预设了发起 Ajax 请求的 HTTP 方法了(显然 $.get() 就是 GET,而 $.post() 就是 POST)。也就是说,正常人类应该是不会想用 $.get() 方法来发送一个 POST 请求的。
假设有如下一段代码:
$.get({
url: 'https://www.audero.it',
method: 'POST' // This property is ignored
// 这个属性将被忽略
});
无论咱们把 method 属性写成什么,这个请求老是会以 GET 的方式发出去的。
采用 requestAnimationFrame() 来实现动画
全部现代浏览器(包括 IE10 及以上)都是支持 requestAnimationFrame 的。jQuery 3 将会在内部采用这个 API 来实现动画,以便达到更流畅、更省资源的动画效果。
unwrap() 方法
jQuery 3 为 unwrap() 方法增长了一个可选的 selector 参数。这个方法的新签名是这样的:
unwrap([selector])
有了这个特性,你就能够给这个方法传入一个包含选择符表达式的字符串,用它来在父元素内进行匹配。若是存在匹配的子元素,则这个子元素的父层将被解除;若是没有匹配,则不进行操做。
有变动的特性
jQuery 3 还修改了一些特性的行为。
:visible 和 :hidden
jQuery 3 将会修改 :visible 和 :hidden 过滤器的含义。只要元素具备任何布局盒,哪怕宽高为零,也会被认为是 :visible。举个例子,br 元素和不包含内容的行内元素如今都会被 :visible 这个过滤器选中。
所以,若是你的页面中包含以下的结构:
<div><div>
<br />
而后运行如下语句:
console.log($('body :visible').length);
在 jQuery 1.x 和 2.x 中,你获得的结果会是 0;但在 jQuery 3 中,你会获得 2。
data() 方法
另外一个重要的变化是跟 data() 方法有关的。如今它的行为已经变得跟 Dataset API 规范 一致了。jQuery 3 将会把全部属性键名转换成驼峰形式。咱们来详细看一下,以以下元素为例:
<div id="container"><div>
当咱们在用 jQuery 3 之前的版本时,若是运行以下代码:
var $elem = $('#container');
$elem.data({
'my-property': 'hello'
});
console.log($elem.data());
将会在控制台获得以下结果:
{my-property: "hello"}
而在 jQuery 3 中,咱们将会获得以下结果:
{myProperty: "hello"}
请注意,在 jQuery 3 中,属性名已经变成了驼峰形式,横杠已经被去除了;而在之前的版本中,属性名会保持全小写,并原样保留横杠。
Deferred 对象
jQuery 3 还改变了 Deferred 对象的行为。Deferred 对象能够说是 Promise 对象的前身之一,它实现了对 Promise/A+ 协议 的兼容。这个对象以及它的历史都至关有意思。若是想要深刻了解,你能够去阅读 jQuery 官方文档,也能够去看我写的书《jQuery 实战(第三版)》——这本书也涵盖了 jQuery 3。
在 jQuery 1.x 和 2.x 中,传给 Deferred 的回调函数内若是出现未捕获的异常,会当即中断程序的执行(译注:即静默失败,其实 jQuery 绝大多数回调函数的行为都是这样的)。而原生的 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.x 和 2.x 中,只有第一个函数(也就是抛出错误的那个函数)会被执行到。此外,因为咱们没有为 window.onerror 定义任何事件处理函数,控制台将会输出 “Uncaught Error: An error”,并且程序的执行将停止。
而在 jQuery 3 中,整个行为是彻底不一样的。你将在控制台中看到 “Failure 1” 和 “Success 2” 两条消息。那个异常将会被第一个失败回调处理,而且,一旦异常获得处理,那么后续的成功回调将被调用。
SVG 文档
没有哪个 jQuery 版本(包括 jQuery 3)曾官方宣称支持 SVG 文档。不过事实上有不少方法是能够奏效的,此外还有一些方法在之前是不行的(好比操做类名的那些方法),但它们在 jQuery 3 中也获得了更新。所以,在 jQuery 3 中,你应该能够放心使用诸如 addClass() 和 hasClass() 这样的方法来操做 SVG 文档了。
已废弃、已移除的方法和属性
在增长了上述改进的同时,jQuery 也移除、废弃了一些特性。
废弃 bind()、unbind()、delegate() 和 undelegate() 方法
jQuery 在好久之前就引入了 on() 方法,它提供了一个统一的接口,用以取代 bind()、delegate() 和 live() 等方法。与此同时,jQuery 还引入了 off() 这个方法来取代 unbind()、undelegated() 和 die() 等方法。从那时起,bind()、delegate()、unbind() 和 undelegate() 就已经再也不推荐使用了,但它们仍是一直存在着。
jQuery 3 终于开始将这些方法标记为 “废弃” 了,并计划在将来的某个版本(极可能是 jQuery 4)中将它们完全移除。所以,请在你的项目中统一使用 on() 和 off() 方法,这样你就不用担忧将来版本的变动了。
移除 load()、unload() 和 error() 方法
jQuery 3 完全抛弃了 load()、unload() 和 error() 等已经标记为废弃的方法。这些方法在很早之前(从 jQuery 1.8 开始)就已经被标记为废弃了,但一直没有去掉。若是你正在使用的某款插件仍然依赖这些方法,那么升级到 jQuery 3 会把你的代码搞挂。所以,在升级过程当中请务必留意。
移除 context、support 和 selector 属性
jQuery 3 完全抛弃了 context、support 和 selector 等已经标记为废弃的属性。同上,在升级到 jQuery 3 时,请留意你正使用的插件。
已修复的 Bug
jQuery 3 修复了以往版本中的一些很是重要的 bug。在本节中,我将着重介绍其中两处,由于这二者应该会对你写代码的习惯带来显著影响。
width() 和 height() 的返回值将再也不取整
jQuery 3 修复了 width()、height() 和其它相关方法的一个 bug。这些方法的返回值将再也不舍入取整,由于这种取整行为在某些状况下不便于对元素进行定位。
咱们来详细看一看。假设你一个宽度为 100px 的容器元素,它包含了三个子元素,宽度均为三分之一(即 33.333333%):
<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 已经被修复了,所以你将会获得更加精确的结果(即一个浮点数)。
wrapAll() 方法
jQuery 3 还修复了 wrapAll() 方法中的一个 bug,这个 bug 出如今把一个函数做为参数传给它的状况下。在 jQuery 3 之前的版本中,当一个函数被传给 wrapAll() 方法时,它会把 jQuery 集合中的每一个元素单独包裹起来。换句话说,这种行为和把一个函数传给 wrap() 时的行为是彻底同样的。
在修复这个问题的同时,还引入了另一个变动:因为在 jQuery 3 中,这个函数只会调用一次了,那就没法把 jQuery 集合中每一个元素都传给它。所以,这个函数的执行上下文(this)将只能指向当前 jQuery 集合中的第一个元素。
如何下载 jQuery 3 beta 1
既然你已经读到了这里,那说明你极可能想试试 jQuery 3 的第一个 beta 测试版。你能够经过如下两个地址来获取这个版本:
未压缩版: 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
结论
不少人一直在唱衰 jQuery,说它在现代网页开发中已经没有一席之地了。但无论怎样,jQuery 的开发仍在继续,客观的统计数据(在排名前一百万名的网站中占有率高达 78.5%)也让这些论调不攻自破。
在本文中,我已经带你了解了一遍 jQuery 3 将会带来的一些重大变化。或许你已经察觉到了,这个版本并不太可能搞挂你的既有项目,由于它引入的破坏性变动其实寥寥无几。不过,在升级到 jQuery 3 的过程当中,你仍是有必要牢记一些关键点,好比 Deferred 对象的改进等等。一样,在升级某个第三方库时,也有必要检查一下该项目的兼容性状况,以便尽早发现任何非预期行为,避免某些功能失效。
译注
除了本文所说起的变动以外,jQuery 3.0 最大的变化就是完全放弃对 IE8 的支持。jQuery 团队作出这个决定的缘由在于,微软已经在今年年初宣布中止对 IE 8~10 的支持。所以,jQuery 在 3.0 alpha 阶段所发布的 jQuery Compat 项目也就没有继续存在的必要了。
不过,因为 IE8 仍然是中国大陆最流行的浏览器之一,对国内的开发者来讲,在短时间(甚至中期)内还不得不停留在 jQuery 1.x 版本。
好吧,最后仍是说个好消息吧。为帮助用户平滑升级,这次 jQuery 一样会为 3.0 版本提供迁移插件(jQuery Migrate plugin)。在把 jQuery 升级到 3.0 以后同时运行这个插件,便可确保基于 jQuery 1.x 或 2.x 的既有业务代码正常运行;同时,它还将在控制台向你报告既有代码与 jQuery 3 不兼容的地方。当你修复了这些不兼容问题以后,就能够安全地移除这个插件了。