接着javascript实现tab标签组件1,来继续完善tab标签组件,在之前的几个示例中都是通过点击事件来触发标签切换,下面实现定制激活事件的功能。

<div class="tab J_tab">
<ul class="tab-menuWrapper">
<li class="J_tab-menu tab-currentMenu1">menu1</li>
<li class="J_tab-menu">menu2</li>
<li class="J_tab-menu">menu3</li>
</ul>
<div class="tab-contnetWrapper">
<div class="J_tab-content">
<div>content1</div>
<ul>
<li>1</li>
<li>2</li>
</ul>
</div>
<div  class="J_tab-content" style="display:none;">
<p>content2</p>
<div>abc</div>
</div>
<div  class="J_tab-content" style="display:none;">
            content3
</div>
</div>
</div>
<div class="tab J_tab">
<ul class="tab-menuWrapper">
<li class="J_tab-menu tab-currentMenu2">menu1</li>
<li class="J_tab-menu">menu2</li>
<li class="J_tab-menu">menu3</li>
</ul>
<div class="tab-contnetWrapper">
<div class="J_tab-content">
<div>content1</div>
<ul>
<li>1</li>
<li>2</li>
</ul>
</div>
<div  class="J_tab-content" style="display:none;">
<p>content2</p>
<div>abc</div>
</div>
<div  class="J_tab-content" style="display:none;">
            content3
</div>
</div>
</div>
<div class="tab J_tab">
<ul class="tab-menuWrapper">
<li class="J_tab-menu tab-currentMenu3">menu1</li>
<li class="J_tab-menu">menu2</li>
<li class="J_tab-menu">menu3</li>
</ul>
<div class="tab-contnetWrapper">
<div class="J_tab-content">
<div>content1</div>
<ul>
<li>1</li>
<li>2</li>
</ul>
</div>
<div  class="J_tab-content" style="display:none;">
<p>content2</p>
<div>abc</div>
</div>
<div  class="J_tab-content" style="display:none;">
            content3
</div>
</div>
</div>

Javascript:

<script type="text/javascript">
var GLOBAL = {};
GLOBAL.namespace = function(str){
var arr = str.split('.'),o = GLOBAL;
for(i = (arr[0] == GLOBAL)?1:0;i<arr.length;i++){
        o[arr[i]] = o[arr[i]]||{};
        o = o[arr[i]];
    }
}
GLOBAL.namespace("Dom");
GLOBAL.Dom.getElementsByClassName = function(str,root,tag){
if(root){
        root = (typeof root == "string")?document.getElementById(root):root;
    }else{
        root = document.body;
    }
    tag = tag||'*';
var els = root.getElementsByTagName(tag),arr = [];
for(var i=0,leng = els.length;i<leng;i++){
var k = els[i].className.split(' ');
for(j = 0,len = k.length;j<len;j++){
if(k[j] == str){
                arr.push(els[i]);
break;
            }
        }
    }
return arr;
}
GLOBAL.Dom.addClass = function(node,str){
var reg = new RegExp("(^|\\s+)"+str);
if(!reg.test(node.className)){
        node.className = node.className+" "+str;
    }
}
GLOBAL.Dom.removeClass = function(node,str){
var reg = new RegExp("(^|\\s+)"+str);
if(reg.test(node.className)){
        node.className = node.className.replace(reg,"");
    }
}
GLOBAL.namespace("Event");
GLOBAL.Event.on = function(node,eventType,handler,scope){
//scope用来设置handler中this的指针,默认指向node节点
    Node = (typeof node == "string")?document.getElementById(node):node;
    scope = scope || Node;
if(node.addEventListener){
        node.addEventListener(eventType,function(){handler.apply(scope,arguments)},false);
    }else if(node.attachEvent){
        node.attachEvent("on"+eventType,function(){handler.apply(scope,arguments)});
    }else{
        node['on'+eventType] = function(){handler.apply(scope,arguments)};
    }
}
function setTab(root,currentClass,trigger){
//取得标签及内容的节点,并以数组的形式保存在变量中
    var tabMenus = GLOBAL.Dom.getElementsByClassName('J_tab-menu',root),
        tabContents = GLOBAL.Dom.getElementsByClassName('J_tab-content',root);
//如果不传入激活类型,默认激活类型为点击
    trigger = trigger||"click";
//遍历数组,让标签监听click事件
    for(var i=0,leng = tabMenus.length;i<leng;i++){
        tabMenus[i]._index = i;
        GLOBAL.Event.on(tabMenus[i],trigger,function(){
for(var j=0,len = tabContents.length;j<len;j++){
                tabContents[j].style.display="none";
            }
            tabContents[this._index].style.display = "block";
var currentMenu = GLOBAL.Dom.getElementsByClassName(currentClass,root)[0];
if(currentMenu){
                GLOBAL.Dom.removeClass(currentMenu,currentClass);
            }
            GLOBAL.Dom.addClass(this,currentClass);
        },tabMenus[i]);
    }
}
var tabs = GLOBAL.Dom.getElementsByClassName('J_tab');
setTab(tabs[0],"tab-currentMenu1",null);
setTab(tabs[1],"tab-currentMenu2","mouseover");
setTab(tabs[2],"tab-currentMenu3",null);
</script>

在上面的代码中需要注意的是关于this问题的处理。

如何控制this关键字的指向的讨论

在javascript中this是个让人捉摸不定的东西

1.javascript中伪协议和内联事件的this指向不同

<!-- 弹出A -->
<a href="#" onclick="alert(this.tagName)">Click me</a>
<!-- 弹出Undefined -->
<a href="JavaScript:alert(this.tagName)">Click me</a>
<!-- 弹出True -->
<a href="JavaScript:alert(this==window)">Click me</a>

通过case发现内联事件的this指向当前点击的对象,而伪协议里的this则是指向window.

2.setTimeout和setInterval也会改变this的指向。

<script type="text/javascript">
var name="somebody";
var adang={
        name:"adang",
        say:function(){
            alert("I'm "+this.name);
        }
    }
    adang.say();//I'm adang

    setTimeout(adang.say,1000);//I'm somebody
    setInterval(adang.say,1000);//I'm somebody
</script>

3.node.onXXX也会改变this的指向

<input type="button" value="ClickMe" id="btn" name="btn"/>
<script type="text/javascript">
var btn = document.getElementById('btn');
var name="somebody";
var adang={
        name:"adang",
        say:function(){
            alert("I'm "+this.name);
        }
    }
    adang.say();//I'm adang
    btn.onclick=adang.say;//I'm btn
</script>

解决this指向的问题有两个方法:

1.匿名函数的方法:

<input type="button" value="ClickMe" id="btn" name="btn"/>
<script type="text/javascript">
var btn = document.getElementById('btn');
var name="somebody";
var adang={
        name:"adang",
        say:function(){
            alert("I'm "+this.name);
        }
    }
    adang.say();//I'm adang
    setTimeOut(function(){adang.say()},1000);//I'm adang
    setInterval(function(){adang.say()},1000);//I'm adang
    btn.onclick=function(){adang.say()};//I'm adang
    setTimeOut(function(){alert(this==window)},1000)//true
    btn.onclick = function(){alert(this==btn)}//true
</script>

2.使用call或apply的方法

<input type="button" value="ClickMe" id="btn" name="btn"/>
<script type="text/javascript">
var btn = document.getElementById('btn');
var name="somebody";
var adang={
        name:"adang",
        say:function(){
            alert("I'm "+this.name);
        }
    }
    adang.say.call(btn);//I'm btn
    btn.onclick=function(){adang.say.call(adang)};//I'm adang
</script>

3.在this改变指向之前,将它指向的对象保存到一个变量中也是非常常用的方法

<input type="button" value="ClickMe" id="btn" name="btn"/>
<script type="text/javascript">
var btn = document.getElementById('btn');
var name="somebody";
var adang={
        name:"adang",
        say:function(){
            alert("I'm "+this.name);
        },
        init:function(){
var This = this;
            btn.onclick=function(){
                This.say();//I'm adang
                this.say();//报错
            }
        }
    }
    adang.init();
</script>