jQuery与document.querySelectorAll


161

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

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

我知道jQuery不仅具有CSS选择器,例如跨浏览器AJAX,漂亮的事件附加等。但是它的查询部分是jQuery实力的很大一部分!

有什么想法吗?


4
(1)使用jQuery,DOM遍历/修改要快得多。(2)它添加了自己的选择器,这些选择器在querySelector方法中不起作用。(3)使用jQuery进行AJAX调用更加快捷,容易。(4)在IE6 +中的支持。我敢肯定,还有很多其他观点。
James Allardice

12
(5)...懒惰打字员的缩写$()是必须的。
Dexter Huinda

4
更容易,是的,为什么要更快?据我所知,jQuery可以转换为常规javascript ...
Joel_Blum

4
@JamesAllardice-跨浏览器XMLHttpRequest的“所有麻烦”可能是您编写一次并放入您自己的库中的30行代码
RobG

6
@RobG-是的,我并不是说,如果您要使用jQuery,那就只使用jQuery。这只是好处之一。如果您需要简单的DOM遍历,AJAX和querySelectorAll,并且都需要它们在较旧的浏览器中运行,那么jQuery是一个明显的选择。我并不是说您应该像这样使用它。
James Allardice

Answers:


127

document.querySelectorAll() 具有跨浏览器的一些矛盾和旧的浏览器不支持这可能不会引起任何麻烦了现在。它具有非常直观的作用域机制和其他一些不太好用的功能。另外,使用javascript时,您将很难处理这些查询的结果集,在许多情况下,您可能想要这样做。jQuery提供的功能像他们的工作:filter()find()children()parent()map()not()和几个。更不用说jQuery使用伪类选择器的能力。

但是,我不会将这些东西视为jQuery最强大的功能,而是将其视为其他东西,例如以跨浏览器兼容的方式或ajax接口在dom上“工作”(事件,样式,动画和操作)。

如果您只希望jQuery的选择器引擎,则可以使用一个jQuery本身正在使用的:Sizzle这样,您就可以拥有jQuerys Selector引擎的强大功能,而不会造成麻烦。

编辑:仅作记录,我是一个巨大的香草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编写的代码行的两倍。另外,您还必须考虑跨浏览器的问题,这将损害本机代码的严重速度优势(除了可靠性之外)。


33
querySelectorAll浏览器之间有什么样的不一致之处?而如何将使用jQuery解决这个问题,因为jQuery的使用 querySelectorAll时,可用?

3
的确,一行代码可以包含无穷无尽的代码链,这在调试过程中可能会很烦人。
Dexter Huinda

1
“ 2)通过一些(可能是嵌套的或递归的)循环遍历子节点数组并检查类” <<这是一个完全废话。您可以在上一步中对元素使用querySelectorAll。
Vanuan

5
@Vanuan这可能不是必需的,但是如果您已经完全阅读了我的答案,您会注意到,querySelector存在一个严重的范围界定问题,以提议的方式使用时,可能会给您带来很多误报。尽管如此,尽管您出于某些挑剔的原因可以自由投票或拒绝投票,但我认为这不是使用粗鲁语言的理由。
Christoph

2
@Christoph因为这很容易,所以我增加了对IE8及更高版本的兼容性。仍具有巨大的速度优势(5-20​​倍)。认为代码在IE8之类的旧浏览器中运行速度会变慢,这只是一个错误的假设。
Pascalius

60

如果要针对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竞争


很好的概述,尽管某些代码示例是错误的...例如$(el).find(selector),不等于,el.querySelectorAll(selector)并且本机方法的性能通常非常糟糕:stackoverflow.com/q/14647470/1047823
Christoph

@Christoph您能详细说明一下,为什么您认为方法不同吗?当然,在某些情况下,jquery的性能会更好,但是我还没有看到DOM操作的例子。
Pascalius

1
无需进一步阐述,只需阅读我的答案,看看小提琴和我链接的文章即可。而且,(至少是atm)大多数本机Array方法的速度都比朴素的js实现要差(就像我在第一条评论中提到的问题)。这些不是边缘情况,而是标准情况。但是,这个问题的主要重点不是速度。
Christoph

2
@Christoph当然,这些方法不是100%相等的,并且jquery通常会提供更多的便利。我更新了答案以表明这只是一个极端情况,实际上我找不到jquery表现更好的其他情况。这个问题没有主要重点。
Pascalius 2014年

+1好答案!我一直在慢慢地用原始的JavaScript在过去的4年或5年更换旧的jQuery代码无论何时何地可能。当然,jQuery是伟大的一些事情,我使用它的那些东西的时候,我觉得我得到了坚实的好处。
是Barry

13

要了解jQuery为什么如此受欢迎,了解我们的来源很重要!

大约十年前,顶级浏览器是IE6,Netscape 8和Firefox 1.5。那时,几乎没有跨浏览器的方法可以从DOM中选择元素Document.getElementById()

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

十多年来,现在,使jQuery如此流行的许多功能已包含在javaScript标准中:

这些东西早在2005年就没有普遍使用。它们今天已经成为事实,这显然引出了我们为什么应该完全使用jQuery的问题。确实,人们越来越怀疑我们是否应该使用jQuery

因此,如果您认为您对JavaScript的理解足够好,可以不用jQuery而行,请这样做!不要因为被其他许多人使用而被迫使用jQuery!


7

这是因为jQuery可以做的不止于此querySelectorAll

首先,jQuery(特别是Sizzle)适用于不支持CSS2.1-3选择器的IE7-8等较旧的浏览器。

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

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

是的,如果您认为可以依靠简单的类和id选择器,则jQuery对您来说太多了,您将获得一笔不菲的回报。但是,如果您不这样做,并且想利用所有jQuery的优点,请使用它。


7

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)


6

就代码的可维护性而言,坚持使用广泛使用的库有几个原因。

主要问题之一是它们有据可查,并且具有诸如... stackexchange之类的社区,可以在其中找到有关图书馆的帮助。使用自定义编码库,您将拥有源代码,甚至可能有一个how-to文档,除非编码人员花费比编写代码更多的时间来记录代码,这种情况很少见。

编写自己的库可能对您有用有用,但是坐在隔壁的实习生可能更容易上手使用jQuery之类的东西。

如果愿意,可以将其称为网络效果。这并不是说该代码在jQuery中会更好。仅仅是因为代码的简洁性,使得所有技能水平的程序员都可以更容易地掌握其总体结构,这仅仅是因为您正在查看的文件中一次可以看到更多的功能代码。从这个意义上讲,5行代码优于10行代码。

综上所述,我认为jQuery的主要好处是简洁的代码和无处不在的代码。


6

如果我想应用相同的属性,例如,隐藏“ my-class”类的所有元素,这是一个比较。这是使用jQuery的原因之一。

jQuery的:

$('.my-class').hide();

JavaScript:

var cls = document.querySelectorAll('.my-class');
for (var i = 0; i < cls.length; i++) {
    cls[i].style.display = 'none';
}

由于jQuery已经如此流行,他们应该使document.querySelector()的行为就像$()一样。相反,document.querySelector()仅选择第一个匹配元素,这仅使它有用一半。


4
我会在这里做一个。
菲利普·森

好吧,你总是可以走一条简单的路线document.querySelectorAll('.my-class').forEach(el => el.style.display = 'none');。即使更短,性能明智的本机总是更好。
阿兰·克鲁兹

从用户的角度来看,在不到0.1秒的时间内发生的所有事情都会立即发生。因此,native甚至更快,只有当jQuery实现慢了0.1秒时才更好。在现实世界中,情况并非如此。
yurin

3

就像官方网站所说的:“ jQuery:更少写,做更多,JavaScript库”

尝试翻译以下没有任何库的jQuery代码

$("p.neat").addClass("ohmy").show("slow");

1
我同意这一点,但是可读性如何?您如何记录很多不相关的事情的长代码行?您如何调试此类怪兽?
Joel_Blum

@ user1032663是文档约定的问题。
Christoph

1
jQuery(或您选择的任何“流行”库)的替代方案不是从头开始编写所有内容,而是使用适合您目的且编写良好的库。您可能自己编写了部分内容,或者选择了MyLibrary之类的模块化库来仅包含所需内容。
RobG

2
您选择的示例并不能真正证明您的意思:问题是在“选择器”省中寻找差异。addClass()show()没有真正计数。至于$('p.neat'),您可以看一下querySelector / All。
kumarharsh

document.querySelectorAll('p.neat').forEach(p=>p.classList.add('ohmy'));然后让CSS完成其余的工作。稍长的代码,但很多更有效。当然,他的解决方案在旧版IE时代还不可用。“更多”部分具有讽刺意味。jQuery需要大约一百行代码来查找某些内容,因此做更多的事情并不总是有效的。
曼戈

2

我认为,真正的答案是jQuery早querySelector/querySelectorAll在所有主流浏览器中就已经开发了。

jQuery的最初版本是2006年。实际上,即使jQuery 也不是第一个实现CSS选择器的人

IE是最后一个实现的浏览器querySelector/querySelectorAll。其第八版于2009年发布

因此,现在,DOM元素选择器不再是jQuery的强项。但是,它仍然有很多好处,例如更改元素的CSS和html内容的快捷方式,动画,事件绑定,ajax。


1

这是一个古老的问题,但是五年后,值得再次探讨。在这里,我仅讨论jQuery的选择器方面。

document.querySelector[All]当前所有的浏览器(包括IE8)都支持该功能,因此兼容性不再是问题。我还没有发现任何性能问题(应该比它慢document.getElementById,但我自己的测试表明它要快一些)。

因此,当涉及直接操作元素时,它比jQuery更受欢迎。

例如:

var element=document.querySelector('h1');
element.innerHTML='Hello';

千差万别优于:

var $element=$('h1');
$element.html('hello');

为了做任何事情,jQuery必须运行一百行代码(我曾经通过上面的代码进行跟踪,以了解jQuery实际在做什么)。这显然是在浪费每个人的时间。

jQuery的另一个显着成本是将所有内容包装在新jQuery对象中的事实。如果您需要再次解开对象或使用一种对象方法来处理已经暴露在原始元素上的属性,则这种开销特别浪费。

但是,jQuery的优势在于处理集合的方式。如果要求设置多个元素的属性,则jQuery有一个内置each方法,该方法允许如下所示:

var $elements=$('h2');  //  multiple elements
$elements.html('hello');

要使用Vanilla JavaScript做到这一点,需要执行以下操作:

var elements=document.querySelectorAll('h2');
elements.forEach(function(e) {
    e.innerHTML='Hello';
});

有些让人望而生畏。

jQuery选择器也略有不同,但是现代浏览器(不包括IE8)不会带来太多好处。

通常,我警告不要将jQuery用于项目:

  • jQuery是一个外部库,它增加了项目的开销,并增加了对第三方的依赖。
  • jQuery函数在处理方面非常昂贵。
  • jQuery施加了一种需要学习的方法,并且可能与代码的其他方面竞争。
  • jQuery很难在JavaScript中公开新功能。

如果以上都不重要,请按照您的意愿去做。但是,jQuery对跨平台开发不再像以前那么重要了,因为现代JavaScript和CSS比以前要走的更远。

这没有提及jQuery的其他功能。但是,我认为他们也需要仔细观察。


1
您的语法甚至是不正确的,更不要说其他错误的东西,例如“在Java脚本中很难公开新功能” JQuery的工作甚至不是公开新功能,这是为了使您易于DOM操作和做一些简单的事情。像Javascript中的10行 您的整个评论没有任何意义,并且包含很多错误的内容。考虑改善它。
男孩

@Boypro感谢您的评论,但是它也充满了错误。也许您想分享我的回答对您造成的影响很大。什么是“甚至不正确的”。更妙的是,您可能想贡献自己的答案。问题是当原始JavaScript可以做很多事情时使用jQuery的成本。考虑回答。
曼戈

0
$(“#id”)vs document.querySelectorAll(“#id”)

交易是通过$()函数创建一个数组,然后为您分解。但是通过document.querySelectorAll()它创建一个数组,您必须将其分解。


0

只是对此做一个评论,当使用Material Design Lite时,jQuery选择器由于某种原因不会返回用于Material Design的属性。

对于:

<div class="logonfield mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
        <input class="mdl-textfield__input" type="text" id="myinputfield" required>
        <label class="mdl-textfield__label" for="myinputfield">Enter something..</label>
      </div>

这有效:

document.querySelector('#myinputfield').parentNode.MaterialTextfield.change();

这不是:

$('#myinputfield').parentNode.MaterialTextfield.change();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.