视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
以BootStrap Tab为例写一个前端组件
2020-11-27 22:34:17 责编:小采
文档

介绍

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

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

原生bootstrap-tab组件使用可参考https://www.runoob.com/bootstrap/bootstrap-tab-plugin.html

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

<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:https://github.com/bill1012/bootstrap-tab

总结

以上所述是小编给大家介绍的以BootStrap Tab为例写一个前端组件,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

下载本文
显示全文
专题