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 相关文章推荐
Jquery获取和修改img的src值的方法
Feb 17 Javascript
js模拟hashtable的简单实例
Mar 06 Javascript
director.js实现前端路由使用实例
Feb 03 Javascript
Jquery代码实现图片轮播效果(一)
Aug 12 Javascript
从零开始学习Node.js系列教程一:http get和post用法分析
Apr 13 Javascript
详解Vue用axios发送post请求自动set cookie
May 10 Javascript
使用use注册Vue全局组件和全局指令的方法
Mar 08 Javascript
微信小程序新手教程之页面打开数量限制
Mar 03 Javascript
小程序自定义单页面、全局导航栏的实现代码
Mar 15 Javascript
webpack.DefinePlugin与cross-env区别详解
Feb 23 Javascript
解决vue字符串换行问题(绝对管用)
Aug 06 Javascript
Js类的构建与继承案例详解
Sep 15 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
overlord人气高涨,却被菲利普频繁举报,第四季很难在国内上映
2020/05/06 日漫
学习php笔记 字符串处理
2010/10/19 PHP
php 传值赋值与引用赋值的区别
2010/12/29 PHP
PHP+Mysql+jQuery实现动态展示信息
2011/10/08 PHP
php单态设计模式(单例模式)实例
2014/11/18 PHP
php文件上传及下载附带显示文件及目录功能
2017/04/27 PHP
php自定义排序uasort函数示例【二维数组按指定键值排序】
2019/06/19 PHP
javascript 特性检测并非浏览器检测
2010/01/15 Javascript
JQUERY获取form表单值的代码
2010/07/17 Javascript
javascript函数式编程程序员的工具集
2015/10/11 Javascript
jQuery前端开发35个小技巧
2016/05/24 Javascript
jQuery 3.0十大新特性最终版发布
2016/07/14 Javascript
jQuery自定义图片上传插件实例代码
2017/04/04 jQuery
JavaScript实现网页头部进度条刷新
2017/04/16 Javascript
微信小程序中post方法与get方法的封装
2017/09/26 Javascript
Vue-CLI3.x 设置反向代理的方法
2018/12/06 Javascript
JavaScript的级联函数用法简单示例【链式调用】
2019/03/26 Javascript
[06:30]DOTA2英雄梦之声_第15期_死亡先知
2014/06/21 DOTA
[51:39]DOTA2-DPC中国联赛 正赛 Magma vs LBZS BO3 第二场 2月7日
2021/03/11 DOTA
Python使用chardet判断字符编码
2015/05/09 Python
Python与R语言的简要对比
2017/11/14 Python
Django Rest framework权限的详细用法
2019/07/25 Python
Python 根据数据模板创建shapefile的实现
2019/11/26 Python
Python加速程序运行的方法
2020/07/29 Python
Python爬虫与反爬虫大战
2020/07/30 Python
Python实现文件压缩和解压的示例代码
2020/08/12 Python
GANT英国官方网上商店:甘特衬衫
2018/02/06 全球购物
医护人员英文求职信范文
2013/11/26 职场文书
移风易俗倡议书
2014/04/15 职场文书
小学兴趣小组活动总结
2014/07/07 职场文书
2015年教师节演讲稿范文
2015/03/19 职场文书
2015年助残日活动总结
2015/03/27 职场文书
2016先进集体事迹材料范文
2016/02/25 职场文书
python设置 matplotlib 正确显示中文的四种方式
2021/05/10 Python
centos8安装MongoDB的详细过程
2021/10/24 MongoDB
MySQL表类型 存储引擎 的选择
2021/11/11 MySQL