运行结果
项目结构
App.vue
<template>
<div id="app">
<router-view></router-view>
<main-tab-bar></main-tab-bar>
</div>
</template>
<script>
import MainTabBar from "./components/content/mainTabbar/MainTabBar";
export default {
name: "App",
components: {
MainTabBar,
},
};
</script>
<style>
@import "assets/css/base.css";
</style>
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
router,
}).$mount('#app')
TabBar.vue
<template>
<div class='tab-bar'>
<slot></slot>
</div>
</template>
<script>
export default {
name: 'TabBar',
components: {}
}
</script>
<style scoped>
.tab-bar {
display: flex;
position: fixed;
left: 0;
right: 0;
bottom: 0;
box-shadow: 0 -2px 1px rgba(100, 100, 100, 0.1); /*X轴偏移量、Y轴偏移量、模糊半径*/
background-color: #f6f6f6;
}
</style>
TabBarItem.vue
<template>
<div class='tab-bar-item' @click='itemClick'>
<div v-if='!isActive'>
<slot name='item-icon'></slot>
</div>
<div v-else>
<slot name='item-active'></slot>
</div>
<!--加一层div的目的是,用户添加的标签会直接替换slot,
这样在slot上添加class不会生效-->
<!-- 动态设置样式,让用户使用组件时自己传入点击后的字体颜色 -->
<!-- <div :class='{active: isActive}'><slot name='item-text'></slot></div> -->
<div :style='activeStyle'>
<slot name='item-text'></slot>
</div>
</div>
</template>
<script>
export default {
name: 'TabBarItem',
props: {
path: String,
colorActive: {
type: String,
default: 'red'
}
},
data() {
return {}
},
computed: {
isActive() {
//this.$route哪个路由活跃就是哪个对象的
//indexOf返回某个指定的字符串值在字符串中首次出现的位置
return this.$route.path.indexOf(this.path) !== -1
},
activeStyle() {
return this.isActive ? {color: this.colorActive} : {}
}
},
methods: {
itemClick() {
this.$router.replace(this.path).catch(err => err)
}
}
}
</script>
<style scoped>
.tab-bar-item {
flex: 1;
text-align: center;
font-size: 14px;
height: 49px;
}
.tab-bar-item img {
width: 24px;
margin: 2px 0;
}
.active {
color: var(--color-high-text)
}
</style>
MainTabBar.vue
<template>
<div>
<tab-bar>
<tab-bar-item path='/home' colorActive='var(--color-high-text)'>
<img slot='item-icon' src="~assets/img/tabbar/home.svg" alt=""/>
<img slot='item-active' src="~assets/img/tabbar/home_active.svg" alt=""/>
<div slot='item-text'>首页</div>
</tab-bar-item>
<tab-bar-item path='/category' colorActive='var(--color-high-text)'>
<img slot='item-icon' src="~assets/img/tabbar/category.svg" alt=""/>
<img slot='item-active' src="~assets/img/tabbar/category_active.svg" alt=""/>
<div slot='item-text'>分类</div>
</tab-bar-item>
<tab-bar-item path='/cart' colorActive='var(--color-high-text)'>
<img slot='item-icon' src="~assets/img/tabbar/shopcart.svg" alt=""/>
<img slot='item-active' src="~assets/img/tabbar/shopcart_active.svg" alt=""/>
<div slot='item-text'>购物车</div>
</tab-bar-item>
<tab-bar-item path='/profile' colorActive='var(--color-high-text)'>
<img slot='item-icon' src="~assets/img/tabbar/profile.svg" alt=""/>
<img slot='item-active' src="~assets/img/tabbar/profile_active.svg" alt=""/>
<div slot='item-text'>我的</div>
</tab-bar-item>
</tab-bar>
</div>
</template>
<script>
import TabBar from "components/common/tabbar/TabBar";
import TabBarItem from "components/common/tabbar/TabBarItem";
export default {
name: "MainTabBar",
components: {
TabBar,
TabBarItem,
},
};
</script>
<style>
</style>
Index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
const Home = () => import('views/home/Home')
const Category = () => import('views/category/Category')
const Cart = () => import('views/cart/Cart')
const Profile = () => import('views/profile/Profile')
//通过Vue.use安装vue-router插件
Vue.use(VueRouter)
const routes = [
{
path: '',
redirect: '/home'
},
{
path: '/home',
component: Home
},
{
path: '/category',
component: Category
},
{
path: '/cart',
component: Cart
},
{
path: '/profile',
component: Profile
},
]
//创建VueRouter对象
const router = new VueRouter({
routes,
mode: 'history'
})
//导出
export default router
vue.config.js
module.exports = {
configureWebpack: {
resolve: {
alias: {
'views': '@/views',
'components': '@/components',
'network': '@/network',
'common': '@/common',
'assets': '@/assets',
}
}
}
}
(根据coderway老师的课程编写的)