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 相关文章推荐
用JS判断IE版本的代码 超管用!
Aug 09 Javascript
js实现运动logo图片效果及运动元素对象sportBox使用方法
Dec 25 Javascript
JS创建事件的三种方法(实例代码)
May 12 Javascript
js无法获取到html标签的属性的解决方法
Jul 26 Javascript
.net MVC+Bootstrap下使用localResizeIMG上传图片
Apr 21 Javascript
Vue.js tab实现选项卡切换
May 16 Javascript
JS实现前端缓存的方法
Sep 21 Javascript
webpack写jquery插件的环境配置
Dec 21 jQuery
Vue项目中使用better-scroll实现菜单映射功能方法
Sep 11 Javascript
VUE-ElementUI 自定义Loading图操作
Nov 11 Javascript
ajax jquery实现页面某一个div的刷新效果
Mar 04 jQuery
Node.js实现断点续传
Jun 23 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
探讨Hessian在PHP中的使用分析
2013/06/13 PHP
PHP传参之传值与传址的区别
2015/04/24 PHP
PHP批量去除BOM头代码分享
2015/06/26 PHP
Docker配置PHP开发环境教程
2016/12/21 PHP
JS打开层/关闭层/移动层动画效果的实例代码
2013/05/11 Javascript
js闭包实现按秒计数
2015/04/23 Javascript
javascript实现简单的html5视频播放器
2015/05/06 Javascript
JS实现左右拖动改变内容显示区域大小的方法
2015/10/13 Javascript
js格式化时间的方法
2015/12/18 Javascript
谈谈JS中常遇到的浏览器兼容问题和解决方法
2016/12/17 Javascript
有关JS中的0,null,undefined,[],{},'''''''',false之间的关系
2017/02/14 Javascript
jquery实现的table排序功能示例
2017/03/10 Javascript
浅析bootstrap原理及优缺点
2017/03/19 Javascript
Vue-router 类似Vuex实现组件化开发的示例
2017/09/15 Javascript
Vue.JS项目中5个经典Vuex插件
2017/11/28 Javascript
Vue表单及表单绑定方法
2018/09/04 Javascript
如何将百度地图包装成Vue的组件的方法步骤
2019/02/12 Javascript
基于JS开发微信网页录音功能的实例代码
2019/04/30 Javascript
微信小程序获取用户信息的两种方法wx.getUserInfo与open-data实例分析
2019/05/03 Javascript
node.js express框架实现文件上传与下载功能实例详解
2019/10/15 Javascript
js实现简单五子棋游戏
2020/05/28 Javascript
[01:09]2014DOTA2国际邀请赛 TI4西雅图DOTA2 中国美女coser加油助威
2014/07/20 DOTA
[58:35]OG vs EG 2019国际邀请赛淘汰赛 胜者组 BO3 第二场 8.22
2019/09/05 DOTA
python实现的DES加密算法和3DES加密算法实例
2015/06/03 Python
pygame游戏之旅 创建游戏窗口界面
2018/11/20 Python
python实现在函数图像上添加文字和标注的方法
2019/07/08 Python
关于pytorch中网络loss传播和参数更新的理解
2019/08/20 Python
使用PyInstaller将Pygame库编写的小游戏程序打包为exe文件及出现问题解决方法
2019/09/06 Python
Python yield的用法实例分析
2020/03/06 Python
python 实现图片裁剪小工具
2021/02/02 Python
纽约服装和生活方式品牌:Saturdays NYC
2017/08/13 全球购物
马来西亚与新加坡长途巴士售票网站:BusOnlineTicket.com
2018/11/05 全球购物
法学专业个人求职信
2013/09/26 职场文书
工程预算与管理应届生求职信
2013/10/06 职场文书
2014年教师学期工作总结
2014/11/08 职场文书
街道社区活动报告
2015/02/05 职场文书