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实例教程(19) 使用HoTMetal(2)
Dec 23 Javascript
由document.body和document.documentElement想到的
Apr 13 Javascript
jQuery通过点击行来删除HTML表格行的实现示例
Sep 10 Javascript
JS中的form.submit()不能提交表单的错误原因
Oct 08 Javascript
jQuery+JSON实现AJAX二级联动实例分析
Dec 18 Javascript
基于JavaScript实现瀑布流布局(二)
Jan 26 Javascript
JavaScript和JQuery获取DIV值的方法示例
Mar 07 Javascript
JavaScript实现修改伪类样式
Nov 27 Javascript
微信小程序实现下载进度条的方法
Dec 08 Javascript
详解小程序毫秒级倒计时(适用于拼团秒杀功能)
May 05 Javascript
微信小程序实现上传word、txt、Excel、PPT等文件功能
May 23 Javascript
JS操作Fckeditor的一些常用方法(获取、插入等)
Feb 19 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数学运算
2011/12/30 PHP
smarty模板引擎中内建函数if、elseif和else的使用方法
2015/01/22 PHP
PHP面向对象程序设计之命名空间与自动加载类详解
2016/12/02 PHP
xmlhttp缓存清除的2种解决方法
2013/12/13 Javascript
将数字转换成大写的人民币表达式的js函数
2014/09/21 Javascript
原生的html元素选择器类似jquery选择器
2014/10/15 Javascript
JQuery悬停控制图片轮播——代码简单
2015/08/05 Javascript
JavaScript中获取纯正的undefined的方法
2016/03/06 Javascript
全面了解JS中的匿名函数
2016/06/29 Javascript
JS获取及验证开始结束日期的方法
2016/08/20 Javascript
Javascript 函数的四种调用模式
2016/11/05 Javascript
微信小程序开发入门基础教程
2017/04/19 Javascript
axios post提交formdata的实例
2018/03/16 Javascript
vue-cli与webpack处理静态资源的方法及webpack打包的坑
2018/05/15 Javascript
微信小程序实现折叠与展开文章功能
2018/06/12 Javascript
JS实现可视化音频效果的实例代码
2020/01/16 Javascript
Vue 中使用 typescript的方法详解
2020/02/17 Javascript
如何配置vue.config.js 处理static文件夹下的静态文件
2020/06/19 Javascript
javascript实现点击产生随机图形
2021/01/25 Javascript
[03:09]2014DOTA2国际邀请赛 Mushi前队友送上祝福
2014/07/12 DOTA
[46:20]CHAOS vs Alliacne 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
Python中处理unchecked未捕获异常实例
2015/01/17 Python
使用Python脚本在Linux下实现部分Bash Shell的教程
2015/04/17 Python
Python中使用hashlib模块处理算法的教程
2015/04/28 Python
Python实现变量数值交换及判断数组是否含有某个元素的方法
2017/09/18 Python
django使用xlwt导出excel文件实例代码
2018/02/06 Python
在django admin中添加自定义视图的例子
2019/07/26 Python
简述python&amp;pytorch 随机种子的实现
2020/10/07 Python
Java语言程序设计测试题改错题部分
2014/07/22 面试题
幼儿园区域活动总结
2014/05/08 职场文书
村党支部公开承诺书
2014/05/29 职场文书
乡镇个人对照检查材料
2014/08/22 职场文书
2014年商场工作总结
2014/11/22 职场文书
2014年小学图书室工作总结
2014/12/09 职场文书
食堂采购员岗位职责
2015/04/03 职场文书
公安忠诚教育心得体会
2016/01/23 职场文书