TabBar实例练习

TabBar实例练习

跟着视频做的一个小demo
代码连接:
链接:https://pan.baidu.com/s/14qAgi-ZADsXXn5YhPh5O7Q
提取码:rt3n

1.新建一个vuecli2-tabbar实例

在这里插入图片描述

2.先搭建最基本的框架

主页文字包括:首页、分类、购物车、我的。这几个持水平分布
App.vue文件中导入基本的组件:

<template>
  <div id="app">
    <div id="tab-bar">
      <div class="tab-bar-item">首页</div>
      <div class="tab-bar-item">分类</div>
      <div class="tab-bar-item">购物车</div>
      <div class="tab-bar-item">我的</div>
    </div>
  </div>
</template>

样式直接在App.vue文件内导入:
其中导入的css文件是在assets文件夹下建的css文件夹,再建一个base.css文件,写入最基本的样式,再导入到App.vue文件中
base.css代码如下:

body{
    margin:0;
    padding:0;
}

App.vue样式代码如下:

<style>
  /* 导入css文件 */
  @import "./assets/css/base.css";
  /* 实现水平分布 */
  #tab-bar{
    display:flex;
    /* 添加背景颜色 */
    background-color: #f6f6f6;

    /* 将文字设置到页面底部 */
    position:fixed;
    left:0;
    right: 0;
    bottom: 0;

    /* 界面和文字过渡部分添加阴影 */
    box-shadow: 0 -1px 1px rgb(100,100,100,0.1);
  }
  /* 等分分布 给每个分类都设置一个类*/
  .tab-bar-item{
    flex:1;
    /* 居中 */
    text-align: center;
    /* 设置高度 一般都设置为49*/
    height: 49px;
  }
</style>

最后效果:
在这里插入图片描述

3.封装成独立的组件

以上方法没有复用性,为了将整个模块可以成为插件直接使用,需要对每个部分进行封装(升级)。
首先分离出一个TabBar.vue文件
在这里插入图片描述
图片和文字内容最后替换到slot的插槽里。
代码部分:

<template>
    <div id="tab-bar">
      <slot></slot>
    </div>
</template>

<script>
export default {
    
}
</script>

<style scoped>
    /* 实现水平分布 */
    #tab-bar{
        display:flex;
        /* 添加背景颜色 */
        background-color: #f6f6f6;

        /* 将文字设置到页面底部 */
        position:fixed;
        left:0;
        right: 0;
        bottom: 0;

        /* 界面和文字过渡部分添加阴影 */
        box-shadow: 0 -1px 1px rgb(100,100,100,0.1);
  }
    
</style>

文字和图片的内容再分离出一个文件TabBarItem.vue,以下是代码部分:
这里有关于图片和文字的样式但是具体内容需要动态获取,所以再放一个插槽。需要动态的获取图片和文字,此时就要用到插槽slot

<template>
    <div class="tab-bar-item">
        <!-- 图片和文字不要写死 可以放一个插槽在这 -->
        <slot name="item-icon"></slot>
        <slot name="item-text"></slot>
         <!-- <img src="../../assets/img/tabbar/home.svg" alt="">
        <div>首页</div> -->
    </div>
</template>

<script>
export default {
    name:'TabBarItem'
}
</script>

<style scoped>
    /* 等分分布 给每个分类都设置一个类*/
    .tab-bar-item{
        flex:1;
        /* 居中 */
        text-align: center;
        /* 设置高度 一般都设置为49*/
        height: 49px;
        /* 调整文字大小 */
        font-size: 14px;

    }

    /* 设置图片的大小 */
    .tab-bar-item img {
        height:24px;
        width: 24px;
        /* 图片距上面有一定空间 */
        margin-top: 3px;
        /* 调整图片和文字中间距离 */
        vertical-align:middle;
    }
</style>

先将具体的图片和文字放到App.vue 代码中:(注意对这两个子组件的导入和使用,并且图片和文字会排到一层,但我们需要上下展示,所以需要一个层级关系,将文字用div包裹一下)

<template>
  <div id="app">
    <!-- 3.使用 -->
    <tab-bar>
      <!-- 要往这个插槽里面填内容 有几个内容就要写几个item-->
      <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/cart.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>
// 1.导入
import TabBar from "./components/tabbar/TabBar.vue"
import TabBarItem from "./components/tabbar/TabBarItem.vue"

export default {
  name: 'App',
  components:{
    // 2.注册
    TabBar,
    TabBarItem
  }
}
</script>

<style>
  /* 导入css文件 */
  @import "./assets/css/base.css";
  
</style>

目前结果:
在这里插入图片描述

4.效果切换

目的:实现处于活跃状态时,图片和文字都为红色,可以设置一个状态isActive,为true时,是活跃状态。
相当于要传入两张图片在一个地方,设置其类,处于某一个状态就显示对应的样式。需要在原来一张图片的插槽上再插入一个插槽:<slot name="item-icon-active"></slot>,在App.vue中加入相应的具体图片,例如:

<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>

TabBarItem.vue中添加相应的方法:

<script>
export default {
    name:'TabBarItem',
    data(){
        return{
            isActive:true
        } 
    }
}
</script>

TabBarItem.vue设中置组件:
注意:1.绑定样式不要在插槽中修改,用一个div包裹起来,在div上设置属性 2.用 v-if 和 v-else 来选择其状态
在这里插入图片描述
具体代码如下:

<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内-->
        <div :class="{active:isActive}">
            <slot  name="item-text"></slot>
        </div>
         <!-- <img src="../../assets/img/tabbar/home.svg" alt="">
        <div>首页</div> -->
    </div>
</template>

5.路由跳转

实现点击下部导航栏出现相应的导航栏内容,路由跳转

5.1在src文件夹下新建一个文件夹views,在views文件夹下再新建四个对应的文件夹,再创建vue文件,如下图所示:

在这里插入图片描述
Home.vue代码如下:

<template>
    <div>
        <h2>首页</h2>
    </div>
</template>

<script>
export default {
    name:"Home"
}
</script>

<style scoped>

</style>
5.2在router文件夹的index.js文件中导入这几个路由
// 导入每个路由
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:'/cart',
    component: Cart
  },
  {
    path:'/profile',
    component: Profile
  }
]

此时,不同路由已经导入到index文件中

5.3监听点击事件

点击下部导航栏跳转到不同的路由界面。
TabBarItem.vue文件中,先监听点击事件,如下图红圈部分:
在这里插入图片描述
通过输入的路径获得此时需要跳转的路由,在TabBarItem.vue 事件触发:
(注意其中有一个报错,看网上资料在this.$router.replace(this.path).catch(err =>err) 加上 .catch这部分就不会报错)

<script>
export default {
    name:'TabBarItem',
    props:{
        path: String
    },
    data(){
        return{
            isActive:false
        } 
    },
    methods:{
        itemClick(){
            this.$router.replace(this.path).catch(err =>err)
            // console.log("123")
        }
    }
}

此时,在App.vue文件中需要传入不同的路径:
下面代码的path='/home'部分:

<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>

现在就可以实现点击下列导航栏实现路由跳转。

6.封装字体颜色

字体颜色之前设置的固定值,要动态传入颜色,分活跃时和不活跃时的状态。

TbaBarItem.vue文件中,添加传入颜色的属性,

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

并且通过三元运算符实现:处于活跃状态时,使用这个活跃的颜色:

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

再绑定这个属性:

 <div :style="activeStyle">
            <slot  name="item-text"></slot>
  </div>

整体代码:

<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>
        <!-- 动态改变文字颜色 因为插槽会被替换掉,因此将样式设置到div内-->
        <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'
        }
    },
    computed:{
        isActive(){
            return this.$route.path.indexOf(this.path) !== -1
        },
        activeStyle(){
            return this.isActive? {color:this.activeColor} : {}
        }
    },
    data(){
        return{
            // isActive:false
        } 
    },
    methods:{
        itemClick(){
            this.$router.replace(this.path).catch(err =>err)
            // console.log("123")
        }
    }
}
</script>

<style scoped>
    /* 等分分布 给每个分类都设置一个类*/
    .tab-bar-item{
        flex:1;
        /* 居中 */
        text-align: center;
        /* 设置高度 一般都设置为49*/
        height: 49px;
        /* 调整文字大小 */
        font-size: 14px;

    }

    /* 设置图片的大小 */
    .tab-bar-item img {
        height:24px;
        width: 24px;
        /* 图片距上面有一定空间 */
        margin-top: 3px;
        /* 调整图片和文字中间距离 */
        vertical-align:middle;
    }

    /* 文字处于活跃状态时为红色 */
    /* .active{
        color: red;
    } */
</style>

7.App.vue组件抽离

之前传入图片和具体文字都是再App.vue的template中传入,此时需要把这部分再抽离出来。
需要注意每个部分要导入的组件,以及图片的路径也需要更改。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值