简单、通用的JQuery Tab实现

网页上的空间是寸土寸金,虽然显示器的分辨率越来越大,可是直到今天,网页设计中仍然是以至少1024×768 像素的支持为主,也就是说,每一屏页面只有区区 955×600像素 的安全尺寸可以用而已。于是,为了在有限的空间里容纳更多的内容,滑动门式的标签切换(Tabs)方式越来越受欢迎。通过滑动门技术,可以在同一块页面区域内放置数倍的内容。根据用户的选择来决定显示哪一部分。最近我在实际应用中,逐步完善出一种基于 jQuery,但是比 jQuery UI Tabs 插件更小巧也更通用的简单 Tabs 实现。

最早的滑动门的技术,一般都是结合 onclick 或者 onmouseover 事件传递一个参数给 JS 函数,根据传递的参数来决定显示哪一个标签。比如:

function showTabs(n) {
  var tabsNumber = 3;
  for (i = 0; i < tabsNumber; i++) {
      if (i == n) {
          document.getElementById("tabPanel-" + i).style.display = "block";
      } else {
          document.getElementById("tabPanel-" + i).style.display = "none";
      }
  }
}

加入有这样的一个函数,就可以在tab的标题按钮中设置 onclick="showTabs(1)"来设置第二块内容显示,而其它块隐藏。

这种方式最大的缺点是:

  • HTML 代码和 JS 代码混合;
  • 可扩展性差;
  • 尽管可以通过 window.onload 绑定事件等方式来是实现 JS 代码从 HTML 中分离,也可以把函数改得更复杂以实现通用性。但是总的来说,还是很难做到一处定义到处引用。

后来随着各种 JS 类库的出现,更强大的 Tabs 出现了,最出名的就是 jQuery UI 中的 tabs 插件。一旦加载了 jQuery框架jQuery UI 插件,那么要在页面中实现 Tabs, 就变得简单了许多。首先我们的页面中的 Tabs 代码这样写:

<div class="tabs">
    <ul>
        <li><a href="#panel-1">标签一</a></li>
        <li><a href="#panel-2">标签二</a></li>
    </ul>
    <div id="panel-1">区域一</div>
    <div id="panel-2">区域二</div>
</div>

注意:这里的代码非常干净,不含任何的 JS 代码或者与文档结构无关的定义。然后,在 head 区域,或者在页面任何地方增加一段 JS 代码:

$(function() {
    $(".tabs").tabs();
});

就实现了 Tabs 功能,这行 JS 代码执行后,上面的 HTML 代码就会变成:

<div class="tabs">
    <ul class="ui-tabs-nav" jquery1239647486215="2">
        <li class="ui-tabs-selected"><a href="#panel-1" jquery1239647486215="8">标签一</a></li>
        <li><a href="#panel-2" jquery1239647486215="9">标签二</a></li>
        ></ul>
    <div id="panel-1" class="ui-tabs-panel" jquery1239647486215="4">
        区域一
    </div>
    <div id="panel-2" class="ui-tabs-panel ui-tabs-hide" jquery1239647486215="5">
        区域二
    </div>
</div>

结合我们自己编写的 CSS,或者 jQuery UI 自带的 CSS,就可以实现滑动门效果。并且,由于 jQuery 的强大,我们可以在页面中放置多组滑动门,然后一次性设定。

要说明的是,这个地方由于只启用了 jQuery UI 中的 Tabs 插件,因此生成的代码还是比较干净的,只增加了 ui-tabs-xxxx 这几个相关的 CSS 类。如果你同时包含了 jQuery UI 的其它插件,那么即使不启用,也会添加一堆的 CSS 定义。而且,jQuery UI Tabs 还提供了非常强大的控制功能,你可以动态地添加 tab,可以随意更改激活事件,可以定义切换效果,还可以设置默认激活状态和禁用等。

但是我在实际应用中遇到了一些问题,除了 jQuery UI 自带的 JS 脚本很大,CSS 不符合实际应用需求外,还有一个最大的问题,你可能已经注意到了,在作为导航的标签定义中,每个标签对应哪一个区域是用链接目标来定义的。比如 <a href="#panel-1">标签一</a><div id="panel-1">区域一</div> 对应,如果你的标签和区域没有对应起来,绑定 tabs() 就不起作用了。

而且,这种方式来带来另一个麻烦,就是当我们需要给标签加上链接的时候,没办法加。即使你将标签的激活事件设置为 onmouseover 而不是 onclick, 链接也不能实现,因为链接用于指定目标了。这种需求在我们的实际应用中并不是不存在的。比如:

两个图片中的 tabs 标签,都要添加到对应的新闻类别或者论坛板块的链接。这时候 jQuery UI Tabs 的默认绑定就带来了麻烦。

其实分析一下,我们在实现滑动门的时候,用以下 HTML 结构就可以满足需要:

<div class="tabs">
    <ul>
        <li>标签一</li>
        <li>标签二</li>
    </ul>
    <div>区域一</div>
    <div>区域二</div>
</div>

借助 jQuery 库,我们可以通过 $(".tabs") 找到要实现的标签,然后 .find("li") 来找到要添加事件的元素,绑定事件的时候,我们可以通过该元素在 $(".tabs li") 集合中的索引值来明确是哪一个标签被激活,然后对应索引值的 panel 显示。代码类似这样:

$(function() {
    $(".tabs").find("li").onmouseover(function(e) {
        if (e.target == this) {
            var tabs = $(this).parent().children("li");
            var panels = $(this).parent().parent().children("div");
            var index = $.inArray(this, tabs);
            if (panels.eq(index)[0]) {
                tabs.removeClass("ui-tabs-selected")
                    .eq(index).addClass("ui-tabs-selected");
                panels.addClass("ui-tabs-hide")
                    .eq(index).removeClass("ui-tabs-hide");
            }
        }
    });
});

这段代码只使用了两个 CSS 类来处理,并且,自动判断 tabs 和 panels 的对应状态,假如你有4个 tab,但是只有前三个启用了,那么你只需要写三个 panel 就可以,第四个 panel 不存在,则第四个 tab 自动不生效。

在实际使用中,会遇到一个问题,一般我们会给 tab 中的文字加链接,那么当鼠标滑过这个 tab 的时候,如果指到了文字,那么激发事件的对象有可能是 A 元素而不是 LI 元素,则事件就不能正确激发。所以我们改进代码如下:

$(function() {
    $(".ui-tabs-nav > li > a")onmouseover(function(e) {
        if (e.target == this) {
            var tabs = $(this).parent().parent().children("li");
            var panels = $(this).parent().parent().parent().children(".ui-tabs-panel");
            var index = $.inArray(this, tabs);
            if (panels.eq(index)[0]) {
                tabs.removeClass("ui-tabs-selected")
                    .eq(index).addClass("ui-tabs-selected");
                panels.addClass("ui-tabs-hide")
                    .eq(index).removeClass("ui-tabs-hide");
            }
        }
    });
});

与此对应的 HTML 结构是:

>div>
    >ul class="ui-tabs-nav">
        >li class="ui-tabs-selected">>a href="/bbs">论坛新帖>/a>>/li>
        >li>>a href="/blog">最新博文>/a>>/li>
    >/ul>
    >div class="ui-tabs-panel">
      >!--这里调用最新论坛文章-->
    >/div>
    >div class="ui-tabs-panel ui-tabs-hide">
      >!--这里调用最新博客文章-->
    >/div>
>/div>

同时,我们有以下的 CSS 样式:

.ui-tabs-nav {
    /*导航容器定义*/
}
.ui-tabs-nav li {
    /*默认标签样式*/
}
.ui-tabs-nav li.ui-tabs-selected {
    /*激活的标签样式*/
}
.ui-tabs-panel {
    /*默认的显示区域样式*/
}
.ui-tabs-hide {
    display: none;
}

这样,就可以根据你的需要,结合自己的 CSS, 定制不同样式的滑动门了。把相应的 JS 代码放到页面中,那么在页面里任何地方只要你按照HTML结构编写了一段 HTML, 这段 HTML 就会自动变成滑动门。而不用在每个页面里单独指定特定的 selector 来应用滑动门的 tabs() 方法。并且,根据需要给你的滑动门标签添加需要的链接,或者不要链接( href="#" 或者 href="javascript:void(0)"). 这段滑动门代码只要具有 jQuery 就可以正常运行,不需要加载 jQuery UI. 非常简单,而且很通用,样式上喜欢怎么扩展都可以。

具体效果可以参见 http:/www.taihainet.com2014修订:由于年代久远,页面已经多次改版,本文截图中的部分已不存在。), 在台海网首页中,我一共应用了四个样式共九组滑动门,代码就只是上面给出的那一段。四个样式列举如下:

滑动门一:多个搜索表单,暂时只实现两个,后面三个由于没有对应的 ui-tabs-panel, 自动禁用,但是链接可以点击。

滑动门二:多块商务信息区域,其中第三个由于没有对应的 ui-tabs-panel, 自动禁用。

滑动门三:新闻栏目切换,标签中的文字链接到对应的新闻栏目。

滑动门四:论坛分板块帖子调用。标签中的文字链接到对应的论坛板块。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏极客编程

前端的对决:React的JSX与Vue的templates

React.js和Vue.js是这个星球上最流行的JavaScript库。它们都很强大,相对来说很容易获取和使用。

23520
来自专栏互联网杂技

编码规范

不要在自闭合(self-closing)元素的尾部添加斜线 -- HTML5 规范中明确说明这是可选的。 不要省略可选的结束标签(closing tag)(例如...

34570
来自专栏熊二哥

Bootstrap快速入门

Bootstrap学习有两个重点,一个是概念的理解,理解bootstrap是如何通过div来代替过去的table布局的;一个是常用结构的熟悉,做到需要的组件及时...

54260
来自专栏阮一峰的网络日志

CSS动画简介

现在,我很少写介绍CSS的文章,因为感觉网站开发的关键还是在服务器端。 但是,CSS动画除外,它实在太有用了。 ? 本文介绍CSS动画的两大组成部分:trans...

37380
来自专栏hightopo

原 Web SCADA 电力接线图工控组态

41060
来自专栏从零开始学 Web 前端

从零开始学 Web 系列教程

在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识点,期间也会分享一些好玩的项目。现在就让我们一起进入 Web 前端学习的冒险之旅吧!

26450
来自专栏影子

jQuery中的常用内容总结(二)

转载请注明地址: http://www.cnblogs.com/funnyzpc/p/7571993.html

13230
来自专栏向治洪

React Native在Android平台运行gif的解决方法

概述 目前RN在Android平台上不支持gif格式的图片,而在ios平台是支持的,期待以后的版本中系统也是可以默认支持Android的。首先说下在ios平台怎...

25660
来自专栏向治洪

React Native在Android平台运行gif的解决方法

概述 目前RN在Android平台上不支持gif格式的图片,而在ios平台是支持的,期待以后的版本中系统也是可以默认支持Android的。首先说下在ios平台怎...

39750
来自专栏Android干货园

popwindow 被魅族虚拟键挡住

版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/lyhhj/article/details/45...

21840

扫码关注云+社区

领取腾讯云代金券