其他分享
首页 > 其他分享> > tabbar

tabbar

作者:互联网

TabBar 的实现功能

在这里插入图片描述

TabBar实现思路

  1. 如果在下方有一个单独的Tabbar组件,你如何封装
    1. 自定义TabBar组件,在APP中使用
    2. 让TabBar出于底部,并且设置相关的样式
  2. TabBar中显示的内容有外界决定
    1. 定义插槽
    2. flex布局平分TabBar
  3. 自定义TabBarItem,可以传入图片和文字
    1. 定义TabBarItem,并且定义两个插槽:图片、文字。
    2. 给两个插槽外层包装div,用于设置样式。
    3. 填充插槽,实现底部TabBar的效果
  4. 传入高亮图片
    1. 定义另外一个插槽,插入active-icon的数据
    2. 定义一个变量isActive,通过v-show来决定是否显示对应的icon
  5. TabBarItem绑定路由数据
    1. 安装路由:npm install vue-router —save
    2. 完成router/index.js的内容,以及创建对应的组件
    3. main.js中注册router
    4. APP中加入<router-view>组件
  6. 点击Item跳转对应路由,并动态决定isActive
    1. 监听item的点击,通过this.$router.replace()替换路由路径
    2. 通过this.$route.path.indexOf(this.link) !== -1来判断是否是active
  7. 动态计算active样式并且不同的分类显示不同的颜色
    1. 封装新的计算属性:this.isActive ? {'color': 'red'} : {}
  8. 动态添加数据并进行切换
    1. 将数据定义到data中tabList数组中[{label:’’,itemIcon:",itemIconActive:"",path:"",activeColor:’’}]

具体实现

1.新建项目

vue create demo

2.新建目录在这里插入图片描述

base.css

body{
  margin: 0;
  padding: 0;
}

在App.vue文件中,我们在<style>@import "./common/style/base.css";来引入css样式

在main.js中用require('./common/style/base.css')引入

3.TabBar页面搭建

App.vue代码

<template>
	<div id="app">
		<div id="tab-bar">
			<div class="tab-bar-item">
				<img src="./common/img/tabbar/home.svg" alt="">
				<div>首页</div>
			</div>
			<div class="tab-bar-item">
				<img src="./common/img/tabbar/category.svg" alt="">
				<div>分类</div>
			</div>
			<div class="tab-bar-item">
				<img src="./common/img/tabbar/shopcart.svg" alt="">
				<div>购物车</div>
			</div>
			<div class="tab-bar-item">
				<img src="./common/img/tabbar/profile.svg" alt="">
				<div>我的</div>
			</div>
		</div>
	</div>
</template>

<script>
	export default {
		name: 'App',
	}
</script>

<style>
	@import url("~@/common/style/base.css");

	#tab-bar {
		display: flex;
		background-color: #f6f6f6;
		position: fixed;
		left: 0;
		right: 0;
		bottom: 0;
		box-shadow: 0 -1px 1px rgba(100, 100, 100, 100);
	}

	.tab-bar-item {
		flex: 1;
		text-align: center;
		height: 49px;
	}

	.tab-bar-item img {
		width: 24px;
		height: 24px;
	}

	.tab-bar-item {
		flex: 1;
		text-align: center;
		height: 49px;
		font-size: 14px;
	}

	.tab-bar-item img {
		width: 24px;
		height: 24px;
		margin-top: 3px;
		/*去掉图片下面多出来的3像素*/
		vertical-align: middle;
	}
</style>

在这里插入图片描述

4.拆分成TabBar和TabBarItem并进行封装

tabbar.vue

<template>
	<div id="tab-bar">
		<slot></slot>
	</div>
</template>

<script>
</script>

<style>
	#tab-bar {
		display: flex;
		background-color: #f6f6f6;
		position: fixed;
		left: 0;
		right: 0;
		bottom: 0;
		box-shadow: 0 -1px 1px rgba(100, 100, 100, 100);
	}

	
</style>

tabbarItem.vue

<template>
	<router-link class="tab-bar-item" :tag="tags" :to="path">
		<slot name="item-icon"></slot>
		<slot name="item-text"></slot>
	</router-link>
</template>

<script>
	export default {
		props: {
			path: {
				type: String,
				default: "",
			},
			tags:{
				type:String,
				default:"div"
			}
		},
	}
</script>

<style>
	.tab-bar-item {
		flex: 1;
		text-align: center;
		height: 49px;
	}

	.tab-bar-item img {
		width: 24px;
		height: 24px;
	}

	.tab-bar-item {
		flex: 1;
		text-align: center;
		height: 49px;
		font-size: 14px;
	}

	.tab-bar-item img {
		width: 24px;
		height: 24px;
		margin-top: 3px;
		/*去掉图片下面多出来的3像素*/
		vertical-align: middle;
	}
</style>

app.vue

<template>
	<div id="app">
		<tabBar>
			<tabBarItem path="/home" >
				<img slot="item-icon" src="~@/common/img/tabbar/home.svg" alt="" />
				<div slot="item-text">首页</div>
			</tabBarItem>
			<tabBarItem path="/category" >
				<img slot="item-icon" src="~@/common/img/tabbar/category.svg" alt="" />
				<div slot="item-text">分类</div>
			</tabBarItem>
			<tabBarItem path="/cart">
				<img slot="item-icon" src="~@/common/img/tabbar/shopcart.svg" alt="" />
				<div slot="item-text">购物车</div>
			</tabBarItem>
			<tabBarItem path="/my">
				<img slot="item-icon" src="~@/common/img/tabbar/profile.svg" alt="" />
				<div slot="item-text">我的</div>
			</tabBarItem>
		</tabBar>
	</div>
</template>

<script>
	import tabBar from '@/page/tabbar/tabbar.vue'
	import tabBarItem from '@/page/tabbar/TabBarItem.vue';
	export default {
		name: 'App',
		components: {
			tabBar,
			tabBarItem
		}
	}
</script>

<style>
	@import url("~@/common/style/base.css");
</style>

在这里插入图片描述

4.路由跳转

  1. 安装路由:npm install vue-router

  2. 使用

    1. 创建router

      1. index.js

        //配置路由相关信息
        import Vue from 'vue'
        import VueRouter from 'vue-router';
        
        // 通过vue.use(路由插件),安装插件
        Vue.use(VueRouter)
        // 路由懒加载
        const home = () => import("@/page/home/index.vue")
        const category = () => import("@/page/category/index.vue")
        const cart = () => import("@/page/cart/index.vue")
        const my = () => import("@/page/my/index.vue")
        
        // 定义路由
        let routes = [{
        		path: "",
        		redireact: '/home'
        	}, {
        		path: "/home",
        		name: "首页",
        		component: home
        	},
        	{
        		path: "/category",
        		name: "分类",
        		component: category,
        	},
        	{
        		path: "/cart",
        		name: "购物车",
        		component: cart
        	}, {
        		path: "/my",
        		component: my,
        		name: "我的"
        	},
        ]
        // 创建router实例
        let router = new VueRouter({
        	// 配置路由和组件之间的应用关系
        	mode: "history", //abstract || history || hash= 
        	routes
        })
        
        // 导出router实例
        export default router
        
    2. 在main引入,并重新启动项目

      import router from './router/index.js';
      
    3. app.js

      <template>
      	<div id="app">
      		<router-view></router-view>
      		<mainTab></mainTab>
      	</div>
      </template>
      
      <script>
      	import mainTab from '@/page/mainTable/index.vue'
      	export default {
      		name: 'App',
      		components: {
      			mainTab
      		}
      	}
      </script>
      
      <style>
      	@import url("~@/common/style/base.css");
      </style>
      
      
    4. tabbarItem.vue发生改变

      <template>
      	<router-link class="tab-bar-item" :tag="tags" :to="path">
      		<slot name="item-icon"></slot>
      		<slot name="item-text"></slot>
      	</router-link>
      </template>
      
      <script>
      	export default {
      		props: {
      			path: {
      				type: String,
      				default: "",
      			},
      			tags:{
      				type:String,
      				default:"div"
      			}
      		},
      	}
      </script>
      
      <style>
      	.tab-bar-item {
      		flex: 1;
      		text-align: center;
      		height: 49px;
      	}
      
      	.tab-bar-item img {
      		width: 24px;
      		height: 24px;
      	}
      
      	.tab-bar-item {
      		flex: 1;
      		text-align: center;
      		height: 49px;
      		font-size: 14px;
      	}
      
      	.tab-bar-item img {
      		width: 24px;
      		height: 24px;
      		margin-top: 3px;
      		/*去掉图片下面多出来的3像素*/
      		vertical-align: middle;
      	}
      </style>
      
      
      

在这里插入图片描述

5.点击Item跳转对应路由,并动态决定isActive

tabbarItem.vue

<template>
	<router-link class="tab-bar-item" :tag="tags" :to="path">
		<div v-if="isActive">
			<slot name="item-icon-active"></slot>
		</div>
		<div v-if='!isActive'>
			<slot name="item-icon"></slot>
		</div>
		<slot name="item-text"></slot>
	</router-link>
</template>

<script>
	export default {
		props: {
			path: {
				type: String,
				default: "",
			},
			tags: {
				type: String,
				default: "div"
			},
		},
		computed: {
			isActive() {
				return this.$route.path.indexOf(this.path) !== -1;
			},
		},

	}
</script>

<style>
	.tab-bar-item {
		flex: 1;
		text-align: center;
		height: 49px;
	}

	.tab-bar-item img {
		width: 24px;
		height: 24px;
	}

	.tab-bar-item {
		flex: 1;
		text-align: center;
		height: 49px;
		font-size: 14px;
	}

	.tab-bar-item img {
		width: 24px;
		height: 24px;
		margin-top: 3px;
		/*去掉图片下面多出来的3像素*/
		vertical-align: middle;
	}
</style>

mainTable.vue

<template>
	<div id="app">
		<tabBar>
			<tabBarItem path="/home" >
				<img
				  slot="item-icon-active"
				  src="~@/common/img/tabbar/home_active.svg"
				  alt=""
				/>
				<img slot="item-icon" src="~@/common/img/tabbar/home.svg" alt="" />
				<div slot="item-text">首页</div>
			</tabBarItem>
			<tabBarItem path="/category" >
				<img
				  slot="item-icon-active"
				  src="~@/common/img/tabbar/category_active.svg"
				  alt=""
				/>
				<img slot="item-icon" src="~@/common/img/tabbar/category.svg" alt="" />
				<div slot="item-text">分类</div>
			</tabBarItem>
			<tabBarItem path="/cart">
				<img
				  slot="item-icon-active"
				  src="~@/common/img/tabbar/shopcart_active.svg"
				  alt=""
				/>
				<img slot="item-icon" src="~@/common/img/tabbar/shopcart.svg" alt="" />
				<div slot="item-text">购物车</div>
			</tabBarItem>
			<tabBarItem path="/my">
				<img
				  slot="item-icon-active"
				  src="~@/common/img/tabbar/profile_active.svg"
				  alt=""
				/>
				<img slot="item-icon" src="~@/common/img/tabbar/profile.svg" alt="" />
				<div slot="item-text">我的</div>
			</tabBarItem>
		</tabBar>
	</div>
</template>

<script>
	import tabBar from '@/page/tabbar/tabbar.vue'
	import tabBarItem from '@/page/tabbar/TabBarItem.vue';
	export default {
		components: {
			tabBar,
			tabBarItem
		}
	}
</script>

<style>
</style>

在这里插入图片描述

5.动态计算active样式并且不同的分类显示不同颜色

<template>
	<router-link class="tab-bar-item" :tag="tags" :to="path">
		<div v-if="isActive">
			<slot name="item-icon-active"></slot>
		</div>
		<div v-if='!isActive'>
			<slot name="item-icon"></slot>
		</div>
		<div :style="activeStyle">
			<slot name="item-text"></slot>
		</div>
	</router-link>
</template>

<script>
	export default {
		props: {
			path: {
				type: String,
				default: "",
			},
			tags: {
				type: String,
				default: "div"
			},
			activeColor:{
				type:String,
				default:''
			}
		},
		computed: {
			isActive() {
				return this.$route.path.indexOf(this.path) !== -1;
			},
			activeStyle(){
				return this.isActive? {'color': this.activeColor} : {}
			}
		},

	}
</script>

<style>
	.tab-bar-item {
		flex: 1;
		text-align: center;
		height: 49px;
	}

	.tab-bar-item img {
		width: 24px;
		height: 24px;
	}

	.tab-bar-item {
		flex: 1;
		text-align: center;
		height: 49px;
		font-size: 14px;
	}

	.tab-bar-item img {
		width: 24px;
		height: 24px;
		margin-top: 3px;
		/*去掉图片下面多出来的3像素*/
		vertical-align: middle;
	}
</style>

mainTable.vue

<tabBarItem path="/home" activeColor="red">
      <img slot="item-icon" src="~@/assets/img/tabbar/home.svg" alt="" />
      <img
        slot="item-icon-active"
        src="~@/assets/img/tabbar/home_active.svg"
        alt=""
      />
      <div slot="item-text">首页</div>
    </tabBarItem>
    <tabBarItem path="/category" activeColor="green">
      <img slot="item-icon" src="~@/assets/img/tabbar/category.svg" alt="" />
      <img
        slot="item-icon-active"
        src="~@/assets/img/tabbar/category_active.svg"
        alt=""
      />
      <div slot="item-text">分类</div>
    </tabBarItem>
    <tabBarItem path="/cart" activeColor="yellow">
      <img slot="item-icon" src="~@/assets/img/tabbar/shopcart.svg" alt="" />
      <img
        slot="item-icon-active"
        src="~@/assets/img/tabbar/shopcart_active.svg"
        alt=""
      />
      <div slot="item-text">购物车</div>
    </tabBarItem>
    <tabBarItem path="/my" activeColor="blue">
      <img slot="item-icon" src="~@/assets/img/tabbar/profile.svg" alt="" />
      <img
        slot="item-icon-active"
        src="~@/assets/img/tabbar/profile_active.svg"
        alt=""
      />
      <div slot="item-text">我的</div>
    </tabBarItem>
  </tabbar>

在这里插入图片描述

6.动态添加数据并进行切换

<template>
	<div id="app">
		<tabBar>
			<tabBarItem v-for="(item,index) in tabList" :key="index" :path="item.path" :activeColor='item.activeColor'>
				<img slot="item-icon-active" :src="item.itemIconActive" alt="" />
				<img slot="item-icon" :src="item.itemIcon" alt="" />
				<div slot="item-text">{{item.label}}</div>
			</tabBarItem>
		</tabBar>
	</div>
</template>

<script>
	import tabBar from '@/page/tabbar/tabbar.vue'
	import tabBarItem from '@/page/tabbar/TabBarItem.vue';
	export default {
		components: {
			tabBar,
			tabBarItem
		},
		data() {
			return {
				tabList: [{
						path: "/home",
						activeColor: "red",
						itemIcon: require("@/common/img/tabbar/home.svg"),
						itemIconActive: require("@/common/img/tabbar/home_active.svg"),
						label: "首页"
					},
					{
						path: "/category",
						activeColor: "yellow",
						itemIcon: require("@/common/img/tabbar/category.svg"),
						itemIconActive: require("@/common/img/tabbar/category_active.svg"),
						label: "分类"
					},
					{
						path: "/cart",
						activeColor: "blue",
						itemIcon: require("@/common/img/tabbar/shopcart.svg"),
						itemIconActive: require("@/common/img/tabbar/shopcart_active.svg"),
						label: "购物车"
					},
					{
						path: "/my",
						activeColor: "green",
						itemIcon: require("@/common/img/tabbar/profile.svg"),
						itemIconActive: require("@/common/img/tabbar/profile_active.svg"),
						label: "我的"
					},
				]
			}
		}
	}
</script>

<style>
</style>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3V24mBB3-1647787006890)(E:\资料存档\资料笔记\总结项目\img\image-20220320223346570.png)]

activeColor: "yellow",
					itemIcon: require("@/common/img/tabbar/category.svg"),
					itemIconActive: require("@/common/img/tabbar/category_active.svg"),
					label: "分类"
				},
				{
					path: "/cart",
					activeColor: "blue",
					itemIcon: require("@/common/img/tabbar/shopcart.svg"),
					itemIconActive: require("@/common/img/tabbar/shopcart_active.svg"),
					label: "购物车"
				},
				{
					path: "/my",
					activeColor: "green",
					itemIcon: require("@/common/img/tabbar/profile.svg"),
					itemIconActive: require("@/common/img/tabbar/profile_active.svg"),
					label: "我的"
				},
			]
		}
	}
}

![在这里插入图片描述](https://www.icode9.com/i/ll/?i=7574d5cdf6984a3c8fad2180f4d8d9ef.png#pic_center)
![在这里插入图片描述](https://www.icode9.com/i/ll/?i=b46f5bb2ce8e4df88a3981216f77adc6.png?,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56iL5bqP5r2H5r2H,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)

标签:vue,bar,tabbar,img,item,tab
来源: https://blog.csdn.net/fxxx_/article/details/123623630