JS面向对象编程实现的Tab选项卡案例详解


Posted in Javascript onMarch 03, 2020

本文实例讲述了JS面向对象编程实现的Tab选项卡。分享给大家供大家参考,具体如下:

Tab选项卡案例

JS面向对象编程实现的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按钮里有这两个属性吗?没有,所以会出错!

JS面向对象编程实现的Tab选项卡案例详解JS面向对象编程实现的Tab选项卡案例详解   

<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步继续改造。

JS面向对象编程实现的Tab选项卡案例详解

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="../js/tab.js" ></script>
  <script>  
    window.onload = function(){
      var tab1 = new Tab("tabBox1");     
      var tab2 = new Tab("tabBox2");
    }  
  </script>
</head>
 
<body>
  <div class="tab" id="tabBox1">
    <input type="button" value="主页" class="active" />
    <input type="button" value="说说" />
    <input type="button" value="日志" />
    <div style="display:block;">这是主页内容</div>
    <div>这是说说内容</div>
    <div>这是日志内容</div>
  </div>
  <br />
  <div class="tab" id="tabBox2">
    <input type="button" value="技术" class="active" />
    <input type="button" value="工具" />
    <input type="button" value="网站" />
    <div style="display:block;">Js、Vue</div>
    <div>VSCode</div>
    <div>CSDN</div>
  </div>
</body>
</html>

JS面向对象编程实现的Tab选项卡案例详解

再来简单总结一下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.3water.com/code/HtmlJsRun测试上述代码运行效果。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
JAVASCRIPT HashTable
Jan 22 Javascript
Webkit的跨域安全问题说明
Sep 13 Javascript
js中页面的重新加载(当前页面/上级页面)及frame或iframe元素引用介绍
Jan 24 Javascript
jquery实现商品拖动选择效果代码(自写)
May 28 Javascript
图解Sublime Text3使用技巧
Dec 21 Javascript
概述jQuery中的ajax方法
Dec 16 Javascript
在vscode中统一vue编码风格的方法
Feb 22 Javascript
jquery 实现拖动文件上传加载进度条功能
Mar 18 jQuery
Bootstrap Table列宽拖动的方法
Aug 15 Javascript
bootstrap table列和表头对不齐的解决方法
Jul 19 Javascript
微信小程序实现一个简单swiper代码实例
Dec 30 Javascript
vue中el-input绑定键盘按键(按键修饰符)
Jul 22 Javascript
JS面向对象编程基础篇(三) 继承操作实例详解
Mar 03 #Javascript
小程序接入腾讯位置服务的详细流程
Mar 03 #Javascript
vue.js this.$router.push获取不到params参数问题
Mar 03 #Javascript
JS面向对象编程基础篇(二) 封装操作实例详解
Mar 03 #Javascript
Vue axios与Go Frame后端框架的Options请求跨域问题详解
Mar 03 #Javascript
JS面向对象编程基础篇(一) 对象和构造函数实例详解
Mar 03 #Javascript
vue中改变滚动条样式的方法
Mar 03 #Javascript
You might like
php 文本文件的读取效率
2012/02/10 PHP
完美解决PHP中的Cannot modify header information 问题
2013/08/12 PHP
下载站控制介绍字数显示的脚本 显示全部 隐藏介绍等功能
2009/09/19 Javascript
js 页面刷新location.reload和location.replace的区别小结
2009/12/24 Javascript
JQuery 将元素显示在屏幕的中央的代码
2010/02/27 Javascript
推荐11款jQuery开发的复选框和单选框美化插件
2011/08/02 Javascript
js实现单行文本向上滚动效果实例代码
2013/11/28 Javascript
web 屏蔽BackSpace键实例代码
2016/12/24 Javascript
Vue 组件传值几种常用方法【总结】
2018/05/28 Javascript
vue加载完成后的回调函数方法
2018/09/07 Javascript
vue element table 表格请求后台排序的方法
2018/09/28 Javascript
详解vue文件中使用echarts.js的两种方式
2018/10/18 Javascript
vue中 v-for循环的用法详解
2020/02/19 Javascript
Vue 构造选项 - 进阶使用说明
2020/08/14 Javascript
openLayer4实现动态改变标注图标
2020/08/17 Javascript
在Python的框架中为MySQL实现restful接口的教程
2015/04/08 Python
Python中使用urllib2模块编写爬虫的简单上手示例
2016/01/20 Python
Python寻找路径和查找文件路径的示例
2019/07/10 Python
Python解析命令行读取参数之argparse模块
2019/07/26 Python
超实用的 30 段 Python 案例
2019/10/10 Python
解决python父线程关闭后子线程不关闭问题
2020/04/25 Python
python3.6环境下安装freetype库和基本使用方法(推荐)
2020/05/10 Python
python Matplotlib数据可视化(2):详解三大容器对象与常用设置
2020/09/30 Python
CSS3实现多样的边框效果
2018/05/04 HTML / CSS
西班牙电子产品购物网站:Electronicamente
2018/07/26 全球购物
FLOS美国官网:意大利高级照明工艺的传奇
2018/08/07 全球购物
英国第一的市场和亚马逊替代品:OnBuy
2019/03/16 全球购物
美国时尚假发购物网站:Wigsbuy
2019/04/06 全球购物
药学专业个人自我评价
2013/11/11 职场文书
跟单文员岗位职责
2014/01/03 职场文书
求职信的正确写法
2014/07/10 职场文书
村主任群众路线个人对照检查材料
2014/09/26 职场文书
门面房租房协议书
2014/12/01 职场文书
先进党员事迹材料
2014/12/24 职场文书
酒店员工辞职信范文
2015/02/28 职场文书
企业承诺书格式范文
2015/04/28 职场文书