ul-tab是一个典型的交互组建,纯css样式是没有意义的。ului库提供了一个基本的jquery插件来实现tab的交互功能,用户也可以根据自己的需求来编写js代码实现交互功能。

如果是基本的交互功能,无论是vue、htmx等前端框架,还是原生js,都能很容易地编写。

对于ului来说,可以通过以下方式来实现tab的交互功能。

  1. 引入jquery和ului的js文件
  2. 选中tab组件的最外层容器并调用ulTab方法
<script src="//ului.top/cdn/js/jquery-3.7.1.min.js"></script>
<script src="//ului.top/cdn/js/modules/ul-tab.js"></script>
<script>
    $(function () {
        $('.ul-tab').ulTab();
    });
</script>

ul-tab.js的代码如下:

(function($) {
    'use strict';

    $.fn.ulTab = function(options) {
        // 默认配置
        var settings = $.extend({
            itemClass: '.ul-tab-item',
            paneClass: '.ul-tab-pane',
            activeClass: 'active',
            showClass: 'ul-show'
        }, options);

        return this.each(function() {
            var $tab = $(this);

            // 查找当前 tab 实例下的元素,并排除嵌套 tab 中的元素
            var $tabItems = $tab.find(settings.itemClass).filter(function() {
                return $(this).closest('.ul-tab').is($tab);
            });
            var $tabPanes = $tab.find(settings.paneClass).filter(function() {
                return $(this).closest('.ul-tab').is($tab);
            });

            $tabItems.on('click', function() {
                var $currentItem = $(this);
                var index = $tabItems.index($currentItem);

                // 切换选项卡的激活状态
                $currentItem.addClass(settings.activeClass).siblings().removeClass(settings.activeClass);

                // 切换内容面板的显示状态
                if ($tabPanes.length > index) {
                    $tabPanes.eq(index).addClass(settings.showClass).siblings().removeClass(settings.showClass);
                }
            });
        });
    };

})(jQuery);
基础选项卡
预览效果
  • HTML
  • SCSS
  • CSS
  • UniApp
HTML Content
SCSS Content
CSS Content
UniApp Content
  • HTML
  • SCSS
  • CSS
  • UniApp
<div class="ul-tab ul-tab-basic">
    <ul class="ul-tab-title ul-tab-basic__title">
        <li class="ul-tab-item ul-tab-basic__item active">HTML</li>
        <li class="ul-tab-item ul-tab-basic__item">SCSS</li>
        <li class="ul-tab-item ul-tab-basic__item">CSS</li>
        <li class="ul-tab-item ul-tab-basic__item">UniApp</li>
    </ul>
    <div class="ul-tab-content ul-tab-basic__content">
        <div class="ul-tab-pane ul-tab-basic__pane ul-show">HTML Content</div>
        <div class="ul-tab-pane ul-tab-basic__pane">SCSS Content</div>
        <div class="ul-tab-pane ul-tab-basic__pane">CSS Content</div>
        <div class="ul-tab-pane ul-tab-basic__pane">UniApp Content</div>
    </div>
</div>
.ul-tab-basic {
  &__title {
    border-bottom: 1px solid $color-border;
    display: flex;
    list-style: none;
    padding: 0;
    margin: 0;
  }

  &__item {
    padding: $space-sm $space-md;
    cursor: pointer;
    position: relative;
    margin-bottom: -1px; // 让选中项的下边框覆盖父元素的下边框

    &.active {
      color: $color-primary-base;
      border-bottom: 2px solid $color-primary-base;
    }
  }

  &__content {
    padding: $space-md;
  }

  &__pane {
    // 默认隐藏,由 .ul-show 控制显示
    display: none;

    &.ul-show {
      display: block;
    }
  }
}
.ul-tab-basic__title {
  border-bottom: 1px solid var(--ul-color-border);
  display: flex;
  list-style: none;
  padding: 0;
  margin: 0;
}
.ul-tab-basic__item {
  padding: 8px 16px;
  cursor: pointer;
  position: relative;
  margin-bottom: -1px;
}
.ul-tab-basic__item.active {
  color: var(--ul-color-primary-base);
  border-bottom: 2px solid var(--ul-color-primary-base);
}
.ul-tab-basic__content {
  padding: 16px;
}
.ul-tab-basic__pane {
  display: none;
}
.ul-tab-basic__pane.ul-show {
  display: block;
}
<view class="ul-tab ul-tab-basic">
    <ul class="ul-tab-title ul-tab-basic__title">
        <li class="ul-tab-item ul-tab-basic__item active">HTML</li>
        <li class="ul-tab-item ul-tab-basic__item">SCSS</li>
        <li class="ul-tab-item ul-tab-basic__item">CSS</li>
        <li class="ul-tab-item ul-tab-basic__item">UniApp</li>
    </ul>
    <view class="ul-tab-content ul-tab-basic__content">
        <view class="ul-tab-pane ul-tab-basic__pane ul-show">HTML Content</view>
        <view class="ul-tab-pane ul-tab-basic__pane">SCSS Content</view>
        <view class="ul-tab-pane ul-tab-basic__pane">CSS Content</view>
        <view class="ul-tab-pane ul-tab-basic__pane">UniApp Content</view>
    </view>
</view>

本站的代码预览功能就是用这个组件实现的。

卡片选项卡
预览效果
  • 标签一
  • 标签二
  • 标签三
  • 标签四
  • 标签五
标签一的内容
标签二的内容
标签三的内容
标签四的内容
标签五的内容
  • HTML
  • SCSS
  • CSS
  • UniApp
<div class="ul-tab ul-tab-card">
    <ul class="ul-tab-title ul-tab-card__title">
        <li class="ul-tab-item ul-tab-card__item active">标签一</li>
        <li class="ul-tab-item ul-tab-card__item">标签二</li>
        <li class="ul-tab-item ul-tab-card__item">标签三</li>
        <li class="ul-tab-item ul-tab-card__item">标签四</li>
        <li class="ul-tab-item ul-tab-card__item">标签五</li>
    </ul>
    <div class="ul-tab-content ul-tab-card__content">
        <div class="ul-tab-pane ul-tab-card__pane ul-show">标签一的内容 </div>
        <div class="ul-tab-pane ul-tab-card__pane">标签二的内容 </div>
        <div class="ul-tab-pane ul-tab-card__pane">标签三的内容 </div>
        <div class="ul-tab-pane ul-tab-card__pane">标签四的内容 </div>
        <div class="ul-tab-pane ul-tab-card__pane">标签五的内容 </div>
    </div>
</div>
.ul-tab-card {
  background: #fff;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);

  &__title {
    display: flex;
    list-style: none;
    padding: 0;
    margin: 0;
    border-bottom: 1px solid $color-border;
  }

  &__item {
    flex: 1;
    padding: $space-sm $space-md;
    text-align: center;
    cursor: pointer;
    background: #f8f9fa;
    color: #666;
    border-right: 1px solid $color-border;
    transition: all 0.3s ease;
    position: relative;

    &:last-child {
      border-right: none;
    }

    &:hover {
      background: #e9ecef;
      color: #333;
    }

    &.active {
      background: $color-primary-base;
      color: #fff;

      &:hover {
        background: $color-primary-hover;
      }
    }
  }

  &__content {
    padding: $space-md;
  }

  &__pane {
    // 默认隐藏,由 .ul-show 控制显示
    display: none;

    &.ul-show {
      display: block;
    }
  }
}
.ul-tab-card {
  background: #fff;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.ul-tab-card__title {
  display: flex;
  list-style: none;
  padding: 0;
  margin: 0;
  border-bottom: 1px solid var(--ul-color-border);
}
.ul-tab-card__item {
  flex: 1;
  padding: 8px 16px;
  text-align: center;
  cursor: pointer;
  background: #f8f9fa;
  color: #666;
  border-right: 1px solid var(--ul-color-border);
  transition: all 0.3s ease;
  position: relative;
}
.ul-tab-card__item:last-child {
  border-right: none;
}
.ul-tab-card__item:hover {
  background: #e9ecef;
  color: #333;
}
.ul-tab-card__item.active {
  background: var(--ul-color-primary-base);
  color: #fff;
}
.ul-tab-card__item.active:hover {
  background: var(--ul-color-primary-hover);
}
.ul-tab-card__content {
  padding: 16px;
}
.ul-tab-card__pane {
  display: none;
}
.ul-tab-card__pane.ul-show {
  display: block;
}
<view class="ul-tab ul-tab-card">
    <ul class="ul-tab-title ul-tab-card__title">
        <li class="ul-tab-item ul-tab-card__item active">标签一</li>
        <li class="ul-tab-item ul-tab-card__item">标签二</li>
        <li class="ul-tab-item ul-tab-card__item">标签三</li>
        <li class="ul-tab-item ul-tab-card__item">标签四</li>
        <li class="ul-tab-item ul-tab-card__item">标签五</li>
    </ul>
    <view class="ul-tab-content ul-tab-card__content">
        <view class="ul-tab-pane ul-tab-card__pane ul-show">标签一的内容 </view>
        <view class="ul-tab-pane ul-tab-card__pane">标签二的内容 </view>
        <view class="ul-tab-pane ul-tab-card__pane">标签三的内容 </view>
        <view class="ul-tab-pane ul-tab-card__pane">标签四的内容 </view>
        <view class="ul-tab-pane ul-tab-card__pane">标签五的内容 </view>
    </view>
</view>