原生 JS如何实现类似Jquery的siblings功能?

如题:
比如我body里面有这么几个链接:

    <a href="javascript:;">连接一</a>
    <a href="javascript:;">连接二</a>
    <a href="javascript:;">连接三</a>
    <a href="javascript:;">连接四</a>
    <a href="javascript:;">连接五</a>
    <a href="javascript:;">连接六</a>
    <a href="javascript:;">连接七</a>
    <a href="javascript:;">连接八</a>
    <a href="javascript:;">连接九</a>
var link = document.getElementsByTagName("a");
for (var i = 0; i < link.length; i++) {
    link[i].addEventListener("click", function() {
        this.style.backgroundColor = "#000";
    })
}

现在能实现单击其中一个链接改变它的背景色,但是如何能实现JQ中很容易实现的功能,点击其中一个,其它的样式也同时变了(切换)。

阅读 8.1k
5 个回答

@小明 大神的启发,写了最优雅,最高效的方式(我自认为)。

<style>
body{
  background:#CCC;
}
a{
  display:inline-block;
  width:100px;
  padding:5px 10px;
  background:#666;
  text-align:center;
  color:#FFF;
  border:solid 3px #333;
  margin:1px;
}
a.active{
  background-color:#FF0;
  border-color:#C00;
  color:#C00;
}
</style>
<div id="parent">
  <a href="javascript:;">连接一</a>
  <a href="javascript:;">连接二</a>
  <a href="javascript:;">连接三</a>
  <a href="javascript:;">连接四</a>
  <a href="javascript:;">连接五</a>
  <a href="javascript:;">连接六</a>
  <a href="javascript:;">连接七</a>
  <a href="javascript:;">连接八</a>
  <a href="javascript:;">连接九</a>
</div>
<script>
document.getElementById("parent").addEventListener("click", function(event){
    if( event.srcElement.tagName.toLowerCase() == "a" ){
        if( this.lastClick != event.target){
            event.target.className = "active";
            if( !!this.lastClick){
                this.lastClick.className = "";
            }
            this.lastClick = event.target;
        } else {
            console.log("重复点击不触发");
        }
    }
});
</script>

以下是老答案:

好像没有原生的方法,试着扩展了一下:

Element.prototype.siblings = function(callback){
    var siblingElement = [];
    var parentAllElement = [];
    if( ! this.parentNode ){
        return siblingElement;
    };
    parentAllElement = this.parentNode.getElementsByTagName(this.tagName);
    for( var i = 0; i < parentAllElement.length ; i++ ){
        if( parentAllElement[i] != this ){
            siblingElement.push(parentAllElement[i]);
            typeof callback == "function" && callback.call(parentAllElement[i]);
        }
    }
    return siblingElement;
};

然后就可以向 jQuery 一样使用 siblings() 了。

var link = document.getElementsByTagName("a");
for (var i = 0; i < link.length; i++) {
    link[i].addEventListener("click", function() {
        this.style.backgroundColor = "#000";
        var siblings = this.siblings(function(){
            this.style.backgroundColor = "#FFF";
        });
        console.log(siblings[0].siblings());
    })
}

附带 html 代码的例子:

<style>
body{
    background:#CCC;
}
a{
    display:block;
    width:100px;
    padding:5px 10px;
    float:left;
    background:#666;
    text-align:center;
    color : #FFF;
    border : solid 3px #333;
    margin: 1px;
}
</style>
<div>
  <a href="javascript:;">连接一</a>
  <a href="javascript:;">连接二</a>
  <a href="javascript:;">连接三</a>
  <a href="javascript:;">连接四</a>
  <a href="javascript:;">连接五</a>
  <a href="javascript:;">连接六</a>
  <a href="javascript:;">连接七</a>
  <a href="javascript:;">连接八</a>
  <a href="javascript:;">连接九</a>
</div>
<script>
Element.prototype.siblings = function(callback){
    var siblingElement = [];
    var parentAllElement = [];
    if( ! this.parentNode ){
        return siblingElement;
    };
    parentAllElement = this.parentNode.getElementsByTagName(this.tagName);
    for( var i = 0; i < parentAllElement.length ; i++ ){
        if( parentAllElement[i] != this ){
            siblingElement.push(parentAllElement[i]);
            typeof callback == "function" && callback.call(parentAllElement[i]);
        }
    }
    delete parentAllElement;
    return siblingElement;
};

var link = document.getElementsByTagName("a");
for (var i = 0; i < link.length; i++) {
    link[i].addEventListener("click", function() {
        this.style.backgroundColor = "#C00";
        this.style.borderColor = "#FF0";
        
        //用法1:callback方式;改变背景为蓝色
        this.siblings(function(){
            this.style.backgroundColor = "#009";
        });
        
        //用法2:返回列表;改变边框为绿色
        this.siblings().forEach(function(sibling){
            sibling.style.borderColor = "#090";
        });
    })
}
</script>

这种情况更多的是吧listener加在父级上,从event的target来判断来源吧。我是Demo

应该不是加在本级上,应该是从父元素遍历出来的,因为siblings()方法是可以带参数做筛选的。

再加一层循环呗

var link = document.getElementsByTagName("a");
for (var i = 0; i < link.length; i++) {
    link[i].addEventListener("click", function() {
        for (var j = 0; j < link.length; j++){
            link[j].style.backgroundColor = "#fff";
        }
        this.style.backgroundColor = "#000";
    })
}

@toBeTheLight @mqycn 感谢感谢,确实都能实现同样的效果

@toBeTheLight 的更简洁,只是觉得,a标签如果多了,会不会有性能的影响,或许没有,我也只是这么猜,测试的话也不知道如何能测试性能开销。
@mqycn 的逼格更高,感觉更符合我需要的答案吧,
但具体哪位的更好,我也分辨不出来,总之很是感谢,都能解决实际的问题,至于 性能 暂时就只能不多做考虑了,毕竟我的水平在这。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题