You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

23 KiB

y-tabs 标签页组件

注意:

  • 2.0.1为非兼容性升级,重命名了诸多样式以及提供的属性名,也移除了部分属性及事件,如无必要,请勿升级。
  • 如果不小心升级可以在示例项目中的yTabsVersion目录中找到之前的版本。
  • 从2.0.1版本开始对于吸顶以及滚动导航定位标签的实现已调整了内部逻辑因此无需在页面中的onPageScroll生命周期调用this.$emit("onPageScroll",e)
  • 新增bar-animate-mode属性用于设置滑块切换的动画模式
  • 新增bar-style属性用于设置滑块样式
  • 新增bar插槽用于自定义滑块的内容
  • line-width、line-height属性名改为bar-width、bar-height
  • 移除部分tabs Props: tab-click-scroll-top、navHeight 、navWidth 、contentHeight
  • 请注意部分属性默认值的调整;
  • 移除scroll事件如果有用到该事件判断标签栏是否吸顶请替换为sticky-change事件
  • 新增sticky-change事件该事件传递了{isFixed}参数,用于说明标签栏是否吸顶固定;
  • 移除'滚动吸顶+滑动切换'案例
  • 新增'与swiper组件联动'案例;
  • 在QQ/百度/字节跳动/飞书/快手小程序中自定义组件在渲染时会比App/H5端多一级节点导致标签内容样式失效需在组件上添加".y-tab-virtual"的样式;


Tips
  • 代码更新于2023/08/30 13:57若有问题请下载最新代码示例项目中的uni_modules/y-tabs是最新的
  • 请保证HBuilderX正式版为 v3.4.18、Alpha版为 v3.5.2。
  • 该插件使用的预编译需要自行安装less插件。
  • 如果发现组件有bug或者不完善可以留言交流发邮箱18508420370@163.com或QQ1431948195更方便看到。
  • 点击右上角的“使用HubilderX导入示例项目”按钮下载示例项目运行并查看效果项目中内置不少案例。
  • 也可以扫描右侧图片中的微信小程序码查看示例效果(由于微信小程序审核较严,无法发布新的版本,因此案例比较老了,最好导入示例项目查看)。
支持的平台:
  • H5、app-vue、微信、支付宝、钉钉、百度、字节、QQ、飞书、快手小程序可用其他平台可自行测试。
  • 暂不支持nvue。
使用方式:
1、导入插件

该组件符合uni_modules规范使用HbuilderX导入插件到项目根目录下的uni_modules文件夹中。

2、template中使用

符合uni_modules规范直接在页面中使用无需单独引入注册组件。

普通案例

  • 注意在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的支持平台
  • lineAnimateMode="worm",设置底部条切换类似毛毛虫蠕动的效果
  • 经过测试仅支持App、H5、微信、支付宝、字节跳动、QQ、快手小程序
<template>
 <view>
	 <y-tabs ref="tabs" v-model="activeIndex" lineAnimateMode="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="onChange">
	 	<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()的锁定
			},
			onChange(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 绑定当前选中标签的标识符即tab选中项的下标或者tab的name属性值 0
type string 样式风格类型,可选值为 text、card、button、line-button line
color string 标签主题色 #0022AB
background string 标签栏背景色 #fff
title-active-color string 标题选中态颜色 -
title-inactive-color string 标题默认态颜色 -
wrap-style object 标签栏样式 案例 :透明导航栏下的滚动吸顶 -
direction string 标签栏的展示方位,可选值vertical。 horizontal
duration number、string 动画时间,单位秒 0.3 仅支持type为line、button、line-button的滑块移动的动画时间标签内容切换时的转场动画时间、页面级滚动导航的内容定位动画时间。
shrink boolean 通过 shrink 属性可以开启收缩布局,开启后,所有的标签会向左侧收缩对齐 false
bar-width V2.0.1 number、string 滑块宽度默认单位为px, 支持数字、rpx、vh、vw等单位及calc() 函数。 标签栏水平/垂直展示时,type为line,宽度默认为20px/3px;而type为button、line-button时,宽度默认为选中标签宽度。 仅支持type为line、button、line-button。使用了插槽bar则无效
bar-height V2.0.1 number、string 滑块高度默认单位为px支持数字、rpx、vh、vw等单位及calc() 函数。 标签栏水平/垂直展示时,type为line,高度默认为3px/20px, 而type为button、line-button时,宽度默认为选中标签高度。 仅支持type为line、button、line-button。使用了插槽bar则无效
bar-style V2.0.1 object 滑块样式 - 仅支持type为line、button、line-button。使用了插槽bar则无效
bar-animate-mode V2.0.1 string 滑动切换tab内容时滑块的动画模式默认值为linear即切换tab时滑块宽度保持不变线性运动。可选值为worm(毛毛虫蠕动)、worm-ease(毛毛虫缓动效果)、none(不设置)。 linear 仅支持type为line。
可结合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 是否开启延迟渲染(首次切换到标签时才触发内容渲染) true
animated boolean 是否开启动画 true 用于开启标签栏滚动的过渡动画、切换标签内容时的转场动画、滚动导航下的内容定位动画
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 bar-animate-mode为worm、worm-ease时无效worm时阈值默认为标签内容的一半不可设置
滚动吸顶相关属性 :
sticky boolean 是否使用粘性定位布局进行滚动吸顶 案例 :滚动吸顶 false
offset-top number 粘性定位布局下标签栏与顶部的最小距离,单位为 px 0
z-index number 粘性定位布局下标签栏的z-index值 99
transparent boolean 页面滚动过程中,标题栏背景色是否透明渐变 案例 :透明渐变标题栏 false background属性值必须为rgba格式
transparent-offset number 标题栏背景色透明渐变的滚动距离 150 请保证标签内容的高度大于该值
sticky-threshold number 粘性布局的判断阈值:表示在页面滚动过程中,标签栏距屏幕顶部多少px时触发吸顶函数进行吸顶判断 案例 :透明导航栏下的滚动吸顶 0
滚动导航及侧边栏导航相关属性 :
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 图标大小 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 组件内部初始化完成后调用 -
Tabs Slots
名称说明
nav-left 标题左侧内容
nav-right 标题右侧内容
title+下标 标签标题插槽,插槽名默认为"title"+tab下标注意vue3中仅H5、app-vue有效小程序端无效
bar V2.0.1 滑块插槽,可自定义滑块的内容(可以设置图片等)
Tab Slots
名称说明
default 标签页内容
Tabs 方法
通过 ref 可以获取到 Tabs 实例并调用实例方法;
方法名说明参数返回值
resize 外层元素大小、标签数量变化、滑块错位以及标签定位不准时,可以调用此方法来触发组件内部初始化进行调整 callback: 回调函数 -
reset 重置组件的一些状态并调用了resize方法进行数据初始化 callback: 回调函数 -
scrollTo 滚动到指定的标签页,在滚动导航模式下可用 name: 标识符 -
setDx 设置滑块的水平偏移量结合swiper组件的@transition事件设置滑块的位置经过测试仅在App、H5、微信、支付宝、字节跳动、QQ小程序上有良好的效果 dx: swiper组件的e.detail.dx -
unlockDx 解除对setDx()的锁定结合swiper组件的@animationfinish事件在动画完成后不锁定setDx - -
注意事项及常见问题
1. 如何解决上下滑动与左右滑动相冲突?
  • 直接给标签内容具体的高度使用scroll-view实现局部滚动 案例 :滑动切换
  • 但是这种方式会无法触发页面级的上拉加载与下拉刷新事件,因此需要去插件市场找类似的插件
2.如果为侧边栏导航,需要对当前标签附近的两个标签项设置样式?
直接可使用"y-tab\_\_prev"与"y-tab\_\_next" 类 案例 :组合导航(侧边栏导航+滚动导航)-仿京东商品分类
3.侧边栏导航、滚动导航:
  • 两者内容区域的滚动方式通过pageScroll属性控制
  • 为false时则表示内容区域是放在scroll-view中实现的局部滚动 案例 :滚动导航(区域滚动) | 侧边栏导航(区域滚动)
  • 为true时则表示内容区域是屏幕在页面上的跟随页面滚动而滚动(页面级滚动) 案例 :滚动导航(页面级滚动) | 侧边栏导航(页面级滚动)
  • 如何取舍两者之间的使用具体就要看使用场景了比如你的标签页上方有banner图你需要在滚动过程中让标题栏浮动时则需要页面级滚动,或者需要触发原生的上拉加载、下拉刷新事件也用该方式;
  • 如果你想两种模式在一定高度内滚动,那么就使用默认的局部滚动实现方式。
4.切换标签时页面会闪烁?
  • 如果切换标签之后显示的内容是通过接口拿到的数据进行渲染的,请给标签内容一个实际的高度,避免数据清空后导致页面高度回弹
5.如果给选中的标签,在放大字体的同时添加了过渡样式且有过渡时长,会使标签宽高发生变化,导致内部对于滑块的位置计算错误
  • 可以考虑给每一个标签通过titleStyle设定固定宽高避免标签文字放大后标签宽高变化
  • 如果没有过渡效果设置is-dynamic即可解决滑块错误的问题
6.对于嵌在弹出层如u-popup组件中的y-tabs在弹出层显示后需要调用resize方法避免内部计算错误 案例 在Popup中的标签页
// templete
<u-popup :show="show" :round="10" @close="show = false" @open="open">
	<y-tabs ref="tabs" v-model="activeIndex">
	...
	</y-tabs>
</u-popup>

// script 
export default{
	data(){
		return {
			show: false
		}
	},
	methods:{
		open(){
			this.show = true;
			setTimeout(()=>{
				this.$refs.tabs.resize();
			},1000)
		}
	}
}