TabBar案例及思考

效果图
在这里插入图片描述

vue init webpack TabBar
目录结构
在这里插入图片描述
结构搭建

APP.vue

<template>
  <div id="app">
    <div class="tabbar">
    <div class="tab-bar-item">
    <img src="../assets/img/tabbar/home.svg" alt="">
     首页</div>
    <div class="tab-bar-item">
    <img src="../assets/img/tabbar/home.svg" alt="">
    分类</div>
    <div class="tab-bar-item">
    <img src="../assets/img/tabbar/home.svg" alt="">
    商城</div>
    <div class="tab-bar-item">
    <img src="../assets/img/tabbar/home.svg" alt="">
    我的</div>
  </div>
    </div>
  
</template>

<script>

import TabBar from './components/TabBar.vue'
export default {
  name: 'App',
  components:{
    TabBar
    
  }
}
</script>

<style>
//css引入方式
@import url('./assets/css/base.css');
.tabbar{
  display: flex;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: 49px;
  background-color: #f6f6f6;
  line-height: 49px;
  font-size: 18px;
  box-shadow: 0 -2px rgba(0,0,0,.1);
}
.tab-bar-item{
  flex: 1;
  text-align: center;
  
}
.tab-bar-item img{
    width: 24px;
    height: 24px;
}
</style>

此时效果
在这里插入图片描述
文件抽离成组件

都放在APP.vue里过于繁琐

新建TabBar.vue

<template>
  <div class="tabbar">
    <div class="tab-bar-item">
        <img src="../assets/img/tabbar/home.svg" alt="">
        首页</div>
    <div class="tab-bar-item"><img src="../assets/img/tabbar/home.svg" alt="">分类</div>
    <div class="tab-bar-item"><img src="../assets/img/tabbar/home.svg" alt="">商城</div>
    <div class="tab-bar-item"><img src="../assets/img/tabbar/home.svg" alt="">我的</div>
  </div>
</template>

<script>
export default {

}
</script>

<style>
.tabbar{
  display: flex;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: 49px;
  background-color: #f6f6f6;
  line-height: 49px;
  font-size: 18px;
  box-shadow: 0 -2px rgba(0,0,0,.1);
}
.tab-bar-item{
  flex: 1;
  text-align: center;
  
}
.tab-bar-item img{
    width: 24px;
    height: 24px;
}
</style>

此时要在APP.vue中导入

<template>
  <div id="app">
    <!--使用组件-->
    <tab-bar></tab-bar>
    </div>
  
</template>

<script>
//导入组件
import TabBar from './components/TabBar.vue'
export default {
  name: 'App',
  //注册组件
  components:{
    TabBar
  }
}
</script>

<style>
@import url('./assets/css/base.css');

</style>

但是此时TarBar又过于繁琐 它应该只管理TarBar的东西 无需管理tar-bar-item的东西

所以只需要在TarBar中定义一个插槽 tar-bar-item的东西放到APP.vue中进行渲染 如下:
TabBar.vue

<template>
  <div class="tabbar">
    <slot></slot>
  </div>
</template>

<script>
export default {

}
</script>

<style>
.tabbar{
  display: flex;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: 49px;
  background-color: #f6f6f6;
  line-height: 49px;
  font-size: 18px;
  box-shadow: 0 -2px rgba(0,0,0,.1);
}

</style>

App.vue

<template>
  <div id="app">
    <tab-bar>
    <div class="tab-bar-item"><img src="../assets/img/tabbar/home.svg" alt="">首页</div>
    <div class="tab-bar-item"><img src="../assets/img/tabbar/home.svg" alt="">分类</div>
    <div class="tab-bar-item"><img src="../assets/img/tabbar/home.svg" alt="">商城</div>
    <div class="tab-bar-item"><img src="../assets/img/tabbar/home.svg" alt="">我的</div>
    </tab-bar>
    </div>
  
</template>

<script>

import TabBar from './components/TabBar.vue'
export default {
  name: 'App',
  components:{
    TabBar
    
  }
}
</script>

<style>
@import url('./assets/css/base.css');
.tab-bar-item{
  flex: 1;
  text-align: center;
  
}
.tab-bar-item img{
    width: 24px;
    height: 24px;
}
</style>

但是很明显,此时APP.vue又过于复杂 所以我们还需要抽离成组件

新建TabBarItem组件:

//tab-bar-item的东西抽离到这里

<template>
  <div class="tab-bar-item"><img src="../assets/img/tabbar/home.svg" alt=""> 首页</div>
</template>

<script>
export default {

}
</script>

<style>
.tab-bar-item{
  flex: 1;
  text-align: center;
  
}
.tab-bar-item img{
    width: 24px;
    height: 24px;
}
</style>

App.vue

<template>
  <div id="app">
    <tab-bar>
    <tab-bar-item></tab-bar-item>
    <tab-bar-item></tab-bar-item>
    <tab-bar-item></tab-bar-item>
    <tab-bar-item></tab-bar-item>
    </tab-bar>
    </div>
  
</template>

<script>

import TabBar from './components/TabBar.vue'
import TabBarItem from './components/TabBarItem.vue'
export default {
  name: 'App',
  components:{
    TabBar,
    TabBarItem
    
  }
}
</script>

<style>
@import url('./assets/css/base.css');

</style>

此时效果
在这里插入图片描述
但是此时TabBarItem中的内容是写死的 无法改变 而且展示的都是一样的东西 所以我们需要使用插槽

TabBarItem.vue

<template>
<div class="tar-bar-item">
 	<!-- 图片插槽 -->
  <slot name="item-icon"></slot>
   <!-- 文字插槽 -->
  <slot name="item-text"></slot>
  </div>
</template>

<script>
export default {

}
</script>

<style>
.tab-bar-item{
  flex: 1;
  text-align: center;
  
}
.tab-bar-item img{
    width: 24px;
    height: 24px;
}
</style>

此时就可以在APP.vue中定义不同的内容

<template>
  <div id="app">
    <tab-bar>
    <tab-bar-item>
      <img slot="item-icon" src="./assets/img/tabbar/home.svg" alt="">
      <div slot="item-text">首页</div>
    </tab-bar-item>
    <tab-bar-item>
      <img slot="item-icon" src="./assets/img/tabbar/category.svg" alt="">
      <div slot="item-text">分类</div>
    </tab-bar-item>
    <tab-bar-item>
      <img slot="item-icon" src="./assets/img/tabbar/shopcart.svg" alt="">
      <div slot="item-text">商城</div>
    </tab-bar-item>
    <tab-bar-item>
      <img slot="item-icon" src="./assets/img/tabbar/profile.svg" alt="">
      <div slot="item-text">我的</div>
    </tab-bar-item>
    </tab-bar>
    </div>
  
</template>

<script>

import TabBar from './components/TabBar.vue'
import TabBarItem from './components/TabBarItem.vue'
export default {
  name: 'App',
  components:{
    TabBar,
    TabBarItem
  }
}
</script>

<style>
@import url('./assets/css/base.css');

</style>

此时效果
在这里插入图片描述
到此 TabBar就已经封装好了 以后要使用就可以直接在APP.vue中定义不同内容了

但是此时只有一张图片 点击时无法更换图片
所以需要在定义一个插槽 并添加图片

TabBarItem.vue

<template>
<div class="tab-bar-item">
    <!-- 图片插槽 -->
  <div v-if="!isActive"><slot name="item-icon"></slot></div>
  <!-- 点击时图片插槽 -->
  <div v-else><slot name="item-icon-active"></slot></div>
  <!-- 文字插槽 -->
  <div :class="{active:isActive}"><slot name="item-text"></slot></div>
  </div>
</template>

<script>
export default {
    data() {
        return{
            isActive:true
        }
    }

}
</script>

<style>
.tab-bar-item{
  flex: 1;
  text-align: center;
  margin-top: 3px;
  margin-bottom: 2px;
  font-size: 14px;
  vertical-align: middle;
  
}
.tab-bar-item img{
    width: 24px;
    height: 24px;
    
}
.active{
    color: red;
}
</style>

App.vue

<template>
  <div id="app">
    <tab-bar>
    <tab-bar-item>
      <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>
      <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>
      <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>
    </tab-bar-item>
    <tab-bar-item>
      <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>
    </div>
  
</template>

<script>

import TabBar from './components/TabBar.vue'
import TabBarItem from './components/TabBarItem.vue'
export default {
  name: 'App',
  components:{
    TabBar,
    TabBarItem 
  }
}
</script>

<style>
@import url('./assets/css/base.css');

</style>

插槽外面为啥加上div标签
如果不加 APP.vue中的内容会覆盖插槽 导致属性失效 加上div 覆盖插槽 也不会影响div中的属性

此时效果
在这里插入图片描述
现在进行路由配置
新建目录及文件
在这里插入图片描述
配置路由

import Vue from 'vue'
import Router from 'vue-router'

const Home = () =>
    import ('../views/Home/Home')
const Category = () =>
    import ('../views/Category/Category')
const Shopcart = () =>
    import ('../views/Shuocart/Shopcart')
const Profile = () =>
    import ('../views/Profile/Profile')

Vue.use(Router)

export default new Router({
    routes: [{
            path: '',
            redirect: '/home'
        },
        {
            path: '/home',
            component: Home

        },
        {
            path: '/category',
            component: Category
        },
        {
            path: '/shopcart',
            component: Shopcart
        },
        {
            path: '/profile',
            component: Profile
        },

    ],
    mode: 'history'
})

配置 点击事件进行页面跳转

<template>
<div class="tab-bar-item" @click="Btnclick">
    <!-- 图片插槽 -->
  <div v-if="!isActive"><slot name="item-icon"></slot></div>
  <!-- 点击时图片插槽 -->
  <div v-else><slot name="item-icon-active"></slot></div>
  <!-- 文字插槽 -->
  <div :class="{active:isActive}"><slot name="item-text"></slot></div>
  </div>
</template>

<script>
export default {
	//点击时 传过来的路径不能写死 所以需要props将路径传过来  路径在App.vue中定义
    props:{
        path:String
    },
    data() {
        return{
            isActive:true,
            
        }
    },
    methods:{
        Btnclick() {
        	//获取路径
            this.$router.push(this.path)      
        }
    }

}
</script>

<style>
.tab-bar-item{
  flex: 1;
  text-align: center;
  margin-top: 3px;
  margin-bottom: 2px;
  font-size: 14px;
  vertical-align: middle;
  
}
.tab-bar-item img{
    width: 24px;
    height: 24px;
    
}
.active{
    color: red;
}
</style>

App.vue中


<!-- 这里的path:'/home'等就是通过props传过去的路径 -->

<template>
  <div id="app">
    <router-view></router-view>
    <tab-bar>
    <tab-bar-item path="/home">
      <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">
      <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="/shopcart">
      <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>
    </tab-bar-item>
    <tab-bar-item path="/profile">
      <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>
    </div>
  
</template>

到此 点击不同tabbaritem就可以进行页面跳转

此时还有一个问题 当我不点击时 active图片还是会显示
所以要进行修改

data() {
        return{
            // isActive:true,
            
        }
    },
    computed:{
        isActive() {
            return this.$route.path.indexOf(this.path) !== -1
        }
    },

isActive不要写死

return this.$route.path.indexOf(this.path) !== -1

this.$route.path 拿到当前活跃的路由 也就是点击的路由

判断它和this.path相不相等 相等返回1

在对应

<div v-if="!isActive"><slot name="item-icon"></slot></div>
  
<div v-else><slot name="item-icon-active"></slot></div>

就可以进行点击时图片切换

此时还有一个问题 文字颜色我们设置了红色 如果修改就要进到封装好的 组件中修改
所以进行以下修改

props:{
        path:String,
        activeColor:{
            type:String,
            default:'red'
        }
    },
    data() {
        return{
            // isActive:true,
            
        }
    },
    computed:{
        isActive() {
            return this.$route.path.indexOf(this.path) !== -1
        },
        activeStyle() {
        //判断isActive是否为true 为true就activeColor false就为空
            return this.isActive ? {color:this.activeColor} : {}
        }
    },
    methods:{
        Btnclick() {
            this.$router.push(this.path)      
        }
    }
//动态绑定style
<div :style="activeStyle"><slot name="item-text"></slot></div>
//这里添加要修改的颜色
 <tab-bar-item path="/home" activeColor= "blue">

在这里插入图片描述


总结:
v-if v-else的使用

计算属性的使用

组件化抽离的思想

插槽的使用

路由的配置

props的使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值