当前位置: 移动技术网 > IT编程>开发语言>JavaScript > 以BootStrap Tab为例写一个前端组件

以BootStrap Tab为例写一个前端组件

2017年12月12日  | 移动技术网IT编程  | 我要评论

介绍

本文以bootstrap标签页组件为例,介绍如何编写或者封装一个前端组件,以下是实现效果:

原生的bootstrap-tab组件主要有html,css组成,开发者使用时,需要写很多代码,不易于使用,对bootstrap-tab封装后,可以更方便地使用,同时提供关闭、增加tab页、指定当前选中页、即使加载等功能,这样组件可以适配更多的场景。

原生bootstrap-tab组件使用可参考

其中官网一段实例代码是:

<ul id="mytab" class="nav nav-tabs">
  <li class="active"><a href="#home" rel="external nofollow" data-toggle="tab">
      菜鸟教程</a>
  </li>
  <li><a href="#ios" rel="external nofollow" data-toggle="tab">ios</a></li>
  <li class="dropdown">
    <a href="#" rel="external nofollow" id="mytabdrop1" class="dropdown-toggle"
      data-toggle="dropdown">java <b class="caret"></b>
    </a>
    <ul class="dropdown-menu" role="menu" aria-labelledby="mytabdrop1">
      <li><a href="#jmeter" rel="external nofollow" tabindex="-1" data-toggle="tab">
          jmeter</a>
      </li>
      <li><a href="#ejb" rel="external nofollow" tabindex="-1" data-toggle="tab">
          ejb</a>
      </li>
    </ul>
  </li>
</ul>
<div id="mytabcontent" class="tab-content">
  <div class="tab-pane fade in active" id="home">
    <p>菜鸟教程是一个提供最新的web技术站点,本站免费提供了建站相关的技术文档,帮助广大web技术爱好者快速入门并建立自己的网站。菜鸟先飞早入行——学的不仅是技术,更是梦想。</p>
  </div>
  <div class="tab-pane fade" id="ios">
    <p>ios 是一个由苹果公司开发和发布的手机操作系统。最初是于 2007 年首次发布 iphone、ipod touch 和 apple
      tv。ios 派生自 os x,它们共享 darwin 基础。os x 操作系统是用在苹果电脑上,ios 是苹果的移动版本。</p>
  </div>
  <div class="tab-pane fade" id="jmeter">
    <p>jmeter 是一款开源的测试软件。它是 100% 纯 java 应用程序,用于负载和性能测试。</p>
  </div>
  <div class="tab-pane fade" id="ejb">
    <p>enterprise java beans(ejb)是一个创建高度可扩展性和强大企业级应用程序的开发架构,部署在兼容应用程序服务器(比如 jboss、web logic 等)的 j2ee 上。
    </p>
  </div>
</div>
<script>
  $(function () {
    $('#mytab li:eq(1) a').tab('show');
  });
</script>

那么如何封装或者开发一个组件呢?

组件开发步骤

step1:结构化静态代码,梳理核心的问题

在组件开发流程中,可能拿到前端设计的静态代码(html+css的组合),这时候要拆解代码结构,使得结构能够模板化。其次梳理核心问题,bootstrap-tab组件化之后,应该能够动态加载tab内容,这个可以通过jquery.load方法解决,这样可以做到主页面和子页面解耦。

读懂了静态代码,理解了结构和核心问题就可以写代码了,首先搭建组件的架子。

step2:组件骨架

/**
 * bootstrap tab组件封装
 * @author billjiang qq:475572229
 * @created 2017/7/24
 *
 */
(function ($, window, document, undefined) {
  'use strict';
  var pluginname = 'tabs';
  //入口方法
  $.fn[pluginname] = function (options) {
    var self = $(this);
    if (this == null)
      return null;
    var data = this.data(pluginname);
    if (!data) {
      data = new basetab(this, options);
      self.data(pluginname, data);
    }
    return data;
  };
  var basetab = function (element, options) {
    this.$element = $(element);
    this.options = $.extend(true, {}, this.default, options);
    this.init();
  }
  //默认配置
  basetab.prototype.default = {
  }
  //结构模板
  basetab.prototype.template = {
  }
  //初始化
  basetab.prototype.init = function () {
  } 
})(jquery, window, document)

搭建了以上组件的骨架,并对组件命名为tabs,这样就可以通过$("#tab-container").data("tabs")获取组价的方法和属性。在入口方法中,会将初始化后的对象缓存到页面html中,这样可以避免重复创建对象。一些经典的开源前端组件都是这样写法,比如bootstrap-treeview,大家有时间可以看看它的源码。

以上的写法使用原型链的写法。定义了默认配置,结构模板,初始化入口。

编写代码

在组件的代码骨架里,填充模板代码,这里使用占位符{0},{1}等表示外部传入的变量,然后在init方法中校验外部传入数据的合法性,然后构建组件,并且绑定关闭事件、点击事件。

在开发前端组件的时候,往往不知道默认参数应该有什么,可以在开发的时候,用到就加上去,这里加了两个默认参数,一个showindex是默认显示的tab页索引,一个loadalltab是否一次性把所有的页面数据加载完。

具体的逻辑请看下面的代码: 

//默认配置
  basetab.prototype.default = {
    showindex: 0, //默认显示页索引
    loadall: true,//true=一次全部加在页面,false=只加在showindex指定的页面,其他点击时加载,提高响应速度
  }
  //结构模板
  basetab.prototype.template = {
    ul_nav: '<ul class="nav nav-tabs"></ul>',
    ul_li: '<li><a href="#{0}" rel="external nofollow" data-toggle="tab"><span>{1}</span></a></li>',
    ul_li_close: '<i class="fa fa-remove closeable" title="关闭"></i>',
    div_content: '<div class="tab-content"></div>',
    div_content_panel: '<div class="tab-pane fade" id="{0}"></div>'
  }
  //初始化
  basetab.prototype.init = function () {
    if (!this.options.data || this.options.data.length == 0) {
      console.error("请指定tab页数据");
      return;
    }
    //当前显示的显示的页面是否超出索引
    if (this.options.showindex < 0 || this.options.showindex > this.options.data.length - 1) {
      console.error("showindex超出了范围");
      //指定为默认值
      this.options.showindex = this.default.showindex;
    }
    //清除原来的tab页
    this.$element.html("");
    this.builder(this.options.data);
  }
  //使用模板搭建页面结构
  basetab.prototype.builder = function (data) {
    var ul_nav = $(this.template.ul_nav);
    var div_content = $(this.template.div_content);
    for (var i = 0; i < data.length; i++) {
      //nav-tab
      var ul_li = $(this.template.ul_li.format(data[i].id, data[i].text));
      //如果可关闭,插入关闭图标,并绑定关闭事件
      if (data[i].closeable) {
        var ul_li_close = $(this.template.ul_li_close);
        ul_li.find("a").append(ul_li_close);
        ul_li.find("a").append(" ");
      }
      ul_nav.append(ul_li);
      //div-content
      var div_content_panel = $(this.template.div_content_panel.format(data[i].id));
      div_content.append(div_content_panel);
    }
    this.$element.append(ul_nav);
    this.$element.append(div_content);
    this.loaddata();
    this.$element.find(".nav-tabs li:eq(" + this.options.showindex + ") a").tab("show");
  }
  basetab.prototype.loaddata = function () {
    var self = this;
    //tab点击即加载事件
    //设置一个值,记录每个tab页是否加载过
    this.stateobj = {};
    var data = this.options.data;
    //如果是当前页或者配置了一次性全部加载,否则点击tab页时加载
    for (var i = 0; i < data.length; i++) {
      if (this.options.loadall || this.options.showindex == i) {
        if (data[i].url) {
          $("#" + data[i].id).load(data[i].url);
          this.stateobj[data[i].id] = true;
        } else {
          console.error("id=" + data[i].id + "的tab页未指定url");
          this.stateobj[data[i].id] = false;
        }
      } else {
        this.stateobj[data[i].id] = false;
        (function (id, url) {
          self.$element.find(".nav-tabs a[href='#" + id + "']").on('show.bs.tab', function () {
            if (!self.stateobj[id]) {
              $("#" + id).load(url);
              self.stateobj[id] = true;
            }
          });
        }(data[i].id, data[i].url))
      }
    }
    //关闭tab事件
    this.$element.find(".nav-tabs li a i.closeable").each(function (index, item) {
      $(item).click(function () {
        var href = $(this).parents("a").attr("href").substr(1);
        $(this).parents("li").remove();
        $("#" + href).parent().remove();
      })
    });
  }

测试

编写一个前端界面,测试组件

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>tab组件</title>
</head>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" rel="external nofollow" >
<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css" rel="external nofollow" >
<link rel="stylesheet" href="../css/bootstrap-tab.css" rel="external nofollow" >
<body>
<div id="tabcontainer"></div>
</body>
<script src="jquery/jquery-1.8.3.min.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script>
<script src="../js/bootstrap-tab.js"></script>
<script>
  $("#tabcontainer").tabs({
    data: [{
      id: 'home',
      text: '百度一下',
      url: "tab_first.html",
      closeable:true
    }, {
      id: 'admineap',
      text: 'admineap',
      url: "tab_second.html"
    }, {
      id: 'edit',
      text: '编辑人员',
      url: "tab_content.html",
      closeable:true
    }],
    showindex:1,
    loadall:false
  })
</script>
</html>

通过配置各种参数,看看组件是否满足了预期的要求。

扩展

组件在使用的过程中还会遇到各种问题,或者各种需求,比如新增一个tab页面,比如获取当前tab的id或index,这是可以在代码中按需扩展。

//新增一个tab页
  basetab.prototype.addtab=function (obj) {
    //nav-tab
    var ul_li = $(this.template.ul_li.format(obj.id, obj.text));
    //如果可关闭,插入关闭图标,并绑定关闭事件
    if (obj.closeable) {
      var ul_li_close = $(this.template.ul_li_close);
      ul_li.find("a").append(ul_li_close);
      ul_li.find("a").append(" ");
    }
    this.$element.find(".nav-tabs").append(ul_li);
    //div-content
    var div_content_panel = $(this.template.div_content_panel.format(obj.id));
    this.$element.find(".tab-content").append(div_content_panel);
    $("#" + obj.id).load(obj.url);
    this.stateobj[obj.id] = true;
    if(obj.closeable){
      this.$element.find(".nav-tabs li a[href='#" + obj.id + "'] i.closeable").click(function () {
        var href = $(this).parents("a").attr("href").substr(1);
        $(this).parents("li").remove();
        $("#" + href).parent().remove();
      })
    }
    this.$element.find(".nav-tabs a[href='#" + obj.id + "']").tab("show");
  }
  //根据id设置活动tab页
  basetab.prototype.showtab=function (tabid) {
    this.$element.find(".nav-tabs li a[href='#" + tabid + "']").tab("show");
  }
  //获取当前活动tab页的id
  basetab.prototype.getcurrenttabid=function () {
    var href=this.$element.find(".nav-tabs li.active a").attr("href");
    href=href.substring(1);
    return href;
  }

更完善的bootrap-tab版本已经开源,详见我的github地址:

bootstrap-tab:

总结

以上所述是小编给大家介绍的以bootstrap tab为例写一个前端组件,希望对大家有所帮助

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网