更新记录

2.2.7(2024-04-12)

  • 标签栏吸顶时,记录标签内容的滚动高度,在下一次切换回来时回滚到相应位置
  • barWidth、barHeight属性支持传入'auto'值,表示滑块宽高可以自适应选中标签的宽高,支持范围见文档

2.2.6(2024-03-15)

  • 【修复】抖音小程序报错

2.2.5(2024-03-14)

  • bug修复
查看更多

平台兼容性

Vue2 Vue3
App 快应用 微信小程序 支付宝小程序 百度小程序 字节小程序 QQ小程序
HBuilderX 3.5.5 app-vue ×
钉钉小程序 快手小程序 飞书小程序 京东小程序
H5-Safari Android Browser 微信浏览器(Android) QQ浏览器(Android) Chrome IE Edge Firefox PC-Safari
×

y-tabs 标签页组件

注意:

  • 2.0.1+为非兼容性升级,重命名了诸多样式以及提供的属性名,也移除了部分属性及事件,如无必要,请勿升级,具体调整内容请查看更新记录。


Tips

  • 如果有问题,可尝试下载最新代码(示例项目中的uni_modules/y-tabs是最新的)。
  • 请保证HBuilderX正式版为 v3.4.18、Alpha版为 v3.5.2
  • 使用该插件需安装scss插件。
  • 点击右上角的“使用HubilderX导入示例项目”按钮下载示例项目运行并查看效果,项目中内置不少案例。
  • 也可扫描右侧图片中的微信小程序码查看(由于微信小程序审核较严,无法发布新版本,因此案例较老,最好运行示例项目查看)。
  • 可以加QQ群交流反馈:566764891;也可以邮箱或QQ留言:18508420370@163.com1431948195

支持的平台

  • H5、app-vue、微信、支付宝、钉钉、百度、字节、QQ、飞书、快手、京东小程序可用。
  • 暂不支持nvue及快应用。

使用方式

1、通过HbuilerX创建项目

  • 该组件符合uni_modules规范,使用HbuilderX导入插件到项目根目录下的uni_modules文件夹中。
  • template中直接使用,无需单独引入注册组件。
  • 该组件依赖于uni-icons,请单独导入。

2、通过vue cli创建项目

  • 需保证src下面有uni_modules文件夹,将y-tabs拷贝到里面
  • pages.json中通过easycom的方式引入组件(tabs组件中使用了uni-icons,因此需要引入uni-ui)
    {
    "easycom": {
        "autoscan": true,
        "custom": {
            "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue",
            "^y-(.*)": "@/uni_modules/y-$1/components/y-$1.vue"
        }
    },
    }

普通案例

  • 注意:在QQ/百度/字节跳动/飞书/快手小程序中,自定义组件在渲染时会比App/H5端多一级节点,导致标签内容样式失效,需在组件上添加".y-tab-virtual"的样式
<template>
 <view>
     <y-tabs v-model="activeIndex" @click="tabClick"  @change="tabChange">
        <y-tab class="y-tab-virtual" v-for="index in 5" :key="index" :title="'标签'+index">
            <view class="content-wrap"> 内容{{index}} </view>
        </y-tab>
     </y-tabs>
 </view>
</template>
<script>
    export default {
        data() {
            return {
                activeIndex: 0,
            }
        },
        methods: {
            // 标签点击事件
            tabClick(index, item) {
                console.log("tabClick", index, item);
            },
            // 标签切换事件
            tabChange(index, item) {
                console.log("tabChange", index, item);
            }
        }
    }
</script>
<style scoped>
/* #ifdef MP-QQ || MP-BAIDU || MP-TOUTIAO || MP-LARK || MP-KUAISHOU */
.y-tab-virtual {
    position: relative;
    flex-shrink: 0;
    width: 100%;
}
</style>

滚动吸顶示例

直接开启sticky属性即可

<template>
 <view>
     <y-tabs v-model="activeIndex" sticky :offsetTop="offsetTop">
        <y-tab class="y-tab-virtual" v-for="index in 5" :key="index" :title="'标签'+index">
            <view class="content-wrap"> 内容{{index}} </view>
        </y-tab>
     </y-tabs>
 </view>
</template>
<script>
    export default {
        data() {
            return {
                activeIndex: 0,
                offsetTop: 0, //粘性布局下与顶部的最小距离
            }
        },
        created() {
            // H5端需要减去顶部导航栏高度
            // #ifdef H5
            this.offsetTop = 43
            // #endif
        },
    }
</script>
<style scoped>
/* #ifdef MP-QQ || MP-BAIDU || MP-TOUTIAO || MP-LARK || MP-KUAISHOU */
.y-tab-virtual {
    position: relative;
    flex-shrink: 0;
    width: 100%;
}

.content-wrap{
    height:200vh;
}

</style>

Swiper联动示例

  • 请注意Swiper组件的@transition@animationfinish的支持平台
  • barAnimateMode="worm",设置底部条切换类似毛毛虫蠕动的效果
  • 经过测试,仅支持App、H5、微信、支付宝、字节跳动、QQ、快手小程序
<template>
 <view>
     <y-tabs ref="tabs" v-model="activeIndex" barAnimateMode="worm">
        <y-tab v-for="(item, index) in tabs" :title="item.title" :key="index" />
     </y-tabs>

     <!--
        支持平台
        1. @transition: 支持App、H5、微信、支付宝、字节跳动、飞书、QQ、快手
        2. @animationfinish: 字节跳动、飞书小程序不支持(在change事件中unlockDx)
      -->

     <swiper class="swiper" :current="activeIndex" @transition="onTransition" @animationfinish="onAnimationfinish" @change="swpierChange">
        <swiper-item v-for="(item, index) in tabs" :key="index">
            <view class="swiper-item-view" :style="{backgroundColor: item.color}">
                {{item.title}}
            </view>
        </swiper-item>
     </swiper>
 </view>
</template>
<script>
    export default {
        data() {
            return {
                tabs: [],
                activeIndex: 0,
            }
        },
        created() {
            this.tabs = Array.from({ length: 5 }, (o, i) => {
                return {
                    title: 'tab' + (i + 1),
                    color: this._getRandomColor()
                }
            });
        },
        methods: {
            //swiper滑动中
            onTransition(e) {
                this.$refs.tabs.setDx(e.detail.dx);
            },
            //swiper滑动结束
            onAnimationfinish(e) {
                this.activeIndex = e.detail.current;
                setTimeout(() => this.$refs.tabs.unlockDx(), 0)  //通知y-tabs解除对setDx()的锁定
            },
            swpierChange(e) {
                //  由于字节跳动、飞书不支持@animationfinish,因此在change事件中unlockDx
                // #ifdef MP-TOUTIAO || MP-LARK
                this.onAnimationfinish(e)
                // #endif
            },
            // 生成随机颜色
            _getRandomColor() {
                const rgb = [];
                for (let i = 0; i < 3; ++i) {
                    let color = Math.floor(Math.random() * 256).toString(16)
                    color = color.length == 1 ? '0' + color : color
                    rgb.push(color)
                }
                return '#' + rgb.join('');
            },
        },
    }
</script>
<style scoped>
.swiper {
    height: 300rpx;
}

.swiper-item-view {
    background-color: #007AFF;
    height: 300rpx;
    display: flex;
    justify-content: center;
    align-items: center;
    color: white;
    font-size: 50rpx;
}
</style>

Tabs Props

参数类型描述默认值说明
v-model number、string 绑定当前选中标签的标识符 0 即tab选中项的下标或者tab的name属性值
type string 样式风格类型 line 可选值为 text、card、button、line-button
color string 标签主题色 #0022AB
background string 标签栏背景色 #fff
title-active-color string 标题选中态颜色 -
title-inactive-color string 标题默认态颜色 -
wrap-style object 标签栏样式 案例 :透明导航栏下的滚动吸顶 -
direction string 标签栏的展示方位 horizontal 可选值:vertical
duration number、string 动画时间,单位秒 0.3 仅支持type为line、button、line-button的滑块移动的动画时间,标签内容切换时的转场动画时间、页面级滚动导航的内容定位动画时间。
shrink boolean 通过 shrink 属性可以开启收缩布局,开启后,所有的标签会向左侧收缩对齐 false
bar-width V2.0.1 number、string 滑块宽度,支持rpx、vh、vw等单位及calc()函数,也可传入'auto'值,默认px。 type为line,标签栏水平、垂直时宽度分别为20px、3px,其余为选中标签宽度;为auto时,代表滑块宽度自适应于选中标签宽度(仅在type='line'且bar-animate-mode='linear'、direction='horizontal'下生效) 仅支持type为line、button、line-button。
bar-height V2.0.1 number、string 滑块高度,支持度同bar-width type为line,标签栏水平、垂直时宽度分别为3px、20px,其余为选中标签高度;为auto时,代表滑块高度自适应于选中标签高度(仅在type='line'、bar-animate-mode='linear'、direction='vertical'下生效) 同bar-width
bar-style V2.0.1 object 滑块样式 - 同bar-width
bar-animate-mode V2.0.1 string 滑动切换tab内容时滑块的动画模式,默认为linear。可选值:worm(毛毛虫蠕动)、worm-ease(毛毛虫缓动效果)、none(不设置)。 linear 仅在 type='line'、direction='horizontal' 时有效。
可结合swiper组件使用,效果更好 案例 :新闻列表、与swiper组件联动
is-dynamic V2.0.1 boolean 标签切换后宽高是否有变化 true 当选中标签会放大文字、减少内间距时,开启该属性可避免滑块错位。(如果选中的标签文字使用‘font-size:20px;transition: all .2s’进行过渡变化,开启该属性仍旧会错位)
ellipsis boolean 是否省略过长的标题文字 true 标签栏水平展示时,如果标签数量未超过滚动阈值则生效,垂直则不限制。
scroll-threshold number、string 滚动阈值,标签数量超过阈值且总宽度超过标签栏宽度时开始横向滚动 5
scroll-to-center boolean 标签栏滚动时当前标签居中 true
is-lazy-render boolean 是否开启延迟渲染(首次切换到标签时才触发内容渲染) false
animated boolean 是否开启动画 true 用于开启标签栏滚动的过渡动画、切换标签内容时的转场动画、滚动导航下的内容定位动画
active-last V2.0.1 boolean 在滚动导航模式下,滚动到最后一个标签内容但其顶部未超过可视区域时,是否激活对应的标签项 false
before-change (name) => boolean | Promise 切换标签前的回调函数,返回 false 可阻止切换,支持返回 Promise - name为v-model绑定的值
内容手势滑动切换相关属性 :
swipeable boolean 是否开启手势滑动切换 案例 :滑动切换 | 新闻列表 | 滚动吸顶+左右滑动 false
swipe-animated boolean 是否开启标签内容滑动时的拖动动画 true swipeable为true、且is-lazy-render为false时有效
swipe-threshold number、string 滑动切换的滑动距离阈值,单位为px;表示开启手势滑动时,横向滑动多少px切换标签内容 120 快速滑动时不受限制
滚动吸顶相关属性 :
sticky boolean 是否使用粘性布局进行滚动吸顶 案例 :滚动吸顶 false
offset-top number、string 粘性布局下标签栏与顶部的最小距离,单位为 px 0 注意单位问题,如果是rpx,需要uni.upx2px转为px
z-index number、string 粘性布局下,标签栏的z-index值 99
sticky-threshold number、string 粘性布局吸顶的判断阈值 0 表示在页面滚动时,标签栏距屏幕顶部多少px时会触发吸顶函数进行吸顶判断 案例 :透明导航栏下的滚动吸顶
transparent boolean 页面滚动过程中,标题栏背景色是否透明渐变 案例 :透明渐变标题栏 false background属性值必须为rgba格式
transparent-offset number、string 标题栏背景色透明渐变的滚动距离 150 请保证标签内容的高度大于该值
滚动导航及侧边栏导航相关属性 :
scrollspy boolean 是否开启滚动导航;该模式下,内容将会平铺展示 案例 :滚动导航(页面级滚动) false 如果标签栏垂直展示,且内容平铺展示,就为侧边栏模式案例 :侧边栏导航(页面级滚动)-仿奶茶点单
page-scroll boolean 滚动导航模式下,内容区域是否跟随页面滚动 true 为false时,内容区域是放在scroll-view中实现的局部滚动,需自行设置标签页容器高度 案例 :侧边栏导航(区域滚动)-仿奶茶点单

Tab Props

参数类型描述默认值
name number、string 标签名称,作为匹配的标识符 标签的索引值
title string 标题 -
disabled boolean 是否禁用标签 false
dot boolean 是否在标题右上角显示小红点(优先级高于badge) false
badge number、string 图标右上角徽标的内容 -
badge-max-count V2.0.1 number、string 徽标数最大数字限制,超过这个数字将变成badgeMaxCount+,如果传空字符串则不设置 99
title-style object 自定义标题样式 -
title-class string 自定义标题类名 -
icon-type string 图标图案,为uniapp扩展组件(uni-ui)下的uni-icons的type值,customPrefix用法等同 -
icon-size number、string 图标大小 16
custom-prefix string 自定义图标 -
image-src string 图片路径 -
image-mode string 图片裁剪、缩放的模式,为uniapp内置组件->媒体组件—>image下的mode属性的可选值 -
position string 在有图标或图片的情况下,标题围绕它们所在的位置,可选值:left、top、bottom right

Tabs Events

事件名说明回调参数
click 点击标签时触发 name:标识符,title:标题
change 当前激活的标签改变时触发 name:标识符,title:标题
disabled 点击被禁用的标签时触发 name:标识符,title:标题
rendered 标签内容首次渲染时触发(仅在开启延迟渲染后触发) name:标识符,title:标题
sticky-change V2.0.1 吸顶时触发,仅在 sticky 模式下生效 { isFixed: 是否吸顶 }
loaded V2.0.6 组件内部初始化完成后调用 -
slide-change V2.0.9 内容页滑动时触发(仅barAnimateMode为linear、worm、worm-ease时有效) { dx:滑动距离; rate:当前滑动长度占滑动区域的比例;targetIndex:目标下标;}
slide-end V2.1.4 内容页滑动结束时触发(仅barAnimateMode为linear、worm、worm-ease时有效) { targetIndex: 目标下标 }

Tabs Slots

名称说明
nav-left 标题左侧内容
nav-right 标题右侧内容
title+下标 标签标题,插槽名默认为"title"+tab下标(注意:vue3中仅H5、app-vue有效,小程序端无效)
bar V2.0.1 滑块,可自定义滑块的内容(可以设置图片等)

Tab Slots

名称说明
default 标签页内容

Tabs Methods

通过 ref 可以获取到 Tabs 实例并调用实例方法(如果是vue3的组合式API,请使用vue3的写法);

方法名说明参数返回值
resize 外层元素大小、标签数量变化、滑块错位以及标签定位不准时,可以调用此方法来触发组件内部初始化进行调整 callback: 回调函数 -
reset 重置组件的一些状态,并调用了resize方法进行数据初始化 callback: 回调函数 -
scrollTo 滚动到指定的标签页,在滚动导航模式下可用 name: 标识符 -
setDx 设置滑块的水平偏移量(结合swiper组件的@transition事件,设置滑块的位置;经过测试,仅在App、H5、微信、支付宝、字节跳动、QQ小程序上有良好的效果) dx: swiper组件的e.detail.dx -
unlockDx 解除对setDx()的锁定(结合swiper组件的@animationfinish事件,在动画完成后不锁定setDx) - -

注意事项及常见问题

组件从隐藏状态切换到显示状态时,底部条位置错误?

Tabs 组件在挂载时,会获取自身的宽度,并计算出底部条的位置。如果组件一开始处于隐藏状态,则获取到的宽度永远为 0,因此无法展示底部条位置。

解决方法

方法一,如果是使用 v-show 来控制组件展示的,则替换为 v-if 即可解决此问题:

<!-- Before -->
<y-tabs v-show="show" />
<!-- After -->
<y-tabs v-if="show" />

方法二,调用组件的 resize 方法来主动触发重绘:

<y-tabs v-show="show" ref="tabs" />
this.$refs.tabs.resize();

标签选中后,样式变化可能会导致底部条错误

对于选中的标签,在放大字体的同时添加了过渡样式且有过渡时长,会使标签宽高发生变化,导致内部对于滑块的位置计算错误

解决方法

  • 可以考虑给每一个标签通过title-style设定固定宽高,避免标签文字放大后标签宽高变化
  • 如果没有过渡效果,设置is-dynamic即可解决滑块错误的问题,否则有过渡时长使用了该属性也难以保证滑块位置计算正确

如何解决上下滑动与左右滑动相冲突?

  • 直接给标签内容具体的高度,使用scroll-view实现局部滚动 案例 :滑动切换
  • 但是该方式会导致页面级的上拉加载与下拉刷新事件无法触发,因此需要去插件市场找类似的插件

切换标签时页面会闪烁?

标签切换后,显示的内容是异步请求获取数据进行渲染的,请给标签内容一个实际的最小高度,避免数据清空后高度回弹有导致页面闪烁

在u-popup组件中的y-tabs组件需resize一次

对于在u-popup中的tabs,在弹出层显示后需调用resize方法,避免内部计算错误 案例 :在Popup中的标签页

<u-popup :show="show" :round="10" @close="show = false" @open="open">
    <y-tabs ref="tabs" v-model="activeIndex">
    ...
    </y-tabs>
</u-popup>
export default{
    data(){
        return {
            show: false
        }
    },
    methods:{
        open(){
            this.show = true;
            setTimeout(()=> this.$refs.tabs.resize(),1000)
        }
    }
}

uni-data-select组件显示下拉选项时会被遮挡?

受限于tabs组件样式,内容区域使用了overflow:hidden,导致uni-data-select下拉选项被遮挡,需要给其父容器设置足够的高度才能完整显示

如何在自定义组件中修改y-tabs组件的样式?

在微信小程序端,在自定义组件中使用了y-tabs,需要设置styleIsolation: 'shared',否则在自定义组件中无法修改y-tabs的样式

如何修改y-tabs的样式:

  • 如果在自定义组件或页面中引入了y-tabs,使用 ::v-deepy-tabs所在的页面进行修改
  • 将要修改的样式放在全局样式中,但要给y-tabs赋予一个全局唯一的类名,避免全局样式污染
  • 仅在微信小程序端,如果自定义组件中使用了y-tabs并想修改其样式,需要在自定义组件上配置styleIsolation: 'shared'

    export default {
    options: {
        styleIsolation: 'shared'
    },

如何对激活标签的相邻标签设置样式 ?

直接可使用y-tab__prevy-tab__next案例 :组合导航(侧边栏导航+滚动导航)-仿京东商品分类

侧边栏导航、滚动导航模式

  • 两者内容区域的滚动方式通过pageScroll属性控制
  • 为false时,则表示内容页是放在scroll-view中实现的局部滚动 案例 :滚动导航(区域滚动) | 侧边栏导航(区域滚动)
  • 为true时,则表示内容区域是在页面上的,跟随页面滚动而滚动(页面级滚动) 案例 :滚动导航(页面级滚动) | 侧边栏导航(页面级滚动)
  • 如何取舍两者之间的使用,根据场景考虑,比如你的标签页上方有banner图,你需要在滚动过程中让标题栏浮动时,则需要页面级滚动,或者需要触发原生的上拉加载、下拉刷新事件也用该方式;
  • 如果你想两种模式在一定高度内滚动,那么就使用局部滚动。

如果标签栏仍出现滚动条,请在全局样式(可放在APP.vue引入的样式文件)中添加如下css:

// 隐藏scroll-view的滚动条
::-webkit-scrollbar {
    display: none;  
    width: 0 !important;  
    height: 0 !important;  
    -webkit-appearance: none;  
    background: transparent;  
}

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问