写了个选项卡组件,支持页面中多个选项卡一起用。写完了也实现了,就是有点疑问。

时间:2022-03-20 18:42:26
中午的时候一哥们说他在做一个页面,N多选项卡。
我说那写一个通用的呗,然后在哪用直接写个className或者attribute往上一套就行了。
然后趁午休时间我写了一个,但是写完了。有个在此之外的疑问困扰了我。
我先贴完整代码,沙发说疑问。
用的JQ和JS混写的,JQ不太熟,但是又比较喜欢他的选择器。
大家运行的时候别忘了放个jquery.js到同级目录。

HTML

<!doctype html>
<html>
<head>
<link rel="stylesheet" href="tab.css">
<script src="jquery.js"></script>
<script src="tab.js"></script>
</head>
<body>
<div class="tabWrap">
<h2>我是一个tab</h2>
<div class="tab">
<div class="tabHead">
<ul>
<li>第一个</li>
<li>第二个</li>
<li>第三个</li>
<div class="clear"></div>
</ul>
</div>
<div class="tabBody">
<div class="tabItem">
我是第一个选项卡
</div>
<div class="tabItem">
我是第二个选项卡
</div>
<div class="tabItem">
我是第三个选项卡
</div>
</div>
</div>
</div>
<div class="tabWrap">
<h2>我也是一个tab啊啊</h2>
<div class="tab">
<div class="tabHead">
<ul>
<li>第一个</li>
<li>第二个</li>
<li>第三个</li>
<div class="clear"></div>
</ul>
</div>
<div class="tabBody">
<div class="tabItem">
我是第一个选项卡
</div>
<div class="tabItem">
我是第二个选项卡
</div>
<div class="tabItem">
我是第三个选项卡
</div>
</div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function(){
   tab.init();
  });
</script>
</body>
</html>

CSS

*{
margin:0;
padding:0;
}
h2{
padding:10px;
}
.clear{
clear:both;
}
.tabWrap{
border:dotted 1px #999;
width:300px;
height:300px;
}
.tabHead ul{
list-style:none;
padding:10px;
}
.tabHead li{
float:left;
border:solid 1px #333;
padding:10px;
}
.tabSelected{
font-weight:bold;
}
.tabNormal{
font-weight:normal;
}
.tabBody{
padding:10px;
}
.tabItem{
padding:10px;
background:#eee;
display:none;
}

JS

var tab={};
tab.init=function(){
//初始化变量
this.tabList = $(".tab");//全页面的tab对象列表
this.tabBodyList = $(".tabBody");//全页面的tabBody部分列表
this.tabHeadList = $(".tabHead");//全页面的tabHead部分列表

var i=0,j=0;

//初始化TAB状态,默认全部选中第一个。
for (i = 0;i < this.tabList.length;i++){
this.tabList[i].setAttribute("current",0);
this.tabBodyList[i].getElementsByTagName("div")[0].style.display = "block";
this.tabHeadList[i].getElementsByTagName("li")[0].className = "tabSelected";
}

//绑定触发事件
for (i = 0;i < this.tabHeadList.length;i++){
var singleHeadLiList = this.tabHeadList[i].getElementsByTagName("li");
for (j = 0;j < singleHeadLiList.length;j++){
//一个tab接一个tab的赋予事件。不直接用取余的方式,是因为可能tab的栏数不一样。
singleHeadLiList[j].onmouseover = function(j){
//防止闭包导致绑定失败
return function(){
//切换tab事件。用单独函数处理的话要保存触发对象的引用,要不tab.swap取不到。
tab.swap(j,this);
};
}(j);
}
}
};
tab.swap=function(index,o){
//获取存储在tab块的自定义属性current,current标识着当前显示的是第几个选项卡。
var current = o.parentNode.parentNode.parentNode.getAttribute("current");

//取消当前选项卡的样式,准备更换
o.parentNode.getElementsByTagName("li")[current].className = "tabNormal";
o.parentNode.parentNode.parentNode.getElementsByTagName("div")[2].getElementsByTagName("div")[current].style.display = "none";

//更换tab块的自定义属性
o.parentNode.parentNode.parentNode.setAttribute("current",index);

//更换新选定的选项卡的样式
o.className = "tabSelected";
o.parentNode.parentNode.parentNode.getElementsByTagName("div")[2].getElementsByTagName("div")[index].style.display = "block";
};

10 个解决方案

#1


我的疑问就是
像JS代码中的这些

 o.parentNode.parentNode.parentNode.getElementsByTagName("div")[2].getElementsByTagName("div")[index].style.display = "block";

var current = o.parentNode.parentNode.parentNode.getAttribute("current");


有没有什么组件或者写法,能让他优雅一点,不这么写着恶心,读着难受?

#2


一个选项卡 对应一个 tab 对象!

在 tab 中 缓存  tabHead tabBody 

#3


引用 2 楼 hch126163 的回复:
一个选项卡 对应一个 tab 对象!

在 tab 中 缓存  tabHead tabBody

不太理解啊胡大哥-。-
能讲细点吗
这样能解决通过被点击的选项头使用多个parentNode+getElementsByTagName才能找到tabBody里面对应的选项体的问题吗。

其实这个问题到底上应该是“怎么通过一个对象去找到另一个对象”
就算是定义一个tab对象,里面有一个tabHead一个tabBody,我点击的是tabHead里的tabHeadLi,还要通过遍历对象列表,找到他属于的tab,然后再找tabBody对吗。

#4


js也有类和继承的关系,就要看你怎么去设计了。

#5


如果tabHeadLi与tabBodyDiv是一一对应的话。
整个页面有一个tabList数组,里面是一个个tab对象,然后tab对象有tabHead数组和tabBody数组。
通过tabHead的下标index1找到对应的tabBody[index1]
通过tabHeadLi的下标index2再找到对应的tabBodyDiv[index2]

是这样吗?

#6


引用 4 楼 wangyu19820830 的回复:
js也有类和继承的关系,就要看你怎么去设计了。

兄弟所言极是,虽然写后端代码也不少。
但是一到写JS,就感觉拧巴了。
有劲儿使不上的感觉。

像这个例子,如果修改为tabList是一个对象数组。
tab有两个属性分别为tabHead和tabBody,都是对象数组。
然后tabHead有tabHeadLi对象数组,tabBody有tabBody对象数组。

难怪写的时候感觉很拗得慌。 写了个选项卡组件,支持页面中多个选项卡一起用。写完了也实现了,就是有点疑问。

#7


用jquery的页签控件不就好了。。。

#8


谢谢分享。。

#9


引用 1 楼 konghulu 的回复:
我的疑问就是
像JS代码中的这些

JScript code

 o.parentNode.parentNode.parentNode.getElementsByTagName("div")[2].getElementsByTagName("div")[index].style.display = "block";

var current = o.parentNode.parent……

既然用到jq,那就把dom对象包装成jq对象,然后用jq的函数操作
var $o = $(o);
....

#10


帮你改了下,用了更多的jquery选择器。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <title> New Document </title>
   <script src="jquery-1.4.4.min.js" type="text/javascript"></script>
   <style>
   *{
    margin:0;
    padding:0;
}
h2{
    padding:10px;
}
.clear{
    clear:both;
}
.tabWrap{
    border:dotted 1px #999;
    width:300px;
    height:300px;
}
.tabHead{
 width:300px; height:40px; 
}
.tabHead ul{
    list-style:none;
    padding:10px;
}
.tabHead li{
    float:left;
    border:solid 1px #333;
    padding:10px;
cursor:pointer;
}
.tabSelected{
    font-weight:bold;
}
.tabNormal{
    font-weight:normal;
}
.tabBody{
    padding:10px;
}
.tabItem{
    padding:10px;
    background:#eee;
    display:none;
}
   </style>


<script type="text/javascript">
    $(function(){
       $(".tab .tabHead ul li").mouseover(function() {
             
 var titleList=$(this).parent().children("li");
             var checkedTitleIndex;  //选中项的索引
 for(var titleIndex=0;titleIndex<titleList.length;titleIndex++)
 { 
      if ($(titleList[titleIndex]).text()==$(this).text())
      {
     $(titleList[titleIndex]).css("font-weight","bold");
 checkedTitleIndex=titleIndex;  //获取选中项的索引
      }
  else
  {
    $(titleList[titleIndex]).css("font-weight","normal");
  }
 }
             
 var tabItemList= $(this).parent().parent(".tabHead").siblings(".tabBody").children(".tabItem");
             for(var itemIndex=0;itemIndex<tabItemList.length;itemIndex++ )
 {  
     if (itemIndex==checkedTitleIndex)
     {
   $(tabItemList[itemIndex]).css("display","block");
     }
 else
 {
$(tabItemList[itemIndex]).css("display","none");
 }
 }

         });
  });
</script>

 </head>

 <body>
  <div class="tabWrap">
    <h2>我是一个tab</h2>
    <div class="tab">
        <div class="tabHead">
            <ul>
                <li>第一个</li>
                <li>第二个</li>
                <li>第三个</li>
            </ul>
        </div>
        <div class="tabBody">
            <div class="tabItem">
                我是第一个选项卡
            </div>
            <div class="tabItem">
                我是第二个选项卡
            </div>
            <div class="tabItem">
                我是第三个选项卡
            </div>
        </div>
    </div>
</div>
<div class="tabWrap">
    <h2>我也是一个tab啊啊</h2>
    <div class="tab">
        <div class="tabHead">
            <ul>
                <li>第1个</li>
                <li>第2个</li>
                <li>第3个</li>
            </ul>
        </div>
        <div class="tabBody">
            <div class="tabItem">
                我是第一个选项卡
            </div>
            <div class="tabItem">
                我是第二个选项卡
            </div>
            <div class="tabItem">
                我是第三个选项卡
            </div>
        </div>
    </div>
</div>

 </body>
</html>

#1


我的疑问就是
像JS代码中的这些

 o.parentNode.parentNode.parentNode.getElementsByTagName("div")[2].getElementsByTagName("div")[index].style.display = "block";

var current = o.parentNode.parentNode.parentNode.getAttribute("current");


有没有什么组件或者写法,能让他优雅一点,不这么写着恶心,读着难受?

#2


一个选项卡 对应一个 tab 对象!

在 tab 中 缓存  tabHead tabBody 

#3


引用 2 楼 hch126163 的回复:
一个选项卡 对应一个 tab 对象!

在 tab 中 缓存  tabHead tabBody

不太理解啊胡大哥-。-
能讲细点吗
这样能解决通过被点击的选项头使用多个parentNode+getElementsByTagName才能找到tabBody里面对应的选项体的问题吗。

其实这个问题到底上应该是“怎么通过一个对象去找到另一个对象”
就算是定义一个tab对象,里面有一个tabHead一个tabBody,我点击的是tabHead里的tabHeadLi,还要通过遍历对象列表,找到他属于的tab,然后再找tabBody对吗。

#4


js也有类和继承的关系,就要看你怎么去设计了。

#5


如果tabHeadLi与tabBodyDiv是一一对应的话。
整个页面有一个tabList数组,里面是一个个tab对象,然后tab对象有tabHead数组和tabBody数组。
通过tabHead的下标index1找到对应的tabBody[index1]
通过tabHeadLi的下标index2再找到对应的tabBodyDiv[index2]

是这样吗?

#6


引用 4 楼 wangyu19820830 的回复:
js也有类和继承的关系,就要看你怎么去设计了。

兄弟所言极是,虽然写后端代码也不少。
但是一到写JS,就感觉拧巴了。
有劲儿使不上的感觉。

像这个例子,如果修改为tabList是一个对象数组。
tab有两个属性分别为tabHead和tabBody,都是对象数组。
然后tabHead有tabHeadLi对象数组,tabBody有tabBody对象数组。

难怪写的时候感觉很拗得慌。 写了个选项卡组件,支持页面中多个选项卡一起用。写完了也实现了,就是有点疑问。

#7


用jquery的页签控件不就好了。。。

#8


谢谢分享。。

#9


引用 1 楼 konghulu 的回复:
我的疑问就是
像JS代码中的这些

JScript code

 o.parentNode.parentNode.parentNode.getElementsByTagName("div")[2].getElementsByTagName("div")[index].style.display = "block";

var current = o.parentNode.parent……

既然用到jq,那就把dom对象包装成jq对象,然后用jq的函数操作
var $o = $(o);
....

#10


帮你改了下,用了更多的jquery选择器。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <title> New Document </title>
   <script src="jquery-1.4.4.min.js" type="text/javascript"></script>
   <style>
   *{
    margin:0;
    padding:0;
}
h2{
    padding:10px;
}
.clear{
    clear:both;
}
.tabWrap{
    border:dotted 1px #999;
    width:300px;
    height:300px;
}
.tabHead{
 width:300px; height:40px; 
}
.tabHead ul{
    list-style:none;
    padding:10px;
}
.tabHead li{
    float:left;
    border:solid 1px #333;
    padding:10px;
cursor:pointer;
}
.tabSelected{
    font-weight:bold;
}
.tabNormal{
    font-weight:normal;
}
.tabBody{
    padding:10px;
}
.tabItem{
    padding:10px;
    background:#eee;
    display:none;
}
   </style>


<script type="text/javascript">
    $(function(){
       $(".tab .tabHead ul li").mouseover(function() {
             
 var titleList=$(this).parent().children("li");
             var checkedTitleIndex;  //选中项的索引
 for(var titleIndex=0;titleIndex<titleList.length;titleIndex++)
 { 
      if ($(titleList[titleIndex]).text()==$(this).text())
      {
     $(titleList[titleIndex]).css("font-weight","bold");
 checkedTitleIndex=titleIndex;  //获取选中项的索引
      }
  else
  {
    $(titleList[titleIndex]).css("font-weight","normal");
  }
 }
             
 var tabItemList= $(this).parent().parent(".tabHead").siblings(".tabBody").children(".tabItem");
             for(var itemIndex=0;itemIndex<tabItemList.length;itemIndex++ )
 {  
     if (itemIndex==checkedTitleIndex)
     {
   $(tabItemList[itemIndex]).css("display","block");
     }
 else
 {
$(tabItemList[itemIndex]).css("display","none");
 }
 }

         });
  });
</script>

 </head>

 <body>
  <div class="tabWrap">
    <h2>我是一个tab</h2>
    <div class="tab">
        <div class="tabHead">
            <ul>
                <li>第一个</li>
                <li>第二个</li>
                <li>第三个</li>
            </ul>
        </div>
        <div class="tabBody">
            <div class="tabItem">
                我是第一个选项卡
            </div>
            <div class="tabItem">
                我是第二个选项卡
            </div>
            <div class="tabItem">
                我是第三个选项卡
            </div>
        </div>
    </div>
</div>
<div class="tabWrap">
    <h2>我也是一个tab啊啊</h2>
    <div class="tab">
        <div class="tabHead">
            <ul>
                <li>第1个</li>
                <li>第2个</li>
                <li>第3个</li>
            </ul>
        </div>
        <div class="tabBody">
            <div class="tabItem">
                我是第一个选项卡
            </div>
            <div class="tabItem">
                我是第二个选项卡
            </div>
            <div class="tabItem">
                我是第三个选项卡
            </div>
        </div>
    </div>
</div>

 </body>
</html>