LuLu UI pure版中文文档 »

Fork Me

Tab选项卡切换

这里的Tab选项卡切换本质上是一个切换器,任意1对1的交互效果都支持,例如文档后面演示的轮播效果。

作为插件单独使用

引用下面CSS文件:

<link rel="stylesheet" href="https://qidian.gtimg.com/lulu/pure/css/common/ui/Tab.css">

引用下面的JS文件:

<script src="https://qidian.gtimg.com/lulu/pure/js/common/ui/Tab.js"></script>

效果与基本使用

页面内选项卡

效果见本页demo演示。

HTML结构如下:

<div id="tabView" class="ui-tab-tabs">
    <a href="#tabTarget1" class="ui-tab-tab active">选项卡文档</a>
    <a href="#tabTarget2" class="ui-tab-tab">业务JS分离演示</a>
</div>
<div class="ui-tab-contents">
    <div id="tabTarget1" class="ui-tab-content active"></div>
    <div id="tabTarget2" class="ui-tab-content"></div>
</div>

JS Tab初始化:

new Tab(document.querySelectorAll('#tabView > a'), {
    slide: true,
    onSwitch: function (tab, resetTab, panel, resetPanel) {
        // todo
    }
});

上面代码红色部分是选项卡效果生效比较重要的关联设置,href的属性值正好是切换面板元素的ID。

.ui-tab-contents元素可以在页面任意位置,没有限制。

可以看到,选项卡切换的效果触发都是基于状态类名.active实现的。.active类名本身不具有任何样式,用在和其他选择器发生关联进而实现样式设置。

使用href="#id"进行面板元素关联旨在保证无JavaScript或者页面处于非可交互状态时候选项卡也可以使用,语义也非常好,但是由于现在现代浏览器还没有支持:target-within伪类,效果并不完美,有些开发可能不太喜欢,则可以使用data-rel自定义属性指定关联面板的ID或者类名。例如:

本项目通用选项卡基本 HTML 结构如下:

<div id="tabView" class="ui-tab-tabs">
    <a href="javascript:" class="ui-tab-tab active" data-rel="tabTarget1">选项卡1</a>
    <a href="javascript:" class="ui-tab-tab" data-rel="tabTarget2">选项卡2</a>
</div>
<div class="ui-tab-contents">
    <div id="tabTarget1" class="ui-tab-content active"></div>
    <div id="tabTarget2" class="ui-tab-content"></div>
</div>

链接选项卡

如果你的选项卡是 url 页面刷新跳转之流,则只需要静态 HTML 即可,无需任何 JS 绑定或事件处理。HTML如下:

<div class="ui-tab-tabs">
    <a href="/a/" class="ui-tab-tab">选项卡1</a>
    <a href="/b/" class="ui-tab-tab active">选项卡2</a>
</div>

选项卡变体

Tab.js也可以实现手风琴切换或者广告图轮播效果(自己额外增加一段定时器代码),具体参见文档底部案例。

语法和参数

var myTab = new Tab(elements, callback);
var myTab = new Tab(elements, options);

其中:

element
必需。HTMLCollection元素集合。表示触发选项卡切换的元素。
callback
可选。Function函数。表示切换时候触发的回调。
options
可选。Object纯对象。可选参数释义见下表:
参数名称 支持类型 默认值 释义
eventType String 'click' 事件类型。默认为点击事件。

还支持'mouseover''mouseenter'甚至'focus'事件。

index String
Number
'auto' 选中选项卡的索引值。默认'auto'表示根据选项卡上的状态类名(如.active)获取index值。
history Boolean true 是否通过url无刷新标记选项卡地址。默认true表示选项卡切换时候查询地址变化。IE10+增强功能。IE9浏览器使用hash标记。

此参数需要Tab按钮是<a>元素,同时href属性值#开头,或者javascript:开头。

slide Boolean false Tab 切换时底部的下划线是否会有滑动效果。默认false表示 Tab 切换时没有滑动效果。IE10+。
onSwitch Function function () {} 点击切换的回调。其中,上下文this指点击元素DOM对象。

支持4个参数。分别表示:当前点击元素选项卡元素,恢复到非选中态的选项卡元素,显示的面板元素,恢复到非选中态的面板元素。

实例对象

myTab就是返回的实例对象,暴露了以下属性和方法:

{
    // 暴露的元素们
    element = {
        // 选项卡元素们
        tabs: [],
        // 当前激活选项卡
        tab: null,
        // 面板元素们
        panels: [],
        // 当前激活面板元素
        panel: null
    },
    params: {
        // 事件类型
        eventType: 'click',
        // 当前激活选项卡索引值
        index: 0,
        // 是否记录选项卡变化历史
        history: true,
        // 是否下划线动画
        slide: false
    },
    // 回调方法
    callback: {
        switch: function () {}
    },
    // 传入Tab元素,返回对应的Panel元素
    // 可选,如果缺省,使用返回当前激活的Panel元素
    getPanel: function (eleTab) {},
    // 传入Tab元素,对应的面板元素显示
    // 可选,如果缺省,使用当前暴露在element对象中的tab元素
    show: function (eleTab) {}
}

扩展:广告图轮播实现

效果如下:

样式需要重写,LuLu UI不提供,定时播放也需要额外加几行代码,源码示意:

CSS部分:

.slide-container {
    position: relative;
    width: 350px; height: 105px;
    border: 1px solid #ddd;
}
.slide-a {
    position: absolute;
    transition: opacity .2s;
}
.slide-a:not(.active) {
    opacity: 0;
    visibility: hidden;
    transition: opacity .2s, visibility .01s .2s;
}
.slide-img {
    display: block;
    width: 100%; height: 105px;
}
.slide-dot-x {
    width: 350px;
    text-align: center;
    position: relative;
    margin-top: -25px;
}
.slide-dot {
    display: inline-block;
    width: 10px; height: 10px;
    border: 4px solid transparent;
    background-color: #fff;
    background-clip: content-box;
    border-radius: 50%;
}
.slide-dot.active {
    background-color: #cd0000;
}

HTML部分:

<div id="slideContainer" class="slide-container">
    <a href id="slideLi1" class="slide-a active">
        <img src="1.jpg" class="slide-img">
    </a>
    <a href id="slideLi2" class="slide-a">
        <img src="2.jpg" class="slide-img">
    </a>
    <a href id="slideLi3" class="slide-a">
        <img src="3.jpg" class="slide-img">
    </a>
</div>
<div id="slideDot" class="slide-dot-x">
    <i class="slide-dot active" data-rel="slideLi1"></i>
    <i class="slide-dot" data-rel="slideLi2"></i>
    <i class="slide-dot" data-rel="slideLi3"></i>
</div>

JS部分:

var slideTab = new Tab(document.querySelectorAll('#slideDot i'), {
    eventType: 'mouseover'
});
// 定时器自己添加
var timerSlide = null;
var funSetTimer = function () {
    clearInterval(timerSlide);
    timerSlide = setInterval(function () {
        var eleTabs = slideTab.element.tabs;
        slideTab.show(eleTabs[slideTab.params.index + 1] || eleTabs[0]);
    }, 3000);
};
funSetTimer();

// 鼠标经过移除定时器
document.querySelectorAll('#slideContainer, #slideDot').forEach(function (ele) {
    ele.addEventListener('mouseenter', function () {
        clearInterval(timerSlide);
    });
    ele.addEventListener('mouseleave', funSetTimer);
});

每次进来,图片会重载一次,高度随机。演示事件如何触发的。

代码如下:

// 点击第二个选项卡
eleTab2.addEventListener('click', function () {
    container.style.height = container.clientHeight + 'px';
    container.innerHTML = '';
    container.loading = true;
    setTimeout(function () {
        container.innerHTML = '<img src="1.jpg" height="...">';
        container.loading = false;
        container.style.height = 'auto';
    }, 1000);
});

虽然Tab组件提供了onSwitch回调方法。

但是实际开发还是建议对选项卡元素进行独立的事件绑定,好处在于业务代码和UI代码分离开来了,Tab组件只负责切换显示,布局变化。业务逻辑还是在业务代码中,这样前端分离,不耦合,维护方便 bug 少!

另外,建议先绑定业务事件代码,再执行new Tab()初始化,当然大部分场景下,在后面绑定也没有什么关系。

本页贡献者:

zhangxinxu,lennonover