CSS选择器:last-child和:not

时间:2019-02-17 11:36:00

标签: css css-selectors

我希望使用CSS选择器在具有以下JavaScript代码的最后一个非隐藏目录6中选择最后一个文件:

const root = document.querySelector('#root');
const last = root.querySelector('.dir:not(.hidden):last-child .file:last-child');
console.log(last.innerHTML);

但是结果是3。我想知道是否有任何方法仅使用CSS选择器来获取6,而不使用递归Javascript代码。

HTML:

<div id='root'>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>1</div>
      <div class='file'>2</div>
      <div class='file'>3</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>4</div>
      <div class='file'>5</div>
      <div class='file'>6</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='dir hidden'>
        <div class='dir'>
          <div class='file'>7</div>
          <div class='file'>8</div>
          <div class='file'>9</div>
        </div>
      </div>
    </div>
  </div>
</div>

https://jsbin.com/moyagivopi/1/edit?html,js,console

https://jsbin.com/huteqabiga/1/edit?html,js,console

https://jsbin.com/vosereyime/1/edit?html,js,console

3 个答案:

答案 0 :(得分:2)

您可以将选择分为两步,首先获取没有.hidden的元素,然后在最后一个中选择最后一个。我认为纯CSS不会给您带来机会

var last = document.querySelectorAll('#root > .dir:not(.hidden) > .dir:not(.hidden)');

var element = last[last.length - 1].querySelector('.file:last-child');

console.log(element.innerHTML);
<div id='root'>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>1</div>
      <div class='file'>2</div>
      <div class='file'>3</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>4</div>
      <div class='file'>5</div>
      <div class='file'>6</div>
    </div>
  </div>
  <div class='dir hidden'>
    <div class='dir'>
      <div class='file'>7</div>
      <div class='file'>8</div>
      <div class='file'>9</div>
    </div>
  </div>
</div>

另一个例子:

var last = document.querySelectorAll('#root > .dir:not(.hidden) > .dir:not(.hidden)');

var element = last[last.length - 1].querySelector('.file:last-child');

console.log(element.innerHTML);
<div id='root'>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>1</div>
      <div class='file'>2</div>
      <div class='file'>3</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>4</div>
      <div class='file'>5</div>
      <div class='file'>6</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir hidden'>
      <div class='file'>7</div>
      <div class='file'>8</div>
      <div class='file'>9</div>
    </div>
  </div>
</div>

另一个想法是选择所有最后一个.file,然后从最后一个进行测试,以查看是否有.hidden类的祖先。与以前的解决方案不同,它可以在任何嵌套级别使用。

//got from this answer https://stackoverflow.com/a/16863971/8620333
function hasSomeParentTheClass(element, classname) {
  if (element.classList.contains(classname)) return true;
  return element.parentElement && hasSomeParentTheClass(element.parentElement, classname);
}

var elements = document.querySelectorAll('.file');
var i = elements.length - 1;
for (; i >= 0; i--) {
  if (!hasSomeParentTheClass(elements[i], 'hidden')) {
    break;
  }
}

console.log(elements[i].innerHTML);
<div id='root'>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>1</div>
      <div class='file'>2</div>
      <div class='file'>3</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>4</div>
      <div class='file'>5</div>
      <div class='file'>6</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir '>
    <div class='file'>10</div>
      <div class='dir hidden'>
        <div class='file'>7</div>
        <div class='file'>8</div>
        <div class='file'>9</div>
      </div>
    </div>
  </div>
</div>

由OP编辑:如果文件10存在,则删除:last-child

答案 1 :(得分:1)

您可以使用querySelectorAll然后切片以获取数组中的最后一个元素。

请参阅下文。

const root = document.querySelector('#root');
const last = Array.prototype.slice.call(root.querySelectorAll('.dir:not(.hidden):first-child > .file:last-child')).slice(-1)[0];
console.log(last.innerHTML);
<div id='root'>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>1</div>
      <div class='file'>2</div>
      <div class='file'>3</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>4</div>
      <div class='file'>5</div>
      <div class='file'>6</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir hidden'>
      <div class='file'>7</div>
      <div class='file'>8</div>
      <div class='file'>9</div>
    </div>
  </div>
</div>

答案 2 :(得分:1)

您将不得不使用递归检查隐藏类的所有父节点。我上传了两个摘要,每个用例一个。两者都使用相同的JS。

供参考: https://codeburst.io/learn-and-understand-recursion-in-javascript-b588218e87ea

const root = document.querySelector('#root');
const files = root.querySelectorAll('.file');
var div;

for (var i=0; i< files.length; i++){
  if (!doesParentContainClass(files[i])) {
    div = files[i]; 
  }
}

console.log(div.innerHTML)

function doesParentContainClass(element) {
    if (element.className && element.className.split(' ').indexOf('hidden')>=0) return true;
    return element.parentNode && doesParentContainClass(element.parentNode);
}
<div id='root'>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>1</div>
      <div class='file'>2</div>
      <div class='file'>3</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>4</div>
      <div class='file'>5</div>
      <div class='file'>6</div>
    </div>
  </div>
  <div class='dir hidden'>
    <div class='dir'>
      <div class='file'>7</div>
      <div class='file'>8</div>
      <div class='file'>9</div>
    </div>
  </div>
</div>

const root = document.querySelector('#root');
const files = root.querySelectorAll('.file');
var div;

for (var i=0; i< files.length; i++){
  if (!doesParentContainClass(files[i])) {
    div = files[i]; 
  }
}

console.log(div.innerHTML)

function doesParentContainClass(element) {
    if (element.className && element.className.split(' ').indexOf('hidden')>=0) return true;
    return element.parentNode && doesParentContainClass(element.parentNode);
}
<div id='root'>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>1</div>
      <div class='file'>2</div>
      <div class='file'>3</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>4</div>
      <div class='file'>5</div>
      <div class='file'>6</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='dir hidden'>
        <div class='dir'>
          <div class='file'>7</div>
          <div class='file'>8</div>
          <div class='file'>9</div>
        </div>
      </div>
    </div>
  </div>
</div>

相关问题