前言
一、封装思路
1. 效果展示
2. 实现思路
如果在下方有一个单独的
TabBar
组件,你如何封装- 自定义TabBar组件,在APP中使用
- 让TabBar出于底部,并且设置相关的样式
TabBar中显示的内容由外界决定
- 定义插槽
flex布局平分TabBar
自定义
TabBarItem
,可以传入图片和文字
- 定义TabBarItem,并且
定义两个插槽
:图片、文字。 - 给两个插槽外层包装div,用于设置样式。
- 填充插槽,实现底部TabBar的效果
- 定义TabBarItem,并且
传入 高亮图片
- 定义另外一个插槽,
插入active-icon的数据
- 定义一个变量
isActive
,通过v-show来决定是否显示对应的icon
- 定义另外一个插槽,
TabBarItem绑定路由数据
- 安装路由:npm install vue-router —save
- 完成
router/index.js
的内容,以及创建对应的组件 main.js
中注册router
- APP中加入
<router-view>
组件
点击
item
跳转到对应路由,并且动态决定isActive
- 监听
item
的点击,通过this.$router.replace()
替换路由路径 - 通过
this.$route.path.indexOf(this.link) !== -1
来判断是否是active
- 监听
动态计算active样式
- 封装新的计算属性:
this.isActive ? {'color': 'red'} : {}
- 封装新的计算属性:
二、代码实现
1. 新建项目
- 使用
vue init webpack 02-tabbar
- 安装的时候记得选择安装
vue-router
- 项目目录结构如下:
2. 创建组件Home/Category/Cart/Profie
新建目录view
,用于存放各个页面的组件。
3. 配置路由规则
三、封装TarBar
1. 先封装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-icon-active"></slot>
</div>
<!-- :class="{active: isActive}" -->
<div :style="activeStyle">
<slot name="item-text"></slot>
</div>
<!-- <img src="../../assets/img/tabbar/home.svg" alt="">-->
<!-- <div>首页</div>-->
</div>
</template>
<script>
export default {
name: "TabBarItem",
// 传过来的数据
props: {
path: String,
activeColor: {
type: String,
default: 'red'
}
},
data() {
return {
// isActive: true,
}
},
computed: {
isActive() {
// this.$route.path 获取的事当前路由的 路径
return this.$route.path.indexOf(this.path) !== -1
},
activeStyle() {
return this.isActive ? {color: this.activeColor} : {}
}
},
methods: {
itemClick() {
this.$router.replace(
{path: this.path},
onComplete => {
},
onAbort => {
}
)
// console.log('itemClick')
}
}
}
</script>
<style scoped>
.tab-bar-item {
flex: 1;
text-align: center;
height: 49px;
font-size: 14px;
}
.tab-bar-item img {
width: 24px;
height: 24px;
margin-top: 3px;
vertical-align: middle;
margin-bottom: 2px;
}
</style>
2. TabBar.vue
<template>
<div id="tab-bar">
<slot></slot>
</div>
</template>
<script>
export default {
name: "TabBar"
}
</script>
<style scoped>
@import "../../assets/css/base.css";
#tab-bar{
display: flex;
background-color: #f7f7f7;
/*放到下面*/
position: fixed;
left: 0;
right: 0;
bottom: 0;
/*添加阴影*/
box-shadow: 0 -3px 1px rgba(100, 100, 100, .1);
}
</style>
3. MainTabBar.vue
<template>
<TabBar>
<tab-bar-item path="/home" activeColor="blue">
<img slot="item-icon" src="../assets/img/tabbar/home.svg">
<img slot="item-icon-active" src="../assets/img/tabbar/home_active.svg">
<div slot="item-text">首页</div>
</tab-bar-item>
<tab-bar-item path="/category" activeColor="blue">
<img slot="item-icon" src="../assets/img/tabbar/category.svg">
<img slot="item-icon-active" src="../assets/img/tabbar/category_active.svg">
<div slot="item-text">分类</div>
</tab-bar-item>
<tab-bar-item path="/cart" activeColor="blue">
<img slot="item-icon" src="../assets/img/tabbar/shopcart.svg">
<img slot="item-icon-active" src="../assets/img/tabbar/shopcart_active.svg">
<div slot="item-text">购物车</div>
</tab-bar-item>
<tab-bar-item path="/profile" activeColor="blue">
<img slot="item-icon" src="../assets/img/tabbar/profile.svg">
<img slot="item-icon-active" src="../assets/img/tabbar/profile_active.svg">
<div slot="item-text">我的</div>
</tab-bar-item>
</TabBar>
</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>
4. APP.vue 使用
<template>
<div>
<MainTabBar/>
<router-view/>
</div>
</template>
<script>
import MainTabBar from "./components/MainTabBar";
export default {
name: 'App',
components: {
MainTabBar
}
}
</script>
<style>
</style>
5. 用到的地儿
- router
- slot 插槽
- 父传子 传参数