【译】(从今以后)你可能不需要jQuery

自从 jQuery 在 2006 年发布以来,DOM 和原生浏览器 API 有了飞跃式的发展。自 2013 年以来,人们一直在写“你可能不需要 jQuery”的文章 (经典网站 (opens new window)经典 repo (opens new window)) 。我不想老调重弹,但是从最新的《你可能不需要 jQuery》文章中,你可能会偶然发现, 浏览器领域有一些好的改变。浏览器增加了新的 API,从而免于使用第三库开发带来的痛苦 ,其中许多 API 直接从 jQuery 复制。

让我们一起看看有哪些新的原生方法可以替换掉 jQuery。

# 从页面移除元素

还记得使用原生 DOM 从页面上移除一个元素的令人抓狂地迂回方式吗 ?el.parentNode.removeChild(el);?这是 jQuery 方式和新原生方式的对比。

jQuery:

var $elem = $('.someClass'); //选择元素
$elem.remove(); //移除元素
1
2

新原生:

var elem = document.querySelector('.someClass'); //选择元素
elem.remove(); //移除元素
1
2

说明:对于本文的以下部分,我们假设$elem是一组 jQuery 选择的元素集 ,elem是一个原生 JavaScript 选择的 DOM 元素。

# 前置插入元素(内部)

jQuery:

$elem.prepend($someOtherElem);
1

新原生:

elem.prepend(someOtherElem);
1

# 前置插入元素(外部)

jQuery:

$elem.before($someOtherElem);
1

新原生:

elem.before(someOtherElem);
1

# 替换元素

jQuery:

$elem.replaceWith($someOtherElem);
1

新原生:

elem.replaceWith(someOtherElem);
1

# 查找最近的祖先元素

jQuery:

$elem.closest('div');
1

新原生:

elem.closest('div');
1

# 浏览器对 DOM 操作方法的支持

这些方法现在具有良好的浏览器支持:

该浏览器支持数据来自Caniuse (opens new window), 它具有更多的细节。数字表示浏览器从  此版本及以上支持该功能。

# 桌面浏览器

Chrome Firefox IE Edge Safari
54 49 No 17 10

# 手机、平板浏览器

Android Chrome Android Firefox Android iOS Safari
81 68 81 10-10.2

它们目前正在 Edge 中实现。

# 淡入元素

jQuery:

$elem.fadeIn();
1

通过编写我们自己的 CSS,我们可以更好地控制元素的动画。在这里我会做一个简单的淡入 。

.thingy {
  display: none;
  opacity: 0;
  transition: 0.8s;
}
1
2
3
4
5
elem.style.display = 'block';
requestAnimationFrame(() => (elem.style.opacity = 1));
1
2

# 一次事件处理回调函数

jQuery:

$elem.one('click', someFunc);
1

在以前编写原生 JavaScript 时,我们必须在回调函数内部调用 removeEventListener 方 法。

function dostuff() {
  alert('some stuff happened');
  this.removeEventListener('click', dostuff);
}
var button = document.querySelector('button');
button.addEventListener('click', dostuff);
1
2
3
4
5
6

现在这件事情变得更加简单。你可能已经看到过有时会在addEventListener方法中传递第 三个可选参数。用来判断事件捕获或事件冒泡时,它是一个布尔类型的值。现在不仅如此 ,第三个参数 (opens new window)还 可以是一个配置对象。

elem.addEventListener('click', someFunc, { once: true });
1

如果你仍然希望使用事件捕获中仅调用一次回调,那么你也可以在配置对象中设置:

elem.addEventListener('click', myClickHandler, {
  once: true,
  capture: true,
});
1
2
3
4

# 动画

jQuery 的.animate()方法是非常有限的。

$elem.animate(
  {
    width: '70%',
    opacity: 0.4,
    marginLeft: '0.6in',
    fontSize: '3em',
    borderWidth: '10px',
  },
  1500
);
1
2
3
4
5
6
7
8
9
10

文档中说“所有动画属性应该设置为单个数值,除非另有说明;许多非数值属性都无法使用基 本的 jQuery 方法设置动画。”,你需要使用插件才能为 transform 和颜色设置动画。使用 新的 Web Animations API (opens new window) 会简单很多。

var elem = document.querySelector('.animate-me');
elem.animate(
  [
    {
      transform: 'translateY(-1000px) scaleY(2.5) scaleX(.2)',
      transformOrigin: '50% 0',
      filter: 'blur(40px)',
      opacity: 0,
    },
    {
      transform: 'translateY(0) scaleY(1) scaleX(1)',
      transformOrigin: '50% 50%',
      filter: 'blur(0)',
      opacity: 1,
    },
  ],
  1000
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# Ajax

jQuery 以前的另一个招牌特性就是Ajax。 jQuery 消除了XMLHttpRequest的缺点:

$.ajax('https://some.url', {
  success: (data) => {
    /* do stuff with the data */
  },
});
1
2
3
4
5

新的fetch API (opens new window)是 XMLHttpRequest 非常棒的替 代品,现在所有现代浏览器都已支持。

fetch('https://some.url')
  .then((response) => response.json())
  .then((data) => {
    // do stuff with the data
  });
1
2
3
4
5

当然,实际获取数据可能比这个代码示例更复杂一些。例如,在接收到错误的 HTTP 状态码 时fetch()返回的 Promise 并不会 reject 反而会被 resolve。但是,它比建立 在XMLHttpRequest之上的任何功能都更 加通用 (opens new window)

如果我们想要易于使用,有一个简单且流行的选择——但它不是浏览器原生的,这使我进入 ...

# 微型库的兴起

Axios (opens new window)是一个流行的 Ajax 库。这是一个很好的 微型库案例——只为一件事而设计的库。虽然大多数库不会像 jQuery 那样经过良好的测试, 但它们往往可以成为 jQuery 这个庞然大物的替代品。

# (几乎)所有问题都可以解决

现在你已经知道原生操作 DOM 很好用了!但是你可能看过这些发展成果后还是想说:“哦, 仍然需要支持 IE 9, 所以我还是最好还是使用 jQuery 吧”。大多数情况下,Can I Use对你想要使用的某个特性的说法已经不那么重要了,你可以使用任何你喜欢的特性 ,polyfills 可以为低版本浏览器提供兼容支持。在相当长的一段时间里,如果你想使用一 个新的浏览器特性,你必须找到一个 polyfill,然后把它放置到你的页面中。对于 IE9 中 缺少的所有功能,这样做将是一项艰巨的任务。而现在就简单多了

<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>
1

这个简单的脚本标签可以使低版本浏览器支持所有的最新 API。如果你还没有从英国《金融 时报》听说这种 polyfill 服务,你可以 到polyfill.io (opens new window)阅读相关信息。

# 2017 年迭代 NodeList

jQuery 的大量采用并不仅仅是因为它能消除浏览器之间的漏洞和 IE 的不一致性。今天 jQuery 还有一个招牌特性:迭代

NodeList 是不可迭代。开发者不得不通过各种各样的方法使之可以迭代。经典的 for 循环 可能是性能最优的方法, 但肯定不是我喜欢的那一种类型。因此我们得到了最丑陋的方法:

var myArrayFromNodeList = [].slice.call(document.querySelectorAll('li'));
1

或者:

[].forEach.call(myNodeList, function (item) {...});
1

最近,我们已经能够使用Array.from,更简单更优雅地将 nodeList 转换为数组。

Array.from(querySelectorAll('li')).forEach((li) => /* do something with li */);
1

但是最大的消息是,现在 NodeLists默认是可迭代的 (opens new window)

现在只需简单地输入:

document.querySelectorAll('li').forEach((li) => /* do some stuff */);
1

Edge 是最后一个不支持可迭代 NodeLists 的现代浏览器,但目 前正在处理支持中 (opens new window)

# jQuery 很慢吗?

jQuery 可能比那些写的糟糕原生 JS 更快,但这只是一个让我们更好地学习 JavaScript 的理由!jQuery 项目的贡献者 Paul Irish 曾说过:

jQuery 的作者在他的《JavaScript 忍者秘籍》一书中有关学习原生 DOM 操作这样写道:

既然类库已经帮我们做好了,为什么我们还要理解它的实现呢?最能让大家信服的原因就 是为了性能。了解类库中 DOM 操作的实现原理,既可以配合类库写出更高效的代码,也 可以将这些技术灵活运用在自己的代码中。

# 我不喜欢 jQuery 的地方

jQuery 不只是解决各个浏览器之间的 API 兼容性问题,还想要试图将它们全部替换掉。返 回 jQuery 对象而不是 NodeList,这意味着你做事情的方式要受限于 jQuery,而内置的浏 览器方法是不受限制的。对于初学者来说,曾经使前端 js 变得容易上手现在反而成为了障 碍,因为实际上这意味着有两种重复的方式来做这些事情。如果你想轻松阅读别人的代码, 并应用到原生 JS 和 jQuery 环境中,那么你需要学习的东西就会多一倍。然而,有些类库 使用了 jQuery,但是返回的是 NodeList 而不是 jQuery 对象……

# 没有$就活不下了吗?

也许你已经喜欢上了 jQuery 的$,有很多微型库试图去模仿 jQuery 的 API。

我不是 jQuery 的反对者,一些优秀的开发者仍然选择使用 jQuery。如果你已经习惯使用 jQuery 并且对它的 API 非常熟悉,那就没必要放弃使用。有些人使用 jQuery 知道什么是 闭包,可以写出企业级的 Web 应用,而有些人使用原生 JS 却不知道这些。许多工作岗位 仍然将 jQuery 列为必备技能之一。值得庆幸的是,Internet Explorer 11 是 IE 浏览器 的最后一个版本,随着 IE 的消失 jQuery 也可能逐渐成为 DOM 操作的遗物。

小程序开发系列之 Prettier 格式化

小程序开发系列之 Prettier 格式化

【译】CSS继承:介绍

【译】CSS继承:介绍