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