使用 Vue 制作 tabbar
Demo地址 : https://github.com/lpzzzz/vue-tabbar
1. 创建项目
vue-cli2.0使用 vue init webpack tabbar 命令创建项目。
vue init webpack tabbar
在style中引用资源需要使用 @import 进行引用;
2. 删除项目中多余的默认组件以及样式
3. 编写简单的基础界面
编写简单的界面启动测试。
1. npm install
2. npm run dev
3.1 清除页面的默认样式
在assets文件夹中创建img 和 css等静态资源文件夹。
清除页面默认样式
body {
margin: 0;
padding: 0;
}
在App.vue中引用样式
@import "./assets/css/base.css";
编写基本的结构代码 :快捷方法=> #tabbar>div.tabbar-item*4
<div id="tabbar">
<div class="tabbar-item">首页
</div>
<div class="tabbar-item">分类
</div>
<div class="tabbar-item">购物车
</div>
<div class="tabbar-item">我的
</div>
</div>
编写结构简单样式
#tabbar {
display: flex
;
position: fixed
;
left: 0
;
right: 0
;
bottom: 0
;
height: 49px
;
background-color: #f7f7f7
;
box-shadow: 0 -3px 5px
rgba(100, 100, 100, .1
);
}
.tabbar-item {
flex: 1
;
text-align: center
;
}
以上代码没有较强的复用性。
3.2 封装(抽取)组件
3.2.1 抽取App中的Tabbar
将Tabbar代码块内的代码抽取为一个新的组件Tabbar.vue在App.vue中 import Tabbar from “./components/tabbar/Tabbar”在 components中 注册组件
<div id="tabbar">
<div class="tabbar-item">
<img src="../../assets/img/tabbar/home.svg" alt="">
<div>首页
</div>
</div>
<div class="tabbar-item">
<img src="../../assets/img/tabbar/category.svg" alt="">
<div>分类
</div>
</div>
<div class="tabbar-item">
<img src="../../assets/img/tabbar/shopcart.svg" alt="">
<div>购物车
</div>
</div>
<div class="tabbar-item">
<img src="../../assets/img/tabbar/profile.svg" alt="">
<div>我的
</div>
</div>
</div>
3.2.2 抽取 Tabbar组件中的Tabbar-item
抽取Tabbar中的大量代码,使用slot插槽进行替换。
<template>
<div id="tabbar">
<slot> </slot>
</div>
</template>
<script>
export default {
name: "tabbar"
}
</script>
<style scoped>
#tabbar {
display: flex;
position: fixed;
left: 0;
right: 0;
bottom: 0;
height: 49px;
background-color: #f7f7f7;
box-shadow: 0 -3px 5px rgba(100, 100, 100, .1);
}
</style>
3.2.3 将Tabbar-item中的部分抽取出来使用具名插槽替换方便后面扩展
<template>
<div class="tabbar-item">
<slot name="slot-icon"/>
<slot name="slot-text"/>
</div>
</template>
<script>
export default {
name: "tabbar-item"
}
</script>
<style scoped>
.tabbar-item {
flex: 1;
text-align: center;
vertical-align: middle;
margin-top: 3px;
font-size: 14px;
margin-bottom: 2px;
}
.tabbar-item img {
height: 24px;
width: 24px;
}
</style>
3.2.4 在App中引入组件进行使用
在App中使用 script代码块中使用 import … 引入自定义的组件进行使用。
import Tabbar from "./components/tabbar/Tabbar"
import TabbarItem from "./components/tabbar/Tabbar-item"
在App中使用引入的组件如下:
<template>
<div id="app">
<Tabbar>
<tabbar-item>
<img slot="slot-icon" src="./assets/img/tabbar/home.svg" alt="">
<div slot="slot-text">首页
</div>
</tabbar-item>
<tabbar-item>
<img slot="slot-icon" src="./assets/img/tabbar/category.svg" alt="">
<div slot="slot-text">分类
</div>
</tabbar-item>
<tabbar-item>
<img slot="slot-icon" src="./assets/img/tabbar/shopcart.svg" alt="">
<div slot="slot-text">购物车
</div>
</tabbar-item>
<tabbar-item>
<img slot="slot-icon" src="./assets/img/tabbar/profile.svg" alt="">
<div slot="slot-text">我的
</div>
</tabbar-item>
</Tabbar>
</div>
</template>
<script>
import Tabbar from "./components/tabbar/Tabbar"
import TabbarItem from "./components/tabbar/Tabbar-item"
export default {
name: 'App',
components: {
Tabbar,
TabbarItem
}
}
</script>
<style>
@import "./assets/css/base.css";
</style>
3.3 给Tabbar-item传入active图片
新增插槽并且在插槽上加上判断根据条件进行激活显示。
<template>
<div class="tabbar-item">
<div v-if="!isActive">
<slot name="slot-icon"/>
</div>
<div v-else>
<slot name="slot-icon-active"/>
</div>
<div :class="{active:isActive}">
<slot name="slot-text"/>
</div>
</div>
</template>
<script>
export default {
name: "tabbar-item",
data() {
return {
isActive: false
}
}
}
</script>
<style scoped>
.tabbar-item {
flex: 1;
text-align: center;
vertical-align: middle;
margin-top: 3px;
font-size: 14px;
margin-bottom: 2px;
}
.tabbar-item img {
height: 24px;
width: 24px;
}
.active {
color: red;
}
</style>
注意:在使用插槽的时候填充到插槽中的内容会替换掉插槽内的所有内容,所以进行使用一个div将插槽包裹起来,在div中写一些必要的属性。像下面这样:
<div :class="{active:isActive}">
<slot name="slot-text"/>
</div>
3.4 Tabbar-item与路由相结合
每个Tabbar-item都和一个路由跳转相对应。
3.4.1 安装路由操作
如果在创建项目的时候没有安装路由,需要使用命令进行安装:npm install vue-router -save 。创建router文件夹。在文件夹中创建index.js文件。文件中的内容如下 :
import Vue
from 'vue'
import VueRouter
from 'vue-router'
Vue
.use(VueRouter
)
const Home = () => import('../views/home/Home')
const Category = () => import('../views/category/Category')
const Cart = () => import('../views/cart/Cart')
const Profile = () => import('../views/profile/Profile')
const routes
= [
{
path
: '/',
redirect
: '/home'
},
{
path
: '/home',
component
: Home
},
{
path
: '/category',
component
: Category
},
{
path
: '/profile',
component
: Profile
},
{
path
: '/cart',
component
: Cart
}
]
const router
= new VueRouter({
routers
})
export default router
3.4.2 在main.js中引用导入路由并使用
import Vue from 'vue'
import App from './App'
import router from './router'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
render: h => h(App)
})
3.4.3 创建各个组件
各个组件尽量不要建立到components文件夹中,该文件夹中存放的是一些公共的组件。可以新建一个views或者pages存放新的每一个单一的组件。
3.4.4 在Tabbar-item组件上注册监听事件
监听事件上设置路由的跳转,this.$router.push(目的路径);
3.4.5 在App中传递过来跳转的路径
3.5 Tabbar-item的颜色动态控制
将isActive设置为计算属性,根据当前选中的路由路径判断当前选中的状态。返回一个Boolean值;
// 在TabbarItem中添加如下代码
computed: {
isActive() {
/*该条件成立的时候表示某个tabbar-item属于活跃状态*/
return this.$route.path.indexOf(this.path) !== -1
}
}
3.6 TabbarItem中文字颜色
3.6.1 思路
需要在props中定义一个属性。用于接收来自App中传递过来的颜色设置。设置props中的属性名称为activeColor 类型为 String 默认值为red 在TabbarItem组件中的文字上绑定上style 的计算属性。
路径判断当前选中的状态。返回一个Boolean值;
// 在TabbarItem中添加如下代码
computed: {
isActive() {
/*该条件成立的时候表示某个tabbar-item属于活跃状态*/
return this.$route.path.indexOf(this.path) !== -1
}
}
3.6 TabbarItem中文字颜色
3.6.1 思路
需要在props中定义一个属性。用于接收来自App中传递过来的颜色设置。设置props中的属性名称为activeColor 类型为 String 默认值为red 在TabbarItem组件中的文字上绑定上style 的计算属性。
3.7 抽取Tabbar中App中的大量代码到Main.vue组件中
<template>
<Tabbar>
<tabbar-item path="/home" activeColor="red">
<img slot="slot-icon" src="../assets/img/tabbar/home.svg" alt="">
<img slot="slot-icon-active" src="../assets/img/tabbar/home_active.svg" alt="">
<div slot="slot-text">首页
</div>
</tabbar-item>
<tabbar-item path="/category" activeColor="green">
<img slot="slot-icon" src="../assets/img/tabbar/category.svg" alt="">
<img slot="slot-icon-active" src="../assets/img/tabbar/category_active.svg" alt="">
<div slot="slot-text">分类
</div>
</tabbar-item>
<tabbar-item path="/cart" activeColor="blue">
<img slot="slot-icon" src="../assets/img/tabbar/shopcart.svg" alt="">
<img slot="slot-icon-active" src="../assets/img/tabbar/shopcart_active.svg" alt="">
<div slot="slot-text">购物车
</div>
</tabbar-item>
<tabbar-item path="/profile">
<img slot="slot-icon" src="../assets/img/tabbar/profile.svg" alt="">
<img slot="slot-icon-active" src="../assets/img/tabbar/profile_active.svg" alt="">
<div slot="slot-text">我的
</div>
</tabbar-item>
</Tabbar>
</template>
<script>
import Tabbar from "../components/tabbar/Tabbar"
import TabbarItem from "../components/tabbar/Tabbar-item"
export default {
name: "main-tabbar",
components: {
Tabbar,
TabbarItem
}
}
</script>
<style scoped>
</style>
3.8 文件路径起别名(文件路径的引用问题)
修改 webpack.base.conf.js 配置文件 中的下面部分: 在属性中使用:引用src文件路径需要在前面加上~ 引用外部组件
4. 最终效果