(现在比以往任何时候都更)你可能不需要 jQuery

Avatar of Ollie Williams
Ollie Williams 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

自从 jQuery 于 2006 年发布以来,DOM 和原生浏览器 API 已经取得了长足的进步。人们从 2013 年开始撰写“你可能不需要 jQuery”的文章(参见此 经典网站 和此 经典仓库)。我不想重提旧事,但自您可能偶然发现的上一篇“你可能不需要 jQuery”文章以来,浏览器领域发生了很大的变化。浏览器继续实现新的 API,从而消除了无库开发的痛苦,其中许多 API 直接复制自 jQuery。

让我们来看一些 jQuery 方法的原生替代方案。

从页面中删除元素

还记得使用原生 DOM 从页面中删除元素时那种令人抓狂的迂回方式吗?el.parentNode.removeChild(el);?以下是 jQuery 方式和新的改进的原生方式的比较。

jQuery

var $elem = $(".someClass") //select the element 
$elem.remove(); //remove the element

不使用 jQuery

var elem = document.querySelector(".someClass"); //select the element
elem.remove() //remove the element

在本文的其余部分,我们将假设$elem是 jQuery 选择的一组元素,而elem是原生 JavaScript 选择的 DOM 元素。

在元素前插入元素

jQuery

$elem.prepend($someOtherElem);

不使用 jQuery

elem.prepend(someOtherElem);

在另一个元素前插入元素

jQuery

$elem.before($someOtherElem);

不使用 jQuery

elem.before(someOtherElem);

用另一个元素替换元素

jQuery

$elem.replaceWith($someOtherElem);

不使用 jQuery

elem.replaceWith(someOtherElem);

查找与给定选择器匹配的最近祖先

jQuery

$elem.closest("div");

不使用 jQuery

elem.closest("div");

DOM 操作方法的浏览器支持

这些方法现在拥有相当不错的浏览器支持度

此浏览器支持数据来自 Caniuse,其中包含更多详细信息。数字表示浏览器从该版本开始支持该功能。

桌面

ChromeFirefoxIEEdgeSafari
54491710

移动/平板电脑

Android ChromeAndroid FirefoxAndroidiOS Safari
12712712710.0-10.2

它们目前也正在 Edge 中实现。

淡入元素

jQuery

$elem.fadeIn();

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

.thingy {
  display: none;
  opacity: 0;
  transition: .8s;
}
elem.style.display = "block";
requestAnimationFrame(() => elem.style.opacity = 1);

仅调用一次事件处理程序回调

jQuery

$elem.one("click", someFunc);

过去,在编写纯 JavaScript 时,我们必须在回调函数内调用 removeEventListener。

function dostuff() {
  alert("some stuff happened");
  this.removeEventListener("click", dostuff);
}
var button = document.querySelector("button");
button.addEventListener("click", dostuff);

现在事情变得更加简洁了。您可能有时会看到传递给addEventListener的第三个可选参数。这是一个布尔值,用于决定事件捕获或事件冒泡。但是,如今,第三个参数可以是配置对象。

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

如果您仍然希望使用事件捕获以及仅调用一次回调,那么您也可以在配置对象中指定它

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

动画

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

$elem.animate({
  width: "70%",
  opacity: 0.4,
  marginLeft: "0.6in",
  fontSize: "3em",
  borderWidth: "10px"
}, 1500);

文档中写道“所有动画属性都应动画到单个数值,除非在下面另有说明;大多数非数值属性无法使用基本的 jQuery 功能进行动画。”这排除了转换,并且您需要一个插件才能为颜色设置动画。使用新的 Web Animations API 会好得多。

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

Ajax

jQuery 在过去另一个关键的卖点是 Ajax。jQuery 将XMLHttpRequest的丑陋部分抽象化了

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

新的 fetch APIXMLHttpRequest的更优替代方案,现在所有现代浏览器都支持它。

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

诚然,fetch 可能比这个小程序示例复杂一些。例如,从fetch()返回的 Promise 在 HTTP 错误状态下不会被拒绝。但是,它比建立在XMLHttpRequest之上的任何东西都要 通用得多。

但是,如果我们想要易用性,则有一个更简单的选择越来越受欢迎——但它不是浏览器的原生功能,这让我想到……

微型库的兴起

Axios 是一个流行的 Ajax 库。它是微型库的一个很好的例子——一个旨在只做一件事的库。虽然大多数库的测试不会像 jQuery 那样完善,但它们通常可以作为 jQuery 这个庞然大物的一种有吸引力的替代方案。

(几乎)所有内容都可以使用 polyfill

所以现在您已经意识到 DOM 现在非常易于使用!但是,也许您只是查看了这些开发成果,然后想到“哦,好吧,仍然需要支持 IE 9,所以我最好使用 jQuery”。大多数情况下,Can I Use 对您想要使用的某个功能所说的内容并不重要。您可以使用任何您喜欢的功能,polyfill 可以填补空白。曾经有一段时间,如果您想使用一个花哨的新浏览器功能,您必须找到一个 polyfill,然后将其包含在您的页面中。为 IE 9 中缺少的所有功能执行此操作将是一项艰巨的任务。现在它很简单

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

这个简单的脚本标签几乎可以为任何内容提供 polyfill。如果您还没有听说过来自金融时报的这项 polyfill 服务,您可以在 polyfill.io 上阅读相关信息。

2017 年遍历 NodeList

jQuery 的广泛采用并非仅仅因为它可靠地解决了浏览器错误和 IE 遗留问题中的不一致性。如今,jQuery 还有一个卖点:**迭代**。

NodeList 不可迭代,这确实不合理。开发人员不得不绞尽脑汁才能让它们变得可迭代。经典的 for 循环可能是性能最优化的方案,但肯定不是我喜欢的输入方式。因此,我们最终得到了这种丑陋的方式

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

或者

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

最近,我们能够使用 Array.from,这是一种更简洁、更优雅地将 NodeList 转换为数组的方式。

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

但最大的新闻是,NodeList 现在默认情况下是可迭代的

现在只需输入

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

Edge 是最后一个不支持可迭代 NodeList 的现代浏览器,但目前正在开发中

jQuery 慢吗?

jQuery 可能会比写得糟糕的原生 JS 快,但这仅仅是学习更好 JavaScript 的一个好理由!Paul Irish 是 jQuery 项目的贡献者,他得出结论

以下是 jQuery 的创建者在他(非常重要的)Javascript 书籍Secrets of the JavaScript Ninja 中关于学习原生 DOM 的看法

“如果库可以为你处理所有事情,为什么你需要了解它的工作原理?最令人信服的原因是性能。了解库中 DOM 修改的工作原理可以让你编写更好、更快的代码。”

我不喜欢 jQuery 的地方

jQuery 试图完全替换某些浏览器 API 中剩下的丑陋部分,而不是仅仅将其平滑处理。通过返回 jQuery 对象而不是 NodeList,内置的浏览器方法本质上是被禁止的,这意味着你被锁定在 jQuery 的做事方式中。对于初学者来说,曾经让前端脚本变得易于使用的东西现在却成为了障碍,因为它本质上意味着做任何事情都有两种重复的方式。如果你想轻松地阅读其他人的代码并将其应用于需要原生 JS 和需要 jQuery 的工作,那么你需要学习两倍的内容。但是,也有一些库采用了对 jQuery 爱好者来说会感到熟悉 API,但返回 NodeList 而不是对象……

不能没有 $?

也许你已经喜欢上了 jQuery 的 $。某些微型库试图模仿 jQuery API。

  • Lea Verou,W3C CSS 工作组的受邀专家,她本人撰写了文章jQuery Considered Harmful,是Bliss.js 的作者。Bliss 使用熟悉的 $ 语法,但返回 NodeList。
  • 与此同时,Paul Irish 发布了Bling.js因为你想要 jQuery 的 $,但不想用 jQuery”。
  • Remy Sharp 提供了一个类似的微型库,恰如其分地命名为min.js

我并非反 jQuery 的势利小人。一些优秀的开发者仍然选择使用它。如果你已经习惯使用它并且熟悉它的 API,那么没有很大的理由放弃它。最终,有些人使用 jQuery 并知道什么是闭包,并且编写企业级 Web 应用,而有些人使用原生 JS 却不知道。许多工作仍然将其列为必备技能。但是,对于任何刚入门的人来说,它看起来越来越像一个糟糕的选择。谢天谢地,Internet Explorer 11 是那个该死的玩意儿的最终版本。一旦 IE 消失,整个浏览器环境将成为常青树,jQuery 将越来越被视为 DOM 肮脏过去中一个过时的遗物。