目录Vue封装Tabbar组件在App.vue 封装 路由跳转 利用router-view的特性子组件Tabbar然后就是配置的路由从零开始封装一个Tabbar首先底部菜单栏最外层是
话不多说直接上代码
<template>
<div id="app">
<router-view />
//引入子组件 把items 这个数组传进去
<Tabr :items="items" />
</div>
</template>
<script>
import Tabr from "./components/Tabr";
export default {
components: {
Tabr,
},
data() {
return {
items: [
{
title: "首页",
path: "/",
img: require("./assets/img/shouye.png"),
imgs: require("./assets/img/shouye_1.png"),
},
{
title: "分类",
path: "/About",
img: require("./assets/img/fenlei.png"),
imgs: require("./assets/img/fenlei_1.png"),
},
{
title: "购物车",
path: "/Cart",
img: require("./assets/img/Gouwuchezhengpin.png"),
imgs: require("./assets/img/gouwuchezhengpin_1.png"),
},
{
title: "我的",
path: "/Mime",
img: require("./assets/img/wode.png"),
imgs: require("./assets/img/wode_1.png"),
},
],
};
},
};
</script>
<template>
<div class="Yanxuan_tab">
<div v-for="(item,index) in items" :key="index" @click="Onclick(index)">
<div>
<img :src="index===Tabindex?item.imgs:item.img" alt />
//动态绑定
</div>
<div :class="index===Tabindex?'title':'Yanxuan_title'">
//
{{item.title}}</div>
</div>
</div>
</template>
<script>
export default {
props: {
items: {
type: Array,
required: true,
validator: function (value) {
return value.length <= 6;
//市面常见的Tabbar的栏 不能超过6个
},
}
},
data() {
return {
item:this.items,
Tabindex:0
}
},
methods:{
Onclick(index){
//这里是根据下标切换 图片样式跟字体颜色 动态绑定
this.Tabindex = index
var temp = this.item[index]
this.$router.push(temp.path)
}
}
};
</script>
<style scoped>
.Yanxuan_tab {
width: 100%;
height: 64px;
border: 1px solid gainsboro;
position: fixed;
bottom: 0px;
left: 0px;
display: inline-flex;
justify-content: space-around;
align-items: center;
text-align: center;
}
.Yanxuan_title{
font-size: 14px;
}
.title{
font-size: 14px;
color:red
}
</style>
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home,
meta:{
isshowTabbar:true
}
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import( '../views/About.vue'),
meta:{
isShowTabbar:true
}
}
,
{
path: '/Cart',
name: 'Cart',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import( '../views/Cart.vue'),
meta:{
isShowTabbar:false
}
},
{
path: '/Mime',
name: 'Mime',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import( '../views/Mime.vue'),
meta:{
isShowTabbar:true
}
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
最后的效果完成图
代码就直接可以用了
在div中整体上存在四个或五个小div,每个div中包含icon和text,如下图
对于每一个icon对象,它包含图标以及文字,但十实际中我们肯定不会将img和text写死,以及处于active状态时text的颜色也不会写死,以方便调用者传入想要的参数,这样才算一个彻底的封装。
<template>
<div class="tab-bar-item" @click="itemClick">
<div v-if="!isActive">
<slot name="item-icon"></slot>
</div>
<div v-else>
<slot name="item-icon-active"></slot>
</div>
<div :style="activeStyle">
<slot name="item-text"></slot>
</div>
</div>
</template>
<!--
上方代码设置三个插槽,为什么不是两个呢,因为还要包含当item处于活跃状态时要显示的image,所以是三个,使用v-if控制当非活跃时显示默认icon插槽,活跃时显示亮色icon插槽。因为插槽是要被传入其中的内容覆盖的,所以传入的内容可能会将我们slot中的一些属性覆盖掉,所以常常我们需要将slot包裹在div中,这样就可以避免这个问题。
icon下方文同理也放在div中,style绑定一个计算属性,看下方代码可以这个计算属性当item处于活跃时会返回颜色属性,当然这个属性也是可以在调用tab-bar时传入的,默认为红色。
-->
<script>
export default {
name:'TabBarItem',
props:{
path: String, // 当前item对应的路由,由调用者指定
activeColor:{ // 当前item的文字在活跃时的颜色,默认红色,可由使用者指定
type:String,
default:"red"
}
},
data() {
return {
// isActive:false,
}
},
computed:{
// 判断当前item是否处于活跃状态
isActive(){
return this.$route.path.indexOf(this.path)!==-1;
},
// 计算属性,如果处于活跃状态则设置style,否则去除style
activeStyle(){
return this.isActive? {color:this.activeColor}:{};
}
},
methods:{
itemClick(){
if(this.$route.path!==this.path){
this.$router.push(this.path);
// this.isActive = true;
}
}
}
}
</script>
<style scoped>
<!--一些默认样式-->
.tab-bar-item {
flex: 1;
text-align: center;
height: 49px;
font-size: 10px;
}
.tab-bar-item img {
margin-top: 4px;
width: 22px;
height: 22px;
vertical-align: middle;
margin-bottom: 2px;
}
</style>
接下来是整体的tabbar,试想,我们肯定还是放入一个插槽代码如下:
<template>
<div id="tab-bar">
<slot></slot>
</div>
</template>
<script>
export default {
name: "TabBar"
};
</script>
<style scoped>
#tab-bar {
display: flex;
background-color: #f6f6f6;
position: fixed;
left: 0;
right: 0;
bottom: 0;
box-shadow: 0px -2px 1px rgba(100, 100, 100, 0.1);
}
</style>
tabbar预留的插槽则用于放入每一个item,我们在这里也是不能写死的,因为控件开发者并不知需要放入多少个item。
则可以如下代码,放入内容:
<template>
<tab-bar>
<tab-bar-item path="/home" activeColor="deepPink">
<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>
</tab-bar-item>
<tab-bar-item path="/category" activeColor="deepPink">
<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>
</tab-bar-item>
<tab-bar-item path="/cart" activeColor="deepPink">
<img slot="item-icon" src="~assets/img/tabbar/cart.svg" alt="">
<img slot="item-icon-active" src="~assets/img/tabbar/cart_active.svg" alt="">
<div slot="item-text">购物车</div>
</tab-bar-item>
<tab-bar-item path="/profile" activeColor="deepPink">
<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>
</tab-bar-item>
</tab-bar>
</template>
<script>
import TabBar from "components/tabbar/TabBar";
import TabBarItem from "components/tabbar/TabBarItem";
export default {
name:'MainTabBar',
components:{
TabBar,
TabBarItem
}
}
</script>
<style scoped>
</style>
到此结束。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。
--结束END--
本文标题: Vue封装一个Tabbar组件 带组件路由跳转方式
本文链接: https://lsjlt.com/news/147587.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-01-12
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0