uniapp自定义tabbar(支持中间凸起,角标,动态隐藏tab,全端适用)

这篇具有很好参考价值的文章主要介绍了uniapp自定义tabbar(支持中间凸起,角标,动态隐藏tab,全端适用)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

在使用uniapp进行开发时,tabbar是我们使用的很频繁的一个组件,但是在特定的平台会有一些使用上的限制,无法通过一套代码来做通用平台的适配。比如说中间按钮凸起,动态隐藏某个tab(不同角色展示不同功能),使用字体图标,数字角标等,这些功能不是所有平台都支持。今天我们就用一套代码来实现这些功能全端支持。

思路

实现思路就是通过通过自定义view来实现我们这个tabbar功能,然后页面通过组件来展示。通过点击不同的tab来显示不同的组件来达到模拟原生tabbar切换效果。那有些人要问了,你咋知道我项目中有多少个tab,这些tab叫什么名字了?那这里就可以利用uniapp提供的组件easycom模式来解决这些问题,只要我们设置好组件的限制个数和提前占位名称,这些问题就迎刃而解。

实现

1、我们现在components(没有就新建一个components目录)目录下新建一个文件夹(我这里叫ctab),然后分别新建一个vue组件和一个js文件。组件可以让我们在其他地方引用,js文件主要是做配置。
uniapp自定义tabbar,uniapp,uni-app,javascript,前端,自定义tabbar
2、新建tab组件,我们组件最多限制5个tab组件,然后需要通过easycom占位来实现,所以你需要几个tab组件就在components目录下建几个组件命名为ctabx。如下所示,我这里要展示三个tab:
uniapp自定义tabbar,uniapp,uni-app,javascript,前端,自定义tabbar
特别注意这里的tab组件命名一定要符合easycom规范,不然可能会引起组件引用错误。
这里示例一个ctab1写法:

<template>
	<view style="width: 750rpx;height: 300rpx;background-color: red;">
		首页
	</view>
</template>
<script>
	export default {
		name: "ctab1",
		data() {
			return {};
		},
		mounted() {},
		methods: {}
	}
</script>
<style>
</style>

3、tabbar组件ctab.vue实现,这里就直接上代码了,直接copy就能使用,关键地方已加上注释

<template>
	<view>
		<!--中间按钮凸起模式-->
		<block v-if="midBtn && midBtn.show">
			<!--凸起模式最多展示四个-->
			<block v-if="tabs.length < 4">
				<ctab1 v-show="sindex == 0"></ctab1>
				<ctab2 v-show="sindex == 2"></ctab2>
			</block>
			<block v-else="tabs.length >= 4">
				<ctab1 v-show="sindex == 0"></ctab1>
				<ctab2 v-show="sindex == 1"></ctab2>
				<ctab3 v-show="sindex == 3"></ctab3>
				<ctab4 v-show="sindex == 4"></ctab4>
			</block>
			<view class="tabbar">
				<!--中间按钮凸起模式tab为3个或者5-->
				<view class="tab-item"
					  v-for="(item,index) in (tabs.length < 4 ? 3 : 5)"
					  :key="item"
					  @click="handleTabClick(index)">
					  <!--中间按钮凸起显示图片和文字-->
					<block v-if="index == floor">
						<view :style="'bottom: calc('+(midBtn.offset ? midBtn.offset : '50rpx')+' + env(safe-area-inset-bottom));width: '+(midBtn.width ? midBtn.width : '150rpx')+';height: '+(midBtn.width ? midBtn.width : '150rpx')+';background:'+(midBtn.background ? midBtn.background : '#ffffff')"
								class="mid-btn">
							<image :src="midBtn.icon"
								   :style="'width: '+(midBtn.iconwidth ? midBtn.iconwidth : midBtn.width)+';height: '+(midBtn.iconheight ? midBtn.iconheight : midBtn.width)+';'"
								   @click="handleMidBtn"/>
						</view>
						<text class="mid-text"
							  :style="'margin-top: '+(midBtn.textoffset ? midBtn.textoffset : '50rpx;')"
							  v-show="midBtn.showtext">{{midBtn.text}}</text>
					</block>
					<!--普通tab这里需要注意index选择-->
					<block v-else>
						<view class="c-tab-item">
							<text :class="'tab-iconfont iconfont '+(tabs[index < floor ? index : index-1].iconfont)"
								  :style="'color:'+(sindex == index ? scolor : color)"
								  v-if="tabs[index < floor ? index : index-1].iconfont"/>
							<image :src="sindex == index ? tabs[index < floor ? index : index-1].iconSelect : tabs[index < floor ? index : index-1].icon"
								   class="tab-icon"
								   v-else/>
							<text class="tab-text"
								  :style="'color:'+(sindex == index ? scolor : color)">{{tabs[index < floor ? index : index-1].text}}</text>
							<view class="corner"
								  v-show="tabs[index < floor ? index : index-1].mark > 0">{{tabs[index < floor ? index : index-1].mark > 99 ? '99+' : tabs[index < floor ? index : index-1].mark}}</view>
						</view>
					</block>
				</view>
			</view>
		</block>
		<!--普通模式-->
		<block v-else>
			<block v-if="tabs.length == 1">
				<ctab1 v-show="sindex == 0 && tabs[0].show"></ctab1>
			</block>
			<block v-else-if="tabs.length == 2">
				<ctab1 v-show="sindex == 0 && tabs[0].show"></ctab1>
				<ctab2 v-show="sindex == 1 && tabs[1].show"></ctab2>
			</block>
			<block v-else-if="tabs.length == 3">
				<ctab1 v-show="sindex == 0 && tabs[0].show"></ctab1>
				<ctab2 v-show="sindex == 1 && tabs[1].show"></ctab2>
				<ctab3 v-show="sindex == 2 && tabs[2].show"></ctab3>
			</block>
			<block v-else-if="tabs.length == 4">
				<ctab1 v-show="sindex == 0 && tabs[0].show"></ctab1>
				<ctab2 v-show="sindex == 1 && tabs[1].show"></ctab2>
				<ctab3 v-show="sindex == 2 && tabs[2].show"></ctab3>
				<ctab4 v-show="sindex == 3 && tabs[3].show"></ctab4>
			</block>
			<block v-else-if="tabs.length >= 5">
				<ctab1 v-show="sindex == 0 && tabs[0].show"></ctab1>
				<ctab2 v-show="sindex == 1 && tabs[1].show"></ctab2>
				<ctab3 v-show="sindex == 2 && tabs[2].show"></ctab3>
				<ctab4 v-show="sindex == 3 && tabs[3].show"></ctab4>
				<ctab5 v-show="sindex == 4 && tabs[4].show"></ctab5>
			</block>
			<view class="tabbar">
				<view class="tab-item"
					  v-for="(item,index) in tabs"
					  :key="item.text"
					  v-show="item.show"
					  @click="handleTabClick(index)">
					<view class="c-tab-item">
						<text :class="'tab-iconfont iconfont '+(item.iconfont)"
							  :style="'color:'+(sindex == index ? scolor : color)"
							  v-if="item.iconfont"/>
						<image :src="sindex == index ? item.iconSelect : item.icon"
							   class="tab-icon"
							   v-else/>
						<text class="tab-text"
							  :style="'color:'+(sindex == index ? scolor : color)">{{item.text}}</text>
						<view class="corner"
							  v-show="item.mark > 0">{{item.mark > 99 ? '99+' : item.mark}}</view>
					</view>
				</view>
			</view>
		</block>
	</view>
</template>

<script>
	//读取配置
	import ctabbar from './ctab-config.js'
	export default {
		name: "ctab",
		data() {
			return {
				tabs: [],
				color: '',
				scolor: '',
				midBtn: {},
				sindex: 0,
				floor: -1,//midButton开启时使用
			}
		},
		mounted() {
			let tabbar = ctabbar.tabbar
			this.color = tabbar.color
			this.scolor = tabbar.selectcolor
			if(tabbar.midButton && tabbar.midButton.show && tabbar.tabs.length < 2){
				throw new Error('midButton模式开启,配置tab选项不能少于2个')
			}
			if(tabbar.midButton && tabbar.midButton.show){
				let mlength = tabbar.tabs.length < 4 ? 3 : 5
				this.floor = Math.floor(mlength/2)
			}
			//普通模式,设置选中的tab项
			let tablen = tabbar.tabs.length
			if(!tabbar.midButton.show){
				if(!tabbar.tabs[0].show){
					this.sindex ++
					if(tablen >= 2 && !tabbar.tabs[1].show){
						this.sindex ++
						if(tablen >= 3 && !tabbar.tabs[2].show){
							this.sindex ++
							if(tablen >= 4 && !tabbar.tabs[3].show){
								this.sindex ++
								if(tablen >= 5 && !tabbar.tabs[4].show){
									throw new Error('tab不能全部隐藏')
								}
							}
						}
					}
				}
			}
			if(tabbar.tabs.length <= 5){
				this.tabs = tabbar.tabs
			}else {
				this.tabs = tabbar.tabs.slice(0,5)
			}
			this.midBtn = tabbar.midButton
		},
		methods: {
			setTheme(color){
				this.scolor = color
				this.midBtn.background = color
			},
			//设置tab隐藏和显示,midButton模式失效
			setTabVisible(index,visible){
				if(this.tabs[index]){
					this.tabs[index].show = visible
				}
			},
			//设置角标
			setCorner(index,num){
				if(this.tabs[index]){
					this.tabs[index].mark = num
				}
			},
			handleTabClick(tab){
				if(this.midBtn && this.midBtn.show){
					if(tab == this.floor){
						return
					}
				}
				this.sindex = tab
				let rindex = tab
				if(this.midBtn && this.midBtn.show){
					if(tab > this.floor){
						rindex --
					}
				}
				this.$emit('tabClick',rindex)
			},
			handleMidBtn(){
				this.$emit('midClick')
			}
		}
	}
</script>

<style>
	/*这里引入字体图标,如果使用字体图标的话*/
	@import '@/common/font/iconfont.css';
	.tabbar {
		position: fixed;
		z-index: 99;
		width: 100%;
		height: 100rpx;
		background-color: #ffffff;
		bottom: 0;
		left: 0;
		box-shadow: 0rpx 4rpx 8rpx 0rpx rgba(0,0,0,0.5);
		border-radius: 0px 0px 0px 0px;
		opacity: 1;
		display: flex;
		flex-direction: row;
		align-items: center;
		justify-content: center;
		padding-bottom: constant(safe-area-inset-bottom);
		padding-bottom: env(safe-area-inset-bottom);
		box-sizing: content-box;
	}
	.tab-item {
		flex: 1;
		height: 100rpx;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
	}
	.c-tab-item {
		height: 120rpx;
		display: flex;
		flex-direction: column;
		width: 120rpx;
		align-items: center;
		justify-content: center;
		position: relative;
	}
	.tab-icon {
		width: 45rpx;
		height: 45rpx;
	}
	.tab-iconfont {
		font-size: 45rpx;
		font-weight: bold;
	}
	.tab-text {
		font-size: 26rpx;
		color: #333333;
		margin-top: 5rpx;
	}
	.mid-btn {
		position: absolute;
		display: flex;
		flex-direction: row;
		justify-content: center;
		align-items: center;
		background-color: red;
		border-radius: 50%;
	}
	.mid-text {
		font-size: 25rpx;
		color: #999999;
	}
	.corner {
		text-align: center;
		width: 45rpx;
		height: 45rpx;
		position: absolute;
		background-color: red;
		border-radius: 50%;
		color: white;
		font-size: 20rpx;
		font-weight: bold;
		top: 5rpx;
		right: 0;
		display: flex;
		flex-direction: row;
		justify-content: center;
		align-items: center;
	}
</style>

4、配置文件如下:

var tabbar = {
	/*开启midButton模式时取前两个或者前四个显示,其他忽略*/
	midButton: {
		show: true,//是否是中间凸起模式
		width: '153rpx',//不填默认150rpx 中间按钮大小
		iconwidth: '67rpx',//不填默认150rpx 中间图标大小
		iconheight: '60rpx',
		offset: '40rpx',//不填默认50rpx
		background: '#F7D456',//中间按钮背景颜色
		text: '拍一拍',
		textoffset: '50rpx',//不填默认50rpx
		showtext: false,
		icon: '../../static/tabbar/camera.png'
	},
	color: '#333333',//未选中颜色
	selectcolor: '#F7D456',//选中颜色
	/*tabs最多5个,超过5个超过的部分会被忽略,show属性用来控制tab显示隐藏,midButton开启时失效,iconfont优先,没有就使用icon*/
	tabs: [{
		icon: '../../static/tabbar/main_tab_home_normal.png',
		iconSelect: '../../static/tabbar/main_tab_home_select.png',
		text: '首页',
		iconfont: '',
		show: true,
		mark: 0//角标数量,小于等于0不显示
	}, {
		icon: '../../static/tabbar/main_tab_task_normal.png',
		iconSelect: '../../static/tabbar/main_tab_task_select.png',
		text: '任务',
		iconfont: '',
		show: true,
		mark: 100
	}, {
		icon: '../../static/tabbar/main_tab_my_normal.png',
		iconSelect: '../../static/tabbar/main_tab_my_select.png',
		text: '我的',
		iconfont: 'icon-wode',//注意配置字体图标会优先使用字体图标,这里是示例
		show: true,
		mark: 9
	}]
}

module.exports = {
	tabbar
}

5、使用示例:

<template>
	<ctab @midClick='midClick'
		  @tabClick='tabClick'
		  ref="ctab"/>
</template>

<script>
	export default {
		data() {
			return {
				
			}
		},
		onLoad() {
			
		},
		methods: {
			//凸起按钮点击事件
			midClick(){
				console.log('midClick')
			},
			//tab切换点击事件
			tabClick(tab){
				console.log('tabClick',tab)
			}
		}
	}
</script>

<style>
	page {
		width: 100%;
		height: 100%;
	}
	
</style>

6、到这里我们自定义tabbar就完成了,通过修改配置文件中的midButton中的show属性来开启是否中间按钮凸起,接下来我们看下效果。
midButton开启:
uniapp自定义tabbar,uniapp,uni-app,javascript,前端,自定义tabbar
普通模式:
uniapp自定义tabbar,uniapp,uni-app,javascript,前端,自定义tabbar
再普通模式下,我们可以通过配置或者动态修改tabs中tab obj中的show属性来动态形式和隐藏某个tab,我们这里配置第一个tab为隐藏:

...
tabs: [{
		icon: '../../static/tabbar/main_tab_home_normal.png',
		iconSelect: '../../static/tabbar/main_tab_home_select.png',
		text: '首页',
		iconfont: '',
		show: false,//隐藏第一个tab
		mark: 0//角标数量,小于等于0不显示
	}, {
		icon: '../../static/tabbar/main_tab_task_normal.png',
		iconSelect: '../../static/tabbar/main_tab_task_select.png',
		text: '任务',
		iconfont: '',
		show: true,
		mark: 100
	}, {
		icon: '../../static/tabbar/main_tab_my_normal.png',
		iconSelect: '../../static/tabbar/main_tab_my_select.png',
		text: '我的',
		iconfont: '',
		show: true,
		mark: 9
	}]
...

效果图如下:
uniapp自定义tabbar,uniapp,uni-app,javascript,前端,自定义tabbar
7、到这里我们的自定义tabbar就完成了,剩下的就是在tab组件中实现我们各个页面的逻辑。我们通过配置文件可以轻松的使用一个套代码实现tabbar中间按钮凸起、数字角标、动态隐藏、自定义mask覆盖tabbar(需要自己控制好层级),字体图标等功能,并且全端适用。

尾巴

本次内容就这么多,欢迎给我点赞和关注,有什么疑问欢迎给我留言,谢谢!文章来源地址https://www.toymoban.com/news/detail-781934.html

到了这里,关于uniapp自定义tabbar(支持中间凸起,角标,动态隐藏tab,全端适用)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • uniapp - [ H5 网页 / App ] 高性能 tabbar 底部菜单凸起效果,原生系统自定义底部菜单不卡顿、切换页面不闪烁、自动缓存页面(底部菜单中间自定义一个图片并悬浮起来)

    网上有很多自定义 tabbar 底部菜单的教程,但终归是组件形式,避免不了切换页面卡顿、闪屏闪烁、各平台不兼容等一系列问题。 本文 基于 uniapp 系统原生 tabbar 底部菜单,植入一个向上凸起的 “图片” 菜单,并支持点击触发事件, 您可以直接复制代码,换个中间凸起的菜

    2024年02月21日
    浏览(40)
  • 微信小程序自定义 底部 tabbar (中间凸起)

    在与 pages 文件夹同级的地方新建 custom-tab-bar 文件夹,并新建 index.wxml 、index.wxss 、index.js 、index.json 四个文件夹 注意路径!!! 复制后会报错,把图片和页面路径改掉就好了!!! 提示: 不要无脑复制,复制到自己的项目中后记得更改图片、页面路径!!! 如需自定义 头

    2024年02月20日
    浏览(36)
  • 微信小程序自定义tabbar【中间凸起样式】

    效果预览 微信开发文档:自定义tabBar 一、配置信息 在 app.json 中的 tabBar 中指定 custom 字段为 true【允许使用自定义 tabBar】 在所有 tab 页 json 中申明usingComponents 项,或者在 app.json 中全局开启 在 list 中指定自己需要 tab 示例 二、添加 tabBar 代码文件 在代码根目录下添加custom-

    2024年02月10日
    浏览(34)
  • uniapp自定义tabbar——中间特殊按钮

    pages.json 样式覆盖 App.vue 消息设置角标 在三个主页面分别引入组件 传入对于的索引即可

    2024年02月10日
    浏览(27)
  • UNIAPP原生TABBAR设置并添加数字角标或小红点提示

    UNIAPP原生TABBAR设置并添加数字角标或小红点提示 如下图所示: 如下图所示: 在我的界面如果有待用户阅读条数大于0,则在该tabbar(我的)顶部显示小红点。 在页面加载的时候调用。 支付宝开发者工具上面的红点样式比较丑,但是不用调整。真机调试样式会准确些也相对好看

    2024年02月12日
    浏览(48)
  • 微信小程序底部tabbar自定义 实现凸起+透明底部效果

    先上图看效果: 步骤: 1、在文件根目录下创建一个文件夹:custom-tab-bar并分别创建 (js,json,wxml,wxss)类型文件 2、在pages.json中设置tabbar中的custom为true(true自定义,false默认系统) 3、index.js代码如下:

    2024年02月09日
    浏览(43)
  • 前端Vue自定义tabbar底部tabbar凸起tabbar兼容苹果刘海屏小程序和APP

    前端Vue组件化开发:自定义tabbar组件的设计与实现  兼容苹果刘海屏小程序和APP 摘要: 随着前端开发技术的不断发展,组件化开发成为了提高开发效率和降低维护成本的有效手段。本文将介绍一款基于Vue的前端自定义tabbar组件的设计与实现,该组件具有单独开发、单独维护

    2024年02月11日
    浏览(51)
  • uniapp自定义动态tabbar及全局挂载底部自定义组件

    本篇文章解决的问题如下: 1:uniapp在pages.json中定义的tabbar,在非tabbar页面的时候不会显示,所以自定义了一个tabbar组件。(注意是自定义组件不是官方的custom-tab-bar组件) 2:有些tabbar需要动态变化,会员登陆前和会员登陆后可能会需要在tabbar上面展示不同的项目,所以要做

    2024年02月02日
    浏览(42)
  • uniapp+uView2.0实现自定义动态tabbar

         1.需求说明      2.实现原理说明      3.实现过程          3.1集成uView2.0          3.2 自定义tabbar          3.3 vuex定义tabbar共享信息          3.4 tabbar显示个数控制      要求不同时间显示不同的tabbar.点击不同的tabbar跳转到不同的页面,能随时实现tabb

    2023年04月18日
    浏览(25)
  • 基于自定义组件实现微信小程序动态tabBar,根据不同用户角色显示不同底部tabBar,支持自由组合总数超过5个(更新版)

    背景 在开发小程序过程中,有个需求是,小程序底部的tabBar需要根据不同用户角色显示不同底部导航。此时就需要用到自定义底部导航 custom-tab-bar。 上次发文是组合显示4个底部tabBar导航,很多小伙伴评论说组合超过5个怎么办。他们的需求总数超过5个了。 现在我在这里更新

    2024年01月17日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包