我希望使用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
答案 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>