有选择兄弟节点的方法吗?

出于某些性能原因,我试图找到一种只选择所选节点的兄弟节点的方法。

比如说,

<div id="outer">
<div id="inner1"></div>
<div id="inner2"></div>
<div id="inner3"></div>
<div id="inner4"></div>
</div>

如果我选择 inner1节点,是否有办法访问它的兄弟节点 inner2-4节点?

210662 次浏览

好吧,当然可以,先接触父母,然后再接触孩子。

 node.parentNode.childNodes[]

或者... 使用 jQuery:

$('#innerId').siblings()

编辑: Cletus 一如既往地鼓舞人心。我进一步挖掘,这就是 jQuery 从本质上获得兄弟姐妹的方式:

function getChildren(n, skipMe){
var r = [];
for ( ; n; n = n.nextSibling )
if ( n.nodeType == 1 && n != skipMe)
r.push( n );
return r;
};


function getSiblings(n) {
return getChildren(n.parentNode.firstChild, n);
}
var childNodeArray = document.getElementById('somethingOtherThanid').childNodes;
var sibling = node.nextSibling;

这将在它之后立即返回兄弟类型,或者不再有其他兄弟类型可用。

[ Edit ] 转念一想,这将不会给出下一个 div标记,而是节点后面的空格。看起来更好

var sibling = node.nextElementSibling;

还存在一个 previousElementSibling

你检查过 jQuery 中的“ Sibling”方法吗?

    sibling: function( n, elem ) {
var r = [];


for ( ; n; n = n.nextSibling ) {
if ( n.nodeType === 1 && n !== elem ) {
r.push( n );
}
}


return r;
}

NodeType = = 1检查元素是否是 html 节点,n! = = 排除当前元素。

我认为你可以使用相同的函数,所有的代码似乎是普通的 javascript。

有几种方法可以做到这一点。

以下任何一种方法都可以解决这个问题。

// METHOD A (ARRAY.FILTER, STRING.INDEXOF)
var siblings = function(node, children) {
siblingList = children.filter(function(val) {
return [node].indexOf(val) != -1;
});
return siblingList;
}


// METHOD B (FOR LOOP, IF STATEMENT, ARRAY.PUSH)
var siblings = function(node, children) {
var siblingList = [];
for (var n = children.length - 1; n >= 0; n--) {
if (children[n] != node) {
siblingList.push(children[n]);
}
}
return siblingList;
}


// METHOD C (STRING.INDEXOF, ARRAY.SPLICE)
var siblings = function(node, children) {
siblingList = children;
index = siblingList.indexOf(node);
if(index != -1) {
siblingList.splice(index, 1);
}
return siblingList;
}

仅供参考: jQuery 代码库是观察 A 级 Javascript 的一个很好的资源。

下面是一个优秀的工具,它以一种非常流线型的方式展示了 jQuery 代码库。 Http://james.padolsey.com/jquery/

x1 = document.getElementById('outer')[0]
.getElementsByTagName('ul')[1]
.getElementsByTagName('li')[2];
x1.setAttribute("id", "buyOnlineLocationFix");

使用 QuerySelectorAll ()循环和迭代

function sibblingOf(children,targetChild){
var children = document.querySelectorAll(children);
for(var i=0; i< children.length; i++){
children[i].addEventListener("click", function(){
for(var y=0; y<children.length;y++){children[y].classList.remove("target")}
this.classList.add("target")
}, false)
}
}


sibblingOf("#outer >div","#inner2");
#outer >div:not(.target){color:red}
<div id="outer">
<div id="inner1">Div 1 </div>
<div id="inner2">Div 2 </div>
<div id="inner3">Div 3 </div>
<div id="inner4">Div 4 </div>
</div>

下面是你如何得到上一个、下一个和所有兄弟姐妹(双方) :

function prevSiblings(target) {
var siblings = [], n = target;
while(n = n.previousElementSibling) siblings.push(n);
return siblings;
}


function nextSiblings(target) {
var siblings = [], n = target;
while(n = n.nextElementSibling) siblings.push(n);
return siblings;
}


function siblings(target) {
var prev = prevSiblings(target) || [],
next = nexSiblings(target) || [];
return prev.concat(next);
}

快点:

var siblings = n => [...n.parentElement.children].filter(c=>c!=n)

Https://codepen.io/anon/pen/lloyrp?editors=1011

以数组的形式获取父元素的子元素,过滤掉这个元素。

编辑:

并过滤掉文本节点(感谢 Pmrotule) :

var siblings = n => [...n.parentElement.children].filter(c=>c.nodeType == 1 && c!=n)

从2017年开始:
直截了当的回答: element.nextElementSibling表示获得正确的元素兄弟

从这里很容易得到所有下一个兄弟姐妹

var n = element, ret = [];
while (n = n.nextElementSibling){
ret.push(n)
}
return ret;

下面的函数将返回一个数组,该数组包含给定元素的所有兄弟元素。

const getSiblings = node => [...node.parentNode.children].filter(c => c !== node)


// get "c" element siblings (excluding itself)
const siblingsToC = getSiblings(document.querySelector('.c'))


console.log( siblingsToC )
<ul>
<li class='a'>a</li>
<li class='b'>b</li>
<li class='c'>c</li>
<li class='d'>d</li>
<li class='e'>e</li>
</ul>

只需将选定的元素作为参数传递给 getSiblings()函数即可。

1)将选定的类添加到目标元素 < br > 2)查找父元素的所有子元素(不包括目标元素 < br > 3)从目标元素中删除类

 <div id = "outer">
<div class="item" id="inner1">Div 1 </div>
<div class="item" id="inner2">Div 2 </div>
<div class="item" id="inner3">Div 3 </div>
<div class="item" id="inner4">Div 4 </div>
</div>






function getSiblings(target) {
target.classList.add('selected');
let siblings = document.querySelecttorAll('#outer .item:not(.currentlySelected)')
target.classList.remove('selected');
return siblings
}

JQuery

$el.siblings();

本土最新,Edge13 +

[...el.parentNode.children].filter((child) =>
child !== el
);

原生(替代)-最新,Edge13 +

Array.from(el.parentNode.children).filter((child) =>
child !== el
);

原生 IE10 +

Array.prototype.filter.call(el.parentNode.children, (child) =>
child !== el
);

可以使用 NextSibiling属性访问以下同级节点。

这就是在事件委托方式中可以做到的,这是添加事件侦听器的动态方式

 document.addEventListener('click', (event) => {
if (event.target.matches("#inner1")) {
console.log(event.targert.nextSibling); //inner2 div
console.log(event.targert.nextSibling.nextSibling); //inner3 div
/* The more of the property you keep appending the further it goes to
the next sibling */
}
})

我的用例是不同的。我必须选择一些 span,它们没有任何 id/class (也没有它们的父类) ,只有一个入口点(#target)。一旦你有了它,用适当的选择器在它的 parent上运行一个 querySelectorAll,使用 :scope,因为你不能简单地使用 > div> span或者 > .foo

注意,如果目标元素与选择器匹配,那么这种方法也会选择目标元素。在下面的示例中,我必须使用 :scope > span:not(#target)来避免选择入口点。

const spanSiblings = document.getElementById("target").parentNode.querySelectorAll(":scope > span");
console.log([...spanSiblings].map(e => e.innerText));
<div>
<span>One</span>
<span id="target">Target</span>
<div>A</div>
<span>Two</span>
<div>B</div>
<div>Hey</div>
</div>