接着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>