jQuery 与 document.querySelectorAll

IT技术 javascript jquery html css-selectors jquery-selectors
2021-03-06 22:45:29

我曾多次听说 jQuery 最强大的资产是它查询和操作 DOM 中元素的方式:您可以使用 CSS 查询来创建在常规 javascript 中很难做到的复杂查询。但是,据我所知,您可以使用document.querySelector获得相同的结果,document.querySelectorAllInternet Explorer 8 及更高版本支持。

所以问题是:如果 jQuery 最强大的资产可以用纯 JavaScript 实现,为什么要“冒险”jQuery 的开销?

我知道 jQuery 不仅仅是 CSS 选择器,例如跨浏览器 AJAX、漂亮的事件附加等。但它的查询部分是 jQuery 实力的重要组成部分!

有什么想法吗?

6个回答

document.querySelectorAll() 浏览器之间存在一些不一致,并且在较旧的浏览器中不受支持这现在可能不会再造成任何麻烦了它有一个非常不直观的作用域机制和其他一些不太好的特性同样使用 javascript,您在处理这些查询的结果集时会更加困难,在许多情况下您可能想要这样做。jQuery提供的功能像他们的工作:filter()find()children()parent()map()not()和几个。更不用说 jQuery 使用伪类选择器的能力了。

但是,我不会认为这些东西是 jQuery 最强大的特性,而是其他东西,比如以跨浏览器兼容的方式或 ajax 界面在 dom(事件、样式、动画和操作)上“工作”

如果您只想要来自 jQuery 的选择器引擎,您可以使用 jQuery 本身正在使用的一个:Sizzle这样您就可以拥有 jQuery 选择器引擎的强大功能,而不会产生令人讨厌的开销。

编辑:只是为了记录,我是一个巨大的香草 JavaScript 粉丝。尽管如此,您有时需要 10 行 JavaScript,而您需要编写 1 行 jQuery,这是事实。

当然,您必须遵守纪律,不要像这样编写 jQuery:

$('ul.first').find('.foo').css('background-color', 'red').end().find('.bar').css('background-color', 'green').end();

这非常难以阅读,而后者非常清楚:

$('ul.first')
   .find('.foo')
      .css('background-color', 'red')
.end()
   .find('.bar')
      .css('background-color', 'green')
.end();

上面的伪代码说明了等效的 JavaScript 会复杂得多:

1)找到元素,考虑取所有元素或只取第一个。

// $('ul.first')
// taking querySelectorAll has to be considered
var e = document.querySelector("ul.first");

2)通过一些(可能是嵌套或递归)循环遍历子节点数组并检查类(类列表并非在所有浏览器中都可用!)

//.find('.foo')
for (var i = 0;i<e.length;i++){
     // older browser don't have element.classList -> even more complex
     e[i].children.classList.contains('foo');
     // do some more magic stuff here
}

3)应用css样式

// .css('background-color', 'green')
// note different notation
element.style.backgroundColor = "green" // or
element.style["background-color"] = "green"

这段代码至少是您使用 jQuery 编写的代码行数的两倍。此外,您还必须考虑跨浏览器问题,这会损害本机代码严重速度优势(除了可靠性之外)。

querySelectorAll浏览器之间有什么样的不一致而如何将使用jQuery解决这个问题,因为jQuery的使用 querySelectorAll时,可用?
2021-04-19 22:45:29
@Vanuan 这可能不是必需的,但是如果您仔细阅读我的答案,您会注意到,querySelector 有一个严重的范围界定问题,当以您建议的方式使用时,可能会给您带来很多误报。尽管如此,尽管您可以出于某些挑剔的原因自由地投票赞成或反对,但我认为这不是使用粗鲁语言的理由。
2021-04-26 22:45:29
诚然,一行代码可能包含无穷无尽的代码链,这在调试过程中会非常烦人。
2021-05-01 22:45:29
“2)通过一些(可能是嵌套或递归)循环迭代子节点数组并检查类” << 这完全是废话。您可以对上一步中的元素使用 querySelectorAll。
2021-05-02 22:45:29
@Christoph 由于这很容易,我为 IE8 及更高版本添加了兼容性。仍然是巨大的速度优势(5-20​​ 倍)。代码在像 IE8 这样的旧浏览器中运行得更慢只是一个错误的假设。
2021-05-05 22:45:29

如果您正在为 IE8 或更高版本优化您的页面,您应该真正考虑是否需要 jquery。现代浏览器本身就有很多 jquery 提供的资源。

如果您关心性能,则可以使用本机 javascript获得令人难以置信的性能优势(快 2-10)http : //jsperf.com/jquery-vs-native-selector-and-element-style/2

我将 div-tagcloud 从jquery 转换原生 javascript(兼容 IE8+),结果令人印象深刻。只需一点开销,速度就提高了 4 倍。

                    Number of lines       Execution Time                       
Jquery version :        340                    155ms
Native version :        370                    27ms

您可能不需要 Jquery 提供了一个非常好的概述,其中本机方法替换了哪个浏览器版本。

http://youmightnotneedjquery.com/


附录:进一步的速度比较本地方法如何与 jquery 竞争

+1 很好的答案!在过去的 4 或 5 年里,无论何时何地,我一直在慢慢地用原始 JavaScript 替换旧的 jQuery 代码。当然,jQuery 对某些事情非常有用,当我觉得我得到了实实在在的好处时,我会将它用于那些事情。
2021-04-20 22:45:29
@Christoph 当然,这些方法不是 100% 相等的,jquery 通常会提供更多便利。我更新了答案以表明这只是一个边缘情况,我实际上找不到任何其他 jquery 表现更好的情况。这个问题没有重点。
2021-04-27 22:45:29
虽然一些代码示例是错误的,但概述很好......例如$(el).find(selector)不等于el.querySelectorAll(selector)并且本机方法的性能通常非常糟糕:stackoverflow.com/q/14647470/1047823
2021-05-04 22:45:29
@Christoph 您能否详细说明,为什么您认为这些方法不同?当然,在某些边缘情况下,jquery 可以表现得更好,但我还没有看到 DOM-Manipulation 的情况。
2021-05-05 22:45:29
无需进一步阐述,只需阅读我的答案,查看我链接到的小提琴和文章。此外,(至少 atm)大多数本机 Array 方法在速度上不如天真的 js 实现(就像我在第一条评论中的问题中链接的那样)。这些不是边缘情况,而是标准情况。但同样,这个问题的主要焦点不是速度。
2021-05-11 22:45:29

要了解 jQuery 为何如此受欢迎,重要的是要了解我们从何而来!

大约十年前,顶级浏览器是 IE6、Netscape 8 和 Firefox 1.5。在那个年代,除了Document.getElementById().

所以,当 jQuery于 2006 年发布,它是非常具有革命性的。当时,jQuery 为如何轻松选择/更改 HTML 元素和触发事件设定了标准,因为它的灵活性和浏览器支持是前所未有的。

现在,十多年后,许多使 jQuery 如此流行的特性已包含在 javaScript 标准中:

这些在 2005 年普遍不可用。它们今天的事实显然回避了我们为什么应该使用 jQuery 的问题。事实上,人们越来越想知道我们是否应该使用 jQuery

所以,如果你认为你对 JavaScript 的了解足以在没有 jQuery 的情况下完成,请这样做!不要因为有太多人在使用 jQuery 而感到被迫使用 jQuery!

那是因为 jQuery 可以做的远不止querySelectorAll.

首先,jQuery(尤其是 Sizzle)适用于像 IE7-8 这样不支持 CSS2.1-3 选择器的旧浏览器。

此外,Sizzle(它是 jQuery 背后的选择器引擎)为您提供了许多更高级的选择器工具,如:selected伪类、高级:not()选择器、更复杂的语法,如 in$("> .children")等等。

它可以跨浏览器,完美地提供 jQuery 所能提供的所有功能(插件和 API)。

是的,如果您认为您可以依赖简单的类和 id 选择器,那么 jQuery 对您来说太过分了,您将付出夸张的回报。但是,如果您不这样做,并且想利用 jQuery 的所有优点,请使用它。

querySelectorAll如果可用,jQuery 的 Sizzle 选择器引擎可以使用它还可以消除浏览器之间的不一致,以实现统一的结果。如果您不想使用所有 jQuery,您可以单独使用 Sizzle。这是一个非常基本的发明轮子。

以下是一些来自源代码的精选内容,展示了 jQuery(w/ Sizzle) 为您整理的内容:

Safari 怪癖模式:

if ( document.querySelectorAll ) {
  (function(){
    var oldSizzle = Sizzle,
      div = document.createElement("div"),
      id = "__sizzle__";

    div.innerHTML = "<p class='TEST'></p>";

    // Safari can't handle uppercase or unicode characters when
    // in quirks mode.
    if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
      return;
    }

如果该守卫失败,它将使用它的 Sizzle 版本,该版本未使用querySelectorAll. 再往下是 IE、Opera 和 Blackberry 浏览器不一致的特定处理。

  // Check parentNode to catch when Blackberry 4.6 returns
  // nodes that are no longer in the document #6963
  if ( elem && elem.parentNode ) {
    // Handle the case where IE and Opera return items
    // by name instead of ID
    if ( elem.id === match[3] ) {
      return makeArray( [ elem ], extra );
    }

  } else {
    return makeArray( [], extra );
  }

如果所有其他方法都失败,它将返回oldSizzle(query, context, extra, seed).