当前位置:   article > 正文

五种 自定义tabbar导航demo

自定义tabbar

使用场景:

例如:适用于app、微信小程序、H5的自定义底部导航 ,5种动态切换


问题描述

大部分小程序底部导航都是用原生的来写,但是如果遇到难缠的甲方,要各式各样的底部导航,这时候就不得不写自定义导航。但是 平时还是推荐用官方的底部导航,加载快,很少出bug,处理好的生命周期。

我这里是使用uniapp来写的,可以转任意app、微信小程序、H5端,讲一下基本逻辑。

项目结构分析:

在这里插入图片描述

第一步:

上面的是index.vue页面,用来引入5种底部导航, 根据tabBarType来切换不同的底部导航。
<template>
	<view>
		<!-- 翻滚效果 -->
		<view v-if="tabBarType == 1 ">
			<at-tab-roll :fixed-bottom="false"></at-tab-roll>
		</view>

		<!-- 凸起效果 -->
		<view v-if="tabBarType == 2 ">
			<at-tab-bulge :fixed-bottom="false"></at-tab-bulge>
		</view>

		<!-- 冒泡效果 -->
		<view v-if="tabBarType == 3 ">
			<at-tab-bubble :fixed-bottom="false"></at-tab-bubble>
		</view>

		<!-- 窗帘效果 -->
		<view v-if="tabBarType == 4 ">
			<at-tab-curtain :fixed-bottom="false"></at-tab-curtain>
		</view>

		<!-- 翻转效果 -->
		<view v-if="tabBarType == 5 ">
			<at-tab-overturn :fixed-bottom="false"></at-tab-overturn>
		</view>
	</view>
</template>

<script>
	import tabBarRoll from "../../components/at-tabBar/tab-bar-roll.vue" // 翻滚切换方式
	import tabBarBulge from "../../components/at-tabBar/tab-bar-bulge.vue" // 凸起切换方式
	import tabBarBubble from "../../components/at-tabBar/tab-bar-bubble.vue" // 冒泡切换方式
	import tabBarCurtain from "../../components/at-tabBar/tab-bar-curtain.vue" // 窗帘切换方式
	import tabBarOverturn from "../../components/at-tabBar/tab-bar-overturn.vue" // 翻转切换方式
	export default {
		components: {
			"at-tab-roll": tabBarRoll,
			"at-tab-bulge": tabBarBulge,
			"at-tab-bubble": tabBarBubble,
			"at-tab-curtain": tabBarCurtain,
			"at-tab-overturn": tabBarOverturn
		},
		data() {
			return {
				tabBarType: 1,  // tabbar类型依次是 (引入方式顺序)
			}
		},
		methods: {

		}
	}
</script>

<style lang="scss" scoped>

</style>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

第二步:

每个导航里面引入自定义页面,每切换下面的导航index, 会显示不同的组件页面。
<template>
	<view class="">
		<!-- 各组件页面 -->
		<view class="module">
			<view :style="{ display: current == 0 ? 'block' : 'none' }">
				<at-page1 ref="page1"></at-page1>
			</view>
			<view :style="{ display: current == 1 ? 'block' : 'none' }">
				<at-page2 ref="page2"></at-page2>
			</view>
			<view :style="{ display: current == 2 ? 'block' : 'none' }">
				<at-page3 ref="page3"></at-page3>
			</view>
			<view :style="{ display: current == 3 ? 'flex' : 'none' }">
				<at-page4 ref="page4"></at-page4>
			</view>
			<view :style="{ display: current == 4 ? 'flex' : 'none' }">
				<at-page5 ref="page5"></at-page5>
			</view>
		</view>
		
		<!-- tabbar组件 -->
		<view class="at-tab-bar">
			<view class="placeholder" v-if="fixedBottom"></view>
			<view class="bar h-flex-x h-flex-5" :class="{'fixed':fixedBottom}">
				<view class="item" v-for="(item,index) in  tabList" :key="index" :class="{'active':current == index,'recover':prevIndex == index}" @tap="change(index)">
					<view>
						<view class="h-flex-x h-flex-center">
							<image style="width: 48rpx;height: 48rpx;" :src="item.icon" mode=""></image>
						</view>
						<view class="h-flex-x h-flex-center">
							{{item.text}}
						</view>
					</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	import atPage1 from '@/components/at-page/at-page1.vue';
	import atPage2 from '@/components/at-page/at-page2.vue';
	import atPage3 from '@/components/at-page/at-page3.vue';
	import atPage4 from '@/components/at-page/at-page4.vue';
	import atPage5 from '@/components/at-page/at-page5.vue';

	export default {
		// 翻滚切换方式
		name: "atTabBarRoll",
		props: {
			// 固定底部
			fixedBottom: {
				type: Boolean,
				default: true
			}
		},
		components: {
			"at-page1":atPage1,
			"at-page2":atPage2, 
			"at-page3":atPage3, 
			'at-page4':atPage4, 
			"at-page5":atPage5, 
		},
		data() {
			return {
				prevIndex: -1,
				current: 0,
				tabList: [{
						"icon": "../../static/tabbar/home_no.png",
						"iconSelected": "../../static/tabbar/home.png",
						"text": "首页"
					},
					{
						"icon": "../../static/tabbar/order_no.png",
						"iconSelected": "../../static/tabbar/home.png",
						"text": "翻滚1"
					},
					{
						"icon": "../../static/tabbar/order_no.png",
						"iconSelected": "../../static/tabbar/home.png",
						"text": "翻滚2"
					},
					{
						"icon": "../../static/tabbar/store_no.png",
						"iconSelected": "../../static/tabbar/home.png",
						"text": "翻滚3"
					},
					{
						"icon": "../../static/tabbar/my_no.png",
						"iconSelected": "../../static/tabbar/home.png",
						"text": "翻滚4"
					},
				],
			};
		},
		methods: {
			change(index) {
				console.log(index);
				let that = this;
				if (that.current == index) return;
				that.prevIndex = that.current;
				that.current = index;
				
				if (that.current == 0) {
					that.$refs.page1.ontrueGetList();
				} else if (that.current == 1) {
					that.$refs.page2.ontrueGetList();
				} else if (that.current == 2) {
					that.$refs.page3.ontrueGetList();
				} else if (that.current == 3) {
					that.$refs.page4.ontrueGetList();
				} else if (that.current == 4) {
					that.$refs.page5.ontrueGetList();
				}
			}
		}
	}
</script>

<style lang="scss" scoped>
	@import "./at-flex.scss";
	@import "./tab-bar.scss";
	
	.module{
		display: flex;
		align-items: center;
		justify-content: center;
		// background: pink;
	}
	.at-tab-bar {
		padding: 30rpx 0 0;
		width: 100%;
		height: 160rpx;
		position: fixed;
		bottom: 0;
		left: 0;
		background-color: #82a9f2;
		.item {
			height: 100rpx;
			position: relative;
			overflow: hidden;

			>view {
				height: 200%;

				>view {
					height: 50%;
					color: #0043e3;
					font-size: 30rpx;
				}
			}

			&.active {
				&::before {
					content: '';
					display: block;
					position: absolute;
					width: 90rpx;
					height: 90rpx;
					box-sizing: border-box;
					border-color: #0043e3;
					border-style: solid;
					border-width: 2px;
					border-radius: 50%;
					top: 5rpx;
					left: 50%;
					margin-left: -45rpx;
					z-index: 1;

					animation: scale 0.3s ease 0s 1 normal;
					animation-fill-mode: forwards;
				}

				&::after {
					content: '';
					display: block;
					background-color: #0043e3;
					width: 4px;
					height: 4px;
					border-radius: 50%;
					position: absolute;
					bottom: 3px;
					left: 50%;
					margin-left: -2px;
					z-index: 2;
					opacity: 0;

					animation: fide-in 0.5s ease 0.3s 1 normal;
					animation-fill-mode: forwards;
				}

				>view {
					animation: translate 0.4s ease 0.3s 1 normal;
					// transform:translateY(-100rpx);
					animation-fill-mode: forwards;
				}
			}

			&.recover {
				>view {
					animation: recover 0.3s ease 0s 1 normal;
				}
			}
		}
	}

	// 恢复默认
	@keyframes recover {
		from {
			transform: translateY(-100rpx);
		}

		to {
			transform: translateY(0);
		}
	}

	// 转换移动
	@keyframes translate {
		from {
			transform: translateY(0);
		}

		to {
			transform: translateY(-100rpx);
		}
	}

	// 圆圈缩放
	@keyframes scale {
		0% {
			transform: scale(0, 0);
			opacity: 0;
			border-width: 2px;
		}

		50% {
			opacity: 0.5;
			border-width: 5px;
		}

		100% {
			transform: scale(0.95, 0.95);
			opacity: 0;
			border-width: 0px;
		}
	}

	// 淡入
	@keyframes fide-in {
		from {
			transform: scale(0, 0);
			opacity: 0;
		}

		to {
			transform: scale(1, 1);
			opacity: 1;
		}
	}
</style>


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264

最后:

如果你看不太懂,没关系,附上个人gitee 项目地址: https://gitee.com/deer-stars/btm-seniorNavigation.git

如果文章对你帮助,请点个赞支持一下。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/69358
推荐阅读
相关标签
  

闽ICP备14008679号