back back-top comments magnifier menu mobile right smile views

jQuery 3.0 带来哪些新特性?看这一篇就够了

Jean
Jean

2016年6月9日 jQuery 官方团队发布了 jQuery 3.0 的最终版本,这是一个重要的里程碑。jQuery 作为驰骋 web 界 已有十年的大神之作,其在前端领域的深远影响和贡献已无法形容。

jquery-official-website

jQuery 让开发者更便利的操作 DOM、执行 AJAX 请求 以及创建炫酷的 动画 等。另外,它还实现了 “复合模式” composite pattern,你可以在元素集合 或单个元素上 调用 jQuery 方法。

jQuery3 修复了很多bug,增加了一些新方法,弃用了一些旧方法,对一些方法的行为做了优化和更改。现在 最新最稳定的版本是 jQuery-3.1.0,让我们一起来具体瞧瞧 jQuery3 带来哪些最重要的变化:

新特性

for…of 循环

jQuery3 提供了遍历 jQuery 集合中 DOM 元素 使用最新 for…of 方法的可能性,这个最新的迭代器 是ECMAScript 2015 (ES6) 规范中的部分。当你使用  for…of 循环时,你所遍历得到的值并不是一个 jQuery集合,而是一个 DOM 元素。这个迭代器 能在一定程序上 稍稍提高你操作 DOM 的效率。

为了了解这个迭代器是如何工作的,让我们假设 你想为页面上每个 input 元素设置一个 id,在 jQuery3 之前,你可能会这样写:

var $inputs = $('input');

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

在jQuery3中,你可以这样写:

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

// input 的值并不是一个 jQuery 对象,而是一个原生 dom 节点
for(var input of $inputs) {
   input.id = 'input-' + i++; // 等同于:先+i 再i++
}

关于 for…of,想进一步了解 请看 深入学习迭代器和for-of循环

$.get() 和 $.post() 增加了新的参数类型 [settings]

jQuery3 为 $.get() 和 $.post() 方法增加了新的参数类型 [settings],[settings] 是一个对象 同样可以提供给 $.ajax() 方法。

// 以前我们通常这样写:
$.post('test.php', { name: 'David Guetta', age: 49 }, function (data) {
  console.log(data);
});

// jQuery3 中可以这样写:
$.post({
  url: 'test.php',
  data: { name: 'David Guetta', age: 49 },
  success: function (data) {
    console.log(data);
  }
});

和 $.ajax() 唯一不同的是:如果 $.get() 和 $.post() 的 [settings] 中传递了 method 属性,method 的属性值将被忽略掉,原因是 $.get() 和 $.post() 都有预设的 HTTP 方法来执行 Ajax 请求($.get() 是GET,$.post() 是 POST)

思考下面的代码:

// 不管你将 method 的值设为 'GET' 或 'POST' 都会被忽略,$.get() 也不会发起 POST 请求的
$.get({
   url: 'https://www.audero.it',
   method: 'POST'
});

动画使用了 requestAnimationFrame()

jQuery 之前使用 setInterval 通过不断更新元素的 CSS 属性 产生动画,每次更新时 会迫使浏览器对页面进行重绘 (reflow),一般显示器 16.7ms 刷新一次 如果在这间隔期间有其他的 setInterval 请求,就会导致”帧”丢失,造成动画卡顿。而 requestAnimationFrame 会根据浏览器的绘制时间 对动画进行不断优化,使动画流畅并减少对CPU资源的消耗。

现在,几乎所有的现代浏览器 包括 IE-10 及以上版本,都支持 requestAnimationFrame,jQuery3 将会在内部使用这个 API 执行动画。

unwrap()

jQuery3 为 unwrap() 方法增加了一个可选参数 selector,你可以通过这个字符串选择器匹配元素的父元素 如果匹配到 则移除父元素 否则就不移除:

<div class="wrap"><p></p></div>

<div><p></p></div>
// 移除 p 元素的 class="wrap" 的父元素,上面 html 中 只有第一个 div 会被移除
$('p').unwrap('.wrap');

改变的特性

:visible 和 :hidden

新版的 jQuery 修改了 :visible:hidden 过滤器的定义。任何可用于布局的元素 即使它们的高度宽度为0,都会被认为是 :visible,例如:br 元素和没有内容的内联元素,现在都会被 :visible 过滤器匹配。

思考下面代码:

<div></div>
<br>
<span></span>
// 在 jQuery1.x 中控制台输出 1
// 在 jQuery3 中控制台输出 3
// 区别在于:jQuery3 中 内联元素也会被 :visible 过滤器匹配
console.log($('body :visible').length);

data()

另一个重要的变化是有关data()方法的行为。jQuery3 严格遵守 Dataset API 规范。将所有data-属性的键都转成驼峰式命名方式。下面的代码展示了这个变化:

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

如果你使用的是 jQuery3 之前的版本,你可能会这样写:

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

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

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

控制台会输出:

{my-property: "hello"}

但使用了 jQuery3,控制台会输出:

{myProperty: "hello"}

注意:在 jQuery3 中属性名已经变成了驼峰式,在以前的版本中,对于自定义 data 属性,你可能会这样写:data-my-property,但在版本3中,建议改成驼峰式:data-myProperty

Deferred 对象

deferred 对象是由jQuery创造的回调函数解决方案,defer 中文译为”延迟”,所以 deferred 对象的含义就是”延迟”到未来某个点再执行。jQuery3 改变了 deferred 对象的行为,deferred 对象其实是 ES6 Promise 对象的前身,这次改变提高了 deferred 对象本身对 Promise/A+ 提案的兼容性。

在 jQuery1.x 和 2.x 中,传递给 deferred 的回调函数内如果出现未捕获的异常,就会阻断程序的执行。不像原生 Promise 对象那样会抛出异常冒泡至 window.onerror(通常冒泡到这里)。如果你没有定义一个函数处理错误事件(通常我们是会处理的),那么异常信息就会显示并且程序会终止执行。

jQuery3 遵循原生 Promise 对象的模式。因此,抛出的异常被当作失败,接着失败回调函数被执行。一旦失败回调函数执行完成,进程就会继续,下面的成功回调函数将被执行。

为了帮助你理解两者的区别,看一个小例子:

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();

在 jQuery1 和 jQuery2 中,当执行到第一个函数就停止了。控制台会输出“Uncaught Error: An error”,程序会终止执行:

jquery-3-deferred-1

jQuery3 中,行为是完全不同的。控制台输出 “Failure 1” 和 “Success 2”,异常被第一个失败回调函数处理,并且一旦被处理,随后的成功回调函数也会被执行。

jquery-3-deferred-2

SVG

包括 jQuery3 在内 至今没有任何版本的 jQuery 正式支持 SVG documents,然而 还是有很多方法可以正常使用的,在之前的 jQuery 的版本中 不能正常使用类名操作,但 jQuery3 中可以了,你可以在新版本中放心使用 addClass() hasClass() 方法了。

已废弃和已移除的方法和属性

废弃了 bind()、unbind()、delegate() 和 undelegate()

可能有人搞不明白”废弃”和”移除”这两词的区别,”废弃” 是指一些方法还在存在于 jQuery 源码中,但是已经提供了新方法来替换那些方法,而 “移除” 就是一些方法已经从 jQuery 源码中删除了。

jQuery 在1.7版本 就引入了 on() 方法,它提供了统一的接口来替换 bind()、delegate() 和 live() 方法,与此同时 提供了 off() 方法替换 unbind()、undelegated() 和 die() 方法。建议使用 on() 和 off() 来替代它们。

jQuery3 废弃的这些方法 打算在未来的版本中(也许是 jQuery4)移除它们。所以你在项目中使用 on() 和 off() 方法,就不用担心未来的版本更新问题。

移除了 load()、unload() 和 error() 方法

其实在 jQuery1.8 时,这些方法就被废弃了,但当时还存在于 jQuery 源码中,从 jQuery3 开始,这些方法就被彻底移除了。如果你使用的第三方插件 依赖了这些方法,将会报错。因此,升级时,还是注意下吧。

移除 context、support 和 selector 属性

jQuery3 移除了已经废弃的 context、support 和 selector 属性。

Bug 修复

jQuery3 修复了以前版本中被认为存在的重大bug,尤其是 width(),height() 和 wrapAll()。

移除了 load()、unload() 和 error() 方法

width() 和 height() 及所有其它相关方法 将不再将结果的像素值四舍五入到一个整数值,因为四舍五入后在某些情况下很难对元素进行定位。

为了理解,假设页面里有一个宽度为100px的容器元素,它里面包含三个宽度为三分之一(33.3333%)的元素:

<div class="container">
  <div>My name</div>
  <div>is</div>
  <div>Aurelio De Rosa</div>
</div>
.container div {
  width: 33.3333%;
}

然后去获取 “.container” 元素内部的 div 宽度:

var width = $('.container div').width()
console.log(width);

在 jQuery3 之前的版本,你得到的 width 值是33,因为 jQuery 将33.3333这个值四舍五入了,在 jQuery3 中,这个 bug 被修复了,你会得到一个更精确的值(浮点数)。

jquery-3-bug-1

下载 jQuery3

读了这篇文章,你肯定想要尝试下载 jQuery3。可以访问下面两个官方url来下载,目前最新最稳定的是 jQuery-3.1.0:

有人认为随着web前端技术的发展,jQuery将会沉默,然而它缺一直在持续发展进化,有项官方数据:在排名前100万的网站中 jQuery 的使用率高达78.5%,很显然 这个数据反驳了这些说法。快到2016年末了,可能对于已经使用 jQuery 五年的我,jQuery 不仅是大部分项目中不可或缺的js工具库,更是一种情怀。

本文由 前端先生 翻译整理自 What is New in jQuery 3jQuery 3.0 Final Released!,欢迎转载,但请注明出处。

2条评论

2条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注

扫描二维码分享到微信