嵌套项中的querySelector / getElementByClassName顺序

时间:2015-04-08 18:18:30

标签: javascript dom css-selectors selectors-api

我需要了解它是如何工作的,这样我才能编写正确的代码。

<div class="element">
  <div class="content">
    <contents>
    <div class="element">
      <contents>
      <div class="thisClass"></div>
    </div>
  </div>
  <div class="thisClass"></div>
</div>

我有一个包含具有相似结构和类的子元素的元素。如果我做

var element = document.querySelector('.element'); // this returns the parent
element.querySelector('.thisClass') // ok I got it so far

编辑: 我想确保始终从父级获取元素('.thisClass'),无论父级子元素的顺序是什么,并使用最佳脚本。

我非常厌倦像工作狂一样工作,我是原生JS的新手,我希望这很清楚。

2 个答案:

答案 0 :(得分:7)

var element = document.querySelector('.element'); // this returns the parent
element.querySelector('.thisClass')
     

这会带来什么回报?为什么?

它将返回此元素:

<div class="element">
  <div class="content">
    <contents>
    <div class="element">
      <contents>
      <div class="thisClass"></div><!-- <===== Here -->
    </div>
  </div>
  <div class="thisClass"></div>
</div>

&#34;为什么&#34;是因为querySelector和类似的方法在文档顺序中工作,这是文档从上到下的顺序(例如,好像写成HTML)。换句话说,它是元素的depth-first search


重新编辑:

  

我想确保始终从父级获取元素(&#39; .thisClass&#39;),无论父级子元素的顺序是什么,并使用最佳脚本

彻底改变了这个问题。答案是:你不能使用querySelector(好吧,不是没有捏造一点东西)。您有两种选择:

  1. 循环遍历父元素的childNodes(或children)列表,或

  2. 稍微捏造一些东西并使用querySelector

  3. #1相当明显,但为了完整性:

    var element = document.querySelector('.element');
    var targetElement, node;
    for (node = element.firstChild; node; node = node.nextSibling) {
        if (node.nodeType === 1 && node.className.match(/\bthisClass\b/)) {
            targetElement = node;
            break;
        }
    }
    

    或者,如果您可以依赖于使用现代浏览器,则可以使用firstElementChildnextElementSibling并跳过nodeType检查。

    #2对于浏览器来说是更多的工作,并且在这种情况下你可能很难证明你只是在寻找像类名一样简单的东西,但这里有什么捏造querySelector看起来像:

    var markerId = "some-unique-string-you-know-is-not-used-as-an-id-in-your-document";
    var element = document.querySelector('.element');
    if (!element.id) {
        element.id = markerId;
    }
    var targetElement = document.querySelector('#' + markerId + ' > .thisClass');
    if (element.id == markerId) {
        element.id = "";
    }
    

    你可以看到它是如何工作的:我们确保该元素有id,然后使用直接子组合document.querySelector(不是element.querySelector)用id寻找元素的第一个直接子元素。然后,如果我们设置它,我们会移除id

    同样,它为浏览器做了更多工作,而且代码并不短,但如果您有复杂的选择器,可能会有用例......

答案 1 :(得分:1)

尝试使用此代码对其进行可视化:

(function () {
  'use strict'

  var element1 = document.querySelector('.element')
  var element2 = document.querySelector('.thisClass')

  /* .element will have a red border */
  /* .thisClass will have a yellow border */

  element1.style.border = '5px solid red'
  element2.style.border = '5px solid yellow'
})()

我在jsBin上创建了一个演示来尝试:demo

如您所见,document.querySelector始终按文档顺序返回第一个元素。