tabbar的组件封装

tabbar的组件封装

在这里插入图片描述

对于组件的抽离,我们可以进行分析,整个下部分选项卡,肯定是可复用的,不同地方都要使用,我们将TabBar抽离成一个组件。

接下来,那么我们选项卡数目是否固定呢,内容是否固定呢,答案肯定是不,我们选项卡不能写死,也抽离出来每一个单独的,每一个选项为一个单独的item

那我如何确定它在TabBar里边有多少个item呢,那就使用插槽,预留出一个位置,开发者实际需要几个item就使用几个。

每个item其是又是图片和文字组成,我们也不能直接写死,留下具名插槽,分别对应文字和图片。

我们下标的图片肯定有两个状态,活跃和不活跃状态,那么图片传入,就用两个具名插槽,使用v-if来进行控制显示,字体也是的

TarBar.vue
<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: 0 -3px 1px rgba(100, 100, 100, 0.2);
  }


</style> 
TarBarItem.vue
<template>
  <div class="tab-bar-item">
    <div v-if="!isActive">
      <slot name="item-icon"></slot>
    </div>
    <div v-else>
      <slot name="item-active-icon"></slot>
    </div>
    <div v-bind:class="{active:isActive}">
      <slot name="item-text"></slot>
    </div>
  </div>
</template>

<script>
  export default {
    name: "TabBarItem",
    data() {
      return {
        isActive:true
      }
    }
  }
</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;
  }

  .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-active-icon" 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-active-icon" 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-active-icon" 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-active-icon" 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/TabBar";
  import TabBarItem from "./components/tabbar/TabBarItem";
  export default {
    name: 'App',
    components:{
      TabBar,
      TabBarItem
    }
  }
</script>

<style>
  @import "./assets/css/base.css";

</style>

其实还可以将app.vue里的内容进一步抽离,这样app.vue里更加简介。

item与路由切换
import Vue from 'vue'
import VueRouter from 'vue-router'


Vue.use(VueRouter)

const routes = [
  {
    path: '',
    redirect: '/home'
  },
  {
    path: '/home',
    component: () => import(/* webpackChunkName: "home"*/ '../views/home/Home'),
  },
  {
    path: '/cart',
    component: () => import(/* webpackChunkName: "cart"*/ '../views/cart/Cart'),
  },
  {
    path: '/category',
    component: () => import(/* webpackChunkName: "category"*/ '../views/category/Category'),
  },
  {
    path: '/profile',
    component: () => import(/* webpackChunkName: "profile"*/ '../views/profile/Profile'),
  }

]

const router = new VueRouter({
  routes,
  mode:'history'
})

export default router

采用路由懒加载方式,注释是为了打包文件名字不采用哈希值,增加mode来设置路由方式为history模式而非hash值

我们每次点击不同的选项跳转不同的页面,不可能每个页面都写一个跳转函数,那么其实我们每个不同的按钮,都是同一个组件,那么我们直接把该组件绑定上路由跳转方法

那么不同的按钮跳转的目的路由不同,我们必须要实时接收到目的路由进行跳转,我们在app里使用的item组件,就涉及到父子组件之间通信。

子组件定义用于接受的path

props:{
    path:String
},

在父组件里给这个path赋值

<tab-bar-item path="/home">

不使用动态绑定的原因,原本这些路径都是固定的字符串,直接赋值给path即可,子组件自然可以接收到。

在这里插入图片描述

接下来就颜色问题,单击才会变色

我们不可能直接把颜色写死,哪个按钮被点击,也就是对应路由处于活跃状态,我们之前使用过父传子的path属性此刻也可以使用

item组件里设置计算属性

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

$route获取的是当前活跃的路由,我们次使用item组件创建的不同按钮,其对应的path都不同,我们用活跃的路由的path,和其他所有不同组件里的path比较,哪个路由里包含这个路径,说明其处于活跃

indexOf方法是字符串查找,返回第一次出现该字符串的位置,如果没有返回-1

增加一个需求自定义文字颜色

我们有的时候颜色并不是固定的,可以根据用户选择来涉资自己的文字颜色

首先还是在item组件props里定义接受样式的对象

activeColor:{
  type:String,
  default:'red'
}

如果用户选择就是用用户颜色,否则默认红色。

然后在父组件里调用子组件时传入对应样式

<tab-bar-item path="/home" activeColor="blue">

在item里动态绑定对应样式的计算属性

activeStyle() {
  return this.isActive ? {color:this.activeColor}:{}
}

将样式抽离成计算属性,通过判断是否活跃来设置对应的style

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值