本文实例讲述了JS面向对象编程实现的Tab选项卡。分享给大家供大家参考,具体如下:
Tab选项卡案例
下面是一个简单面向过程的Tab选项卡。
<!DOCTYPE html>
<html>
<head>
<style>
#tabBox input {
background: #F6F3F3;
border: 1px solid #FF0000;
}
#tabBox .active {
background: #E9D4D4;
}
#tabBox div {
width:300px;
height:250px;
display:none;
padding: 10px;
background: #E9D4D4;
border: 1px solid #FF0000;
}
</style>
<meta charset="utf-8" />
<title>选项卡</title>
<script>
window.onload=function(){
var tabBox = document.getElementById('tabBox');
var tabBtn = tabBox.getElementsByTagName('input');
var tabDiv = tabBox.getElementsByTagName('div');
for(var i=0;i<tabBtn.length;i++){
tabBtn[i].index = i;
tabBtn[i].onclick = function (){
for(var j=0;j<tabBtn.length;j++){
tabBtn[j].className='';
tabDiv[j].style.display='none';
}
this.className='active';
tabDiv[this.index].style.display='block';
};
}
};
</script>
</head>
<body>
<div id="tabBox">
<input type="button" value="主页" class="active" />
<input type="button" value="说说" />
<input type="button" value="日志" />
<div style="display:block;">这是主页内容</div>
<div>这是说说内容</div>
<div>这是日志内容</div>
</div>
</body>
</html>
下面来慢慢改成面向对象的形式。
1.首先将嵌套的函数拿到window.onload外面,不能有函数嵌套,可以有全局变量。如下:所有的改写最终效果都不变。
<script>
//将在嵌套函数里的变量提取到全局中
var tabBtn = null;
var tabDiv = null;
window.onload = function(){
var tabBox = document.getElementById('tabBox');
tabBtn = tabBox.getElementsByTagName('input');
tabDiv = tabBox.getElementsByTagName('div');
for(var i=0;i<tabBtn.length;i++){
tabBtn[i].index = i;
//此处调用函数即可
tabBtn[i].onclick = clickBtn;
}
};
//将嵌套函数提取到全局中
function clickBtn(){
for(var j=0;j<tabBtn.length;j++){
tabBtn[j].className='';
tabDiv[j].style.display='none';
}
this.className='active';
tabDiv[this.index].style.display='block';
};
</script>
2.将全局的变量变为对象的属性,全局的函数变为对象的方法;将window.onload里的代码提取到一个构造函数里面,在window.onload里创建对象即可;(下面的代码执行起来是有问题的)。
这里必须注意:在构造函数Tab里的this跟之前this所代表的是不同的(此处是通过new来创建对象的);在上面的示例中,this指的是调用者;在构造函数里,this指向的是var tab = new Tab() ,即tab这个对象,注意是对象。
说一下这段代码的问题:我们在Tab的原型上添加clickBtn方法后,clickBtn方法里的this本应该是指向var tab = new Tab()的,但是我们在 this.tabBtn[i].onclick = this.clickBtn; 将clickBtn添加给了this.tabBtn[i],即input按钮,clickBtn的所属由Tab对象变成了input按钮。
clickBtn的所属变成input按钮后,那么clickBtn里的this指向按钮,那再来看clickBtn里的代码,this.tabBtn、this.tabDiv,input按钮里有这两个属性吗?没有,所以会出错!
<script>
window.onload = function(){
var tab = new Tab("tabBox");
}
/**
* 将之前window.onload里的代码提到一个构造函数里
* [可以将这个Tab构造函数想象成一个Tab类]
* @param {Object} id:选项卡id以参数的形式传入
*/
function Tab(id){
var tabBox = document.getElementById(id);
//将之前的全局变量变为对象的属性
this.tabBtn = tabBox.getElementsByTagName('input');
this.tabDiv = tabBox.getElementsByTagName('div');
for(var i=0;i<this.tabBtn.length;i++){
this.tabBtn[i].index = i;
//此处这种方式调用函数,已经将clickBtn的所属变成this.tabBtn[i]
this.tabBtn[i].onclick = this.clickBtn;
}
};
//将之前的全局函数添加到构造函数的原型里,作为对象的一个方法
Tab.prototype.clickBtn = function(){
alert(this); //HTMLInputElement
for(var j=0;j<this.tabBtn.length;j++){
this.tabBtn[j].className='';
this.tabDiv[j].style.display='none';
}
this.className='active';
this.tabDiv[this.index].style.display='block';
};
</script>
3.将clickBtn的调用放在一个函数里,这样就不会改变clickBtn的所属了。alert(this);此时弹出的是一个Object,说明clickBtn的所属关系没变,还是Tab对象。但是还有另一个问题,此时clickBtn里的this指向tab对象,那么this.className、this.index,此处的this指的是tab对象,那么对象中有这两个属性吗?没有,还会出错!所以第4步继续改造。
window.onload = function(){
var tab = new Tab("tabBox");
}
/**
* 选项卡
* @param {Object} id:选项卡id
*/
function Tab(id){
var tabBox = document.getElementById(id);
this.tabBtn = tabBox.getElementsByTagName('input');
this.tabDiv = tabBox.getElementsByTagName('div');
for(var i=0;i<this.tabBtn.length;i++){
this.tabBtn[i].index = i;
//将this保存成一个变量,就可以在下面代码中调用对象的方法了
var _this = this;
//此处这种方式调用函数,就不会改变clickBtn方法的所属关系
this.tabBtn[i].onclick = function(){
//注意此处不能直接使用this,this指向this.tabBtn[i]
_this.clickBtn();
};
}
};
//点击选项卡按钮
Tab.prototype.clickBtn = function(){
alert(this); //Object
for(var j=0;j<this.tabBtn.length;j++){
this.tabBtn[j].className='';
this.tabDiv[j].style.display='none';
}
this.className='active';
this.tabDiv[this.index].style.display='block';
};
4. 以参数的形式将点击的按钮传入clickBtn中
window.onload = function(){
var tab = new Tab("tabBox");
}
/**
* 选项卡
* @param {Object} id:选项卡id
*/
function Tab(id){
var tabBox = document.getElementById(id);
this.tabBtn = tabBox.getElementsByTagName('input');
this.tabDiv = tabBox.getElementsByTagName('div');
for(var i=0;i<this.tabBtn.length;i++){
this.tabBtn[i].index = i;
var _this = this;
this.tabBtn[i].onclick = function(){
//注意参数this代表的是this.tabBtn[i],即input按钮
_this.clickBtn(this);
};
}
};
//将点击的按钮以参数的形式传入
Tab.prototype.clickBtn = function(btn){
for(var j=0;j<this.tabBtn.length;j++){
this.tabBtn[j].className='';
this.tabDiv[j].style.display='none';
}
btn.className='active';
this.tabDiv[btn.index].style.display='block';
};
5.最终版 —— 将代码提取到一个单独的js文件中,在用的时候引入即可。一般花大时间去写一个面向对象的程序,就是为了能够复用,以及方便的使用。
Tab.js
/**
* 选项卡
* @param {Object} id 选项卡id
*/
function Tab(id){
var tabBox = document.getElementById(id);
this.tabBtn = tabBox.getElementsByTagName('input');
this.tabDiv = tabBox.getElementsByTagName('div');
for(var i=0;i<this.tabBtn.length;i++){
this.tabBtn[i].index = i;
var _this = this;
this.tabBtn[i].onclick = function(){
_this.clickBtn(this);
};
}
};
/**
* 为Tab原型添加点击选项卡方法
* @param {Object} btn 点击的按钮
*/
Tab.prototype.clickBtn = function(btn){
for(var j=0;j<this.tabBtn.length;j++){
this.tabBtn[j].className='';
this.tabDiv[j].style.display='none';
}
btn.className='active';
this.tabDiv[btn.index].style.display='block';
};
使用:tab.html 可以看到使用的时候,就可以很简单的创建两个选项卡出来了。
<!DOCTYPE html>
<html>
<head>
<style>
.tab input {
background: #F6F3F3;
border: 1px solid #FF0000;
}
.tab .active {
background: #E9D4D4;
}
.tab div {
width:300px;
height:250px;
display:none;
padding: 10px;
background: #E9D4D4;
border: 1px solid #FF0000;
}
</style>
<meta charset="utf-8" />
<title>选项卡</title>
<!-- 引入tab.js -->
<script type="text/javascript" src="/UploadFiles/2021-04-02/tab.js">
再来简单总结一下JS面向对象中的this,this一般会在两种情况下出问题,一是使用定时器、二是事件,从上面的例子中也可以看出来。注意下面的说法是在构造函数里哦,其它情况下,this指向的是调用者。
可以看到效果没有将姓名显示出来,其实看到这里原因应该很清楚了,就是第14行代码中this.name,此处的this指向谁?指向window,因为setInterval是属于window的。
<!DOCTYPE html>
<html>
<meta charset="UTF-8" />
<head>
<script>
function Person(name){
this.name = name;
//定时器
setInterval(this.showName, 3000);
}
Person.prototype.showName = function(){
alert(this); //window
alert("姓名:"+this.name);
}
var p1 = new Person("jiangzhou");
</script>
</head>
</html>
解决办法:上面例子中已经列出来了,就是用一个function将要执行的代码包起来,使其所属关系不会发生变化,注意function里调用方法时使用的是外部变量'_this'。事件的处理在上面的例子中已经说明了。
function Person(name){
this.name = name;
var _this = this;
setInterval(function(){
this.showName();
}, 3000);
}
Person.prototype.showName = function(){
alert(this); //[Object Object]
alert("姓名:"+this.name); //姓名:jianghzou
}
var p1 = new Person("jiangzhou");
感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码运行效果。
更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》
希望本文所述对大家JavaScript程序设计有所帮助。
JS,面向对象,Tab选项卡
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新动态
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]




