前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue之Tabbar的实现

Vue之Tabbar的实现

作者头像
yuanshuai
发布2022-08-22 16:52:17
2.2K0
发布2022-08-22 16:52:17
举报
文章被收录于专栏:一只程序原一只程序原

Tabbar实现

一、实现思路

  最终的效果如下图所示,下面小编一一为大家解析每个部分如何实现,并附上最终的实现代码。

① 路由懒加载

  首先,肯定有两个组件组成,当点击红色组件中的“首页”、“分类”、“购物车”、“我的”这四个小标题时,就能在蓝色组件中显示相应标题的内容。这部分的实现内容可以通过路由的懒加载实现

② 插槽

  上图中的红色组件就是小编今天重点为大家介绍的 Tabbar。毫无疑问,一整个 Tabbar 应该是一个单独的组件;然后是内部的小标题。我们希望标题的数量、图标、文字都是可以灵活变通的,因此每一个标题、图标、文字我们都可以用slot 插槽来实现,插槽最终显示的内容就会被用户传递过来的数据替换掉。

综上所述,要实现 Tabbar 只需要通过路由懒加载插槽实现。下面小编先对结构和样式进行简单的编写 ⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄

二、实现代码

1. 创建项目

  通过命令行: vue init webpack tabbar 创建项目,并删除原本自带的 HelloVue.vue 文件和 App.vue 中的 template、style 自带的模板和样式。

2.结构和样式
① html结构

在模板中用4个 div 分别表示“首页”、“分类”、“购物车”、“我的”。效果如图所示:

② 样式

2.1 去除留白   首先我们会发现字体和边界有留白的部分,这个留白部分是因为自带有margin和padding,所以我们需要将这两个值设置为0px即可。   在asset中创建css文件夹,然后创建base.css文件,在base.css文件中书写下面的代码:

代码语言:javascript
复制
body{
    margin:0px;
    padding:0px;
}

接着就是在App.vue 文件中的style模块引入base.css文件:

代码语言:javascript
复制
<style>
    @import url("./assets/css/base.css");
</style>

最后查看效果图:

2.2 布局

display:我们需要将 tabbar 的内容水平排列而不是垂直排列,所以在布局上采用 flex

代码语言:javascript
复制
<template>
  <div id="tab-bar">
    <div>首页</div>
    <div>分类</div>
    <div>购物车</div>
    <div>我的</div>
  </div>
</template>

<style>
    @import url("./assets/css/base.css");
    /* 对父级 tab-bar 采用flex布局  */
    #tab-bar{
        display: flex;
    }
</style>

可以看到每个小标题已经呈水平排列。

flex:为了让每个小标题都占据相同的位置,我们需要对小标题进行均等分。因此,我们为每个小标题添加一个 tab-bar-item 的类名,然后在该类中添加 flex:1 的样式。

text-alien: 此外为了让文字能够居中,我们必须对小标题设置 text-alien:center。

height:最后为了让小标题看起来不那么矮,我们需要为小标题设置高度。一般tabbar的高度在业界中公认的是 49px

代码语言:javascript
复制
<template>
  <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>
</template>

<style>
/* 引入base.css文件 */
    @import url("./assets/css/base.css");
/* 对 tab-bar 采用 flex 布局 */
    #tab-bar{
        display: flex;
    }
/* 对 tab-bar-item 均等分 */
    .tab-bar-item{
        flex:1;
        text-align: center;
    }
</style>

在设置完上面的样式后,效果如下所示:

2.3 背景和位置

background:设置背景颜色 position:设置位置

代码语言:javascript
复制
<style>
    @import url("./assets/css/base.css");
    #tab-bar{
        display: flex;
        background: #f6f6f6;
        position: fixed;
/* 为了让 tabbar 占据整个页面的宽度,最好设置 left 和 rigth为0 */
        left: 0px;
        right: 0px;
        bottom: 0px;
    }
</style>
2.4 阴影

box-shadow:为了让 tabbar 和界面的过渡更加自然,我们需要为 tabbar 添加阴影。

代码语言:javascript
复制
<style>
    @import url("./assets/css/base.css");
    #tab-bar{
        display: flex;
        background: #f6f6f6;
        position: fixed;
        left: 0px;
        right: 0px;
        bottom: 0px;
        box-shadow: 0px -1px 7px rgb(100,100,100,0.2);
    }
</style>

最后附加上今天整套的代码:

代码语言:javascript
复制
<template>
  <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>
</template>

<script>


export default {
  name: 'App',
  components: {
    
  }
}
</script>

<style>
    @import url("./assets/css/base.css");
    #tab-bar{
        display: flex;
        background: #f6f6f6;
        position: fixed;
        left: 0px;
        right: 0px;
        bottom: 0px;
        box-shadow: 0px -1px 7px rgb(100,100,100,0.2);
    }
    .tab-bar-item{
        flex:1;
        text-align: center;
        height:49px;
    }
</style>

知识小卡片1--flex:

① 定义

意为”弹性布局”,为盒状模型提供最大的灵活性。在设为Flex布局以后,子元素的float、clear和vertical-align属性将失效。

② 相关概念:

2.1 容器:采用Flex布局的元素,称为Flex容器(flex container),简称”容器”,比如上面例子中是 tab-bar。

2.2 项目:容器内的所有子元素自动成为容器成员,称为Flex项目(flex item),简称”项目”。比如上面例子中的 tab-bar-item。

2.3 轴:容器默认存在两根轴,水平主轴垂直交叉轴。主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;交叉轴的开始位置叫做cross start,结束位置叫做cross end。   项目默认沿主轴排列。单个项目占据的主轴空间叫做main size,占据的交叉轴空间叫做cross size。

③ 属性

3.1 flex-direction:决定主轴的方向,即项目的排列方向 主要语法是:flex-direction: row | row-reverse | column | column-reverse   四个值分别代表:row-主轴为水平方向,起点在左端;row-reverse -主轴为水平方向,起点在右端;column-主轴为垂直方向,起点在上沿;column-reverse-主轴为垂直方向,起点在下沿

3.2 flex-wrap:决定项目是否换行。 主要语法是:flex-wrap: nowrap | wrap | wrap-reverse;   三个数值分别代表:nowrap-不换行;wrap-换行并且第一行在上面;wrap-reverse-换行并且第一行在下面

**3.3 flex-flow:**是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。 主要语法是:flex-flow:

3.4 justify-content:定义了项目在主轴上的对齐方式。 主要语法是:justify-content: flex-start | flex-end | center | space-between | space-around;   五个数值分别代表:flex-start-左对齐;flex-end-右对齐;center-居中;space-between-两端对齐,项目之间的间隔都相等;space-around-每个项目两侧的间隔相等

3.5 align-item:定义项目在交叉轴上如何对齐。 主要语法格式是: align-items: flex-start | flex-end | center | baseline | stretch;   五个参数分别是:flex-start-交叉轴的起点对齐;flex-end-交叉轴的终点对齐;center-交叉轴的中点对齐;baseline-项目的第一行文字的基线对齐;stretch(默认值)-如果项目未设置高度或设为auto,将占满整个容器的高度。

3.6 align-content:定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。 主要语法是:align-content: flex-start | flex-end | center | space-between | space-around | stretch;   六个数值分别是:flex-start-与交叉轴的起点对齐;flex-end-与交叉轴的终点对齐;center-与交叉轴的中点对齐;space-between-与交叉轴两端对齐,轴线之间的间隔平均分布;space-around-每根轴线两侧的间隔都相等。stretch(默认值)-轴线占满整个交叉轴

知识小卡片2-- box-shadow

① 定义 :为盒子增加阴影
② 语法:box-shadow: h-shadow v-shadow blur spread color inset
③ 参数解析

  h-shadow-水平偏移量,v-shadow-垂直偏移量,blur-模糊程度,spread -阴影的范围大小,color-阴影的颜色,inset-阴影的方向,inset是内阴影,outset是外部阴影

④ 注意事项

  偏移量的数值可以是正数也可以是负数;当为正数时,水平方向往右偏移,垂直方向往下偏移,因为偏移的源点在整个窗口的左上角。

Tabbar实现版之组件抽取

一、组件抽取

  上一篇的文章中,我们将Tabbar的模板和样式都写在了App.vue文件中,这样写的缺点是:不利于代码的重复利用。所以我们需要将模板和样式都抽取出来,放在一个单独的文件中,然后在App.vue引用该文件即可。比如:

代码语言:javascript
复制
<!-- tabbar.vue-->
<template>
    <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>
</template>

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

<style>
    #tab-bar{
        display: flex;
        background: #f6f6f6;
        position: fixed;
        left: 0px;
        right: 0px;
        bottom: 0px;
        box-shadow: 0px -1px 7px rgb(100,100,100,0.2);
    }
    .tab-bar-item{
        flex:1;
        text-align: center;
        height:49px;
    }
</style>
代码语言:javascript
复制
<!-- App.vue -->
<template>
    <div id="App">
        <tabbar></tabbar>
    </div>
</template>

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

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

二、插槽

  但是上面tabbar组件中,不仅仅包含tabbar本身的模板和样式,还包含了tabbar-item的模板和样式,所以下一步我们最好将tabbar和tabbar-item抽离出来。

代码语言:javascript
复制
<!-- 抽取过后的 tabbar -->
<template>
    <div id="tab-bar">
        <slot></slot>
    </div>
</template>

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

<style>
    #tab-bar{
        display: flex;
        background: #f6f6f6;
        position: fixed;
        left: 0px;
        right: 0px;
        bottom: 0px;
        box-shadow: 0px -1px 7px rgb(100,100,100,0.2);
    }
</style>

<!-- 加入tabbar-item后的 App.vue-->
<template>
    <div id="App">
        <tabbar>
            <div class="tab-bar-item">
                <img src="./assets/img/tabbar/home.png" alt="">
                <div>首页</div>
            </div>
            <div class="tab-bar-item">
                <img src="./assets/img/tabbar/home.png" alt="">
                <div>分类</div>
            </div>
            <div class="tab-bar-item">
                <img src="./assets/img/tabbar/home.png" alt="">
                <div>购物车</div>
            </div>
            <div class="tab-bar-item">
                <img src="./assets/img/tabbar/home.png" alt="">
                <div>我的</div>
            </div>
        </tabbar>
    </div>
</template>

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

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

在tabbar组件中,有关tabbar-item的模板和样式全部抽取到 App.vue中,就实现了tabbar和tabbar-item分离的目的.但是此时又造成另外一个问题,tabbar-item和App.vue混合了,所以我们最好再创造一个组件,将tabbar-item的相关模板和样式抽取到一块。比如:

代码语言:javascript
复制
<!-- 单独的 tabbar-item zujian-->
<template>
    <div class="tab-bar-item">
        <img src="../../assets/img/tabbar/home.png" alt="">
        <div>首页</div>
    </div>
    </div>
</template>

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

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

<!-- 抽取tabbar-item后的App-->
<template>
    <div id="App">
        <tabbar>
            <tabbarItem></tabbarItem>
            <tabbarItem></tabbarItem>
            <tabbarItem></tabbarItem>
            <tabbarItem></tabbarItem>
        </tabbar>
    </div>
</template>

<script>
import tabbar from "./components/Tabbar/tabbar.vue"
import tabbarItem from "./components/Tabbar/tabbar-item.vue"
export default {
  name: 'App',
  components: {
    tabbar,
    tabbarItem
  }
}
</script>

这里逻辑可能比较混乱的是App在引用tabbar-item的时候。我们已经将tabbar-item抽取成了一个单独的组件,也就表示,每引用一次的就使用了一个小的文字加图片。引用了四次就有了四个文字和图片。效果如下图所示:

以上两步就完成了tabbar和tabbat-item的分离,紧接着就是将tabbat-item内的文字和图标写活。

三、插槽实现数据灵活变通

  在上面我们可以知道,在 tabbar-item 的template中书写什么,就会显示什么,但是我们并不希望将数据写死,而是希望来什么数据就用数据,这个特点和插槽很像,插槽就相当于一个空的标签,你来什么文字和图片,插槽就会被该文字和图片替代,所以第一步是将 tabbar-item 显示数据的地方用插槽替代,代码如下:

代码语言:javascript
复制
<template>
    <div class="tab-bar-item">
        <slot name="item-icon"></slot>
        <slot name="item-text"></slot>
        <!-- <img src="./assets/img/tabbar/home.png" alt="">
        <div>首页</div> -->
    </div>
</template>

然后,当我们在 App.vue 中引入tabbarItem标签,就意味着我们调用了一次 tabbar-item组件,而tabbar-item组件中slot的内容就由tabbarItem标签的内部决定,比如 :

代码语言:javascript
复制
<template>
    <div id="App">
        <tabbar>
            <tabbarItem>
                <img slot="item-icon" src="./assets/img/tabbar/home.png" alt="">
                <div slot="item-text">首页</div>
            </tabbarItem>
            <tabbarItem>
                <img slot="item-icon" src="./assets/img/tabbar/phone.png" alt="">
                <div slot="item-text">分类</div>
            </tabbarItem>
            <tabbarItem>
                <img slot="item-icon" src="./assets/img/tabbar/4.png" alt="">
                <div slot="item-text">购物车</div>
            </tabbarItem>
            <tabbarItem>
                <img slot="item-icon" src="./assets/img/tabbar/my.png" alt="">
                <div slot="item-text">我的</div>
            </tabbarItem>
        </tabbar>
    </div>
</template>

这样便实现了数据的灵活性,不需要考虑个数,不需要考虑样式,不需要考虑结构,因为所有的样式,结构已经在组件tabbar-item中实现了,你尽管的大胆放心的使用便是。

  以上就是有关Tabbar 实现的组件抽取,总体思路是 现将tabbar 和tabbar-item分离,分别用两个组件单独的设计tabbar和tabbar-item的结构和样式,然后就是通过插槽来实现数据的灵活处理。

Tabbar传入active图片和文字

一、实现active图片

1.定义

  为了避免大家误会,在这里解释一下什么是active图片。简单的说,就是某张图片没有被点击之前是白色的,被点击之后就变成黑色,而被点击之后变成黑色的图片就是active图片,因为被点击了,所以是处于活跃状态的。

2.思路

  active图片的思路是一开始就传入了所有图片,当用户没有点击时显示图片1,当用户点击之后就显示图片2 而并不是当用户点击时才传入图片。

3.实现过程

  根据上面的思路,我们知道在tabbar-item中应该再多使用一个插槽来存放图片,然后通过设置标志位和v-if语句来判断该显示哪张图片。比如:

代码语言:javascript
复制
<!-- tabbar-item -->
<template>
    <div class="tab-bar-item">
        <slot v-if="!isActive" name="item-icon"></slot>
        <slot v-else name="item-icon-active"></slot>
        <slot name="item-text"></slot>
    </div>
</template>

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

当然了,相应的 App.vue 组件也应该增加多一个 img 标签来存放活跃状态下的图片。比如:

代码语言:javascript
复制
<tabbarItem>
        <img slot="item-icon" src="./assets/img/tabbar/home.png" alt="">
        <img slot="item-icon-active" src="./assets/img/tabbar/home2.png" alt="">
        <div slot="item-text">首页</div>
</tabbarItem>

上两个代码中,name 为 item-icon-active 是新增加的插槽,用来存放活跃状态下的图片。v-if语句通过 isActive 标志位的值来判断显示哪张图片,当 isActive 的值为真,显示活跃状态的图片,结果如图所示:

二、实现active文字

1.定义

  active文字呢,也是和上面的active图片一个道理。当用户点击某段文字时,该文字的样式就会发生改变。

2.思路

  思路和active图片的思路是类似,设置一个变化样式的类,通过设置标志位来增加该类。

3.实现过程

  首先声明一个类,在该类中书写文字有关的样式,然后通过 标志位的值来判断是否要添加该类。比如:

代码语言:javascript
复制
<!--为了便于理解和观察,小编为大家伙清除了和文字无关的任何一切 O(∩_∩)O哈哈~-->
<template>
    <div class="tab-bar-item">
        <slot :class="{active:isActive}" name="item-text"></slot>
    </div>
</template>
<style>
    .active{
        color: red;
    }
</style>

上述的代码,表示当 isActive 为真时,就为插槽添加类名为active的类,然后文字的颜色就会由原来的黑色变成红色。我们来看效果:

但是我们发现文字的颜色并没有发生任何的变化。这是为什么呢?   这个跟插槽被替换有关。上述代码中,我们将 active 类添加在了插槽中是行不通的,因为插槽最终会被 App.vue组件中的

首页

替换,也就相当于 active类其实并没有被添加到文字所在的div中。

 我们的解决思路很简单,就是在slot外面在裹上div,把active类添加到div上即可,比如:

代码语言:javascript
复制
<div :class="{active:isActive}">
    <slot name="item-text"></slot>
</div>

最终呈现的效果如下所示:

同理,我们也在图片的 slot 外层裹上div,将相应的语法添加到外层的div上,所以本次最终实现的代码如下所示:

代码语言:javascript
复制
<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 {
        name:'tabbarItem',
        data(){
              return {
                  // 判断图片是否处于激活状态的标志位
                  isActive:true
              }
        }
    }
</script>

<style>
    .tab-bar-item{
        flex:1;
        text-align: center;
        height:49px;
    }
    .tab-bar-item img{
        width: 30px;
        height: 25px;
    }
    /* 文字处于激活状态下的样式 */
    .active{
        color: red;
    }
</style>

以上便是今天Tabbar中实现active图片和文字的主要代码和思路,总结如下:

1.active图片是一开始就传入所有的图片,然后根据不同的条件显示不同的图片,而并不是真正使用时才传入的

2.随着图片的数量的增加,也需要添加相应的插槽数量

3.通过设置标志位和 if 判断语句来决定显示那张图片

4.通过标志位来决定文字的样式是否发生改变

5.最后为了避免插槽被替换而导致添加的类名无效,一般在插槽外层包裹一层的div,然后将类、if语句都放到div中。

Tabbar链接路由

一、搭建路由基本框架

  在终端,通过命令 npm install vue-route --save 为项目安装路由,然后创建route文件夹来存放和路由有关的组件,紧接着创建index.js文件,在该文件中搭建路由的基本框架。   搭建路由的基本框架步骤如下:1.引入路由 --> 2.安装插件 --> 3.创建路由对象 --> 4.导出路由。其代码如下所示:

代码语言:javascript
复制
// 1.import 引入路由
import Vue from 'vue'
import VueRouter from "vue-router"

// 2.安装插件
Vue.use(VueRouter)

// 3.创建路由对象
//将router实例中的routes抽取出来写
const routes = [
    
]
const router = new VueRouter({
    routes
})

// 4.导出路由
export default router

二、路由配置

在上面搭建好的框架基础上,我们对路由的映射关系进行配置。 ① 创建目录   为什么要强调这点呢?为了以后做项目的时候,更加方便管理自己的代码,不至于因为项目过于庞大而找不到自己相关页面代码。   首先创建 view 文件夹,该文件夹主要放和视图有关的代码;然后在view文件夹下在分别创建 home、category、car、profile 四个文件夹,这四个文件夹分别放置和 home、category、car、profile有关的代码文件,具体的文件目录如下所示:

②配置路由映射关系   我们通过路由懒加载的方式来建立tabbar-item和各个大组件之间的联系 配置步骤如下:1.引入文件 --> 2.配置映射关系。其代码如下:

代码语言:javascript
复制
//index.js 文件
//① 引入文件 
const Home  = () => import ('../view/home/home.vue')
const Car  = () => import ('../view/car/car.vue')
const Category  = () => import ('../view/category/category.vue')
const Profile  = () => import ('../view/profile/profile.vue')

// ② 配置映射关系
const routes = [
    {
        path:"",
        redirect:"/home"
    },
    {
        path:"/home",
        component:Home
    },
    {
        path:"/category",
        component:Category
    },
    {
        path:"/car",
        component:Car
    },
    {
        path:"/profile",
        component:Profile
    }
]

在上面的配置关系中,首先通过路由懒加载的方式,只有当某个页面被激活时才会从服务器中下载下来,提高了运行效率;   接着是当path为空时,就显示首页的信息,让用户一进来就显示首页的信息,而不是需要用户点击tabbar-item的“首页”才显示首页的信息,显得更加的合理;   最后就是tabbar-item各个子标题的配置。比如当用户点击了“购物车”就会跳转到购物车的页面。   以上两步就是路由框架的搭建和映射关系的配置过程,接下来我们希望用户点击下面的tabbar-item时就会发生跳转,所以我们还需要在增加点击事件。

三、点击事件

1.目的

  添加点击事件的目的很简单,就是希望用户点击“首页”时,上面的内容就变成和首页相关的内容。

2.步骤

① 添加点击事件   如果我们将点击事件添加到App.vue 文件的 标签中,就需要添加四个点击事件,显然不够高效,所以我们将点击事件添加到 tabbar-item.vue文件中的

标签中,其代码如下所示:

② 事件的处理 关于事件的处理会比较麻烦,小编从下面几点为大家分析分析: 2.1 监听是否成功   首先我们得要确定在tabbar-item添加的点击事件是成功的,所以在用户点击相应的tabbart-item小标题的时候在控制台打印“11”就证明点击事件是添加成功的。其代码和效果如下所示:

代码语言:javascript
复制
methods:{
    itemClick(){
        console.log('11')
    }
}

2.2 链接跳转   我们知道,路由的链接跳转是通过**this.$router(参数)**来实现的,小编这里要重点分析的就是参数。   参数肯定不能是被写死的,因为当用户点击不同的tabbar-item时,传递的跳转链接也是不一样的。所以我们通过 props属性来声明path变量,并且该变量的类型是String类型,其代码如下所示:

代码语言:javascript
复制
props:{
    path:String
},

methods:{
    itemClick(){
        this.$router.replace(this.path)
    }
}

那么path具体的数值来自哪里呢?就来自 App.vue文件中的tabbart-item标签,比如:

当用户点击了哪个tabbar-item就传递哪个tabbar-item的链接过去。 2.3 内容的显示   为了让内容显示出来,我们要添加**占位标签 **这是很容易忘记的。

最终显示的效果图如下:

完整代码演示:

代码语言:javascript
复制
<!--tabbar-item代码-->
<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 :class="{active:isActive}">
            <slot name="item-text"></slot>
        </div>
    </div>
</template>

<script>
    export default {
        name:'tabbarItem',
        props:{
            path:String
        },
        data(){
              return {
                  isActive:false
              }
        },
        methods:{
            itemClick(){
                console.log('111')
                this.$router.push(this.path);
            }
        }
    }
</script>

<style>
    .tab-bar-item{
        flex:1;
        text-align: center;
        height:49px;
    }
    .tab-bar-item img{
        width: 30px;
        height: 25px;
    }
    /* 文字处于激活状态下的样式 */
    .active{
        color: red;
    }
</style>
代码语言:javascript
复制
//index.js 

// 1.import 引入路由
import Vue from 'vue'
import VueRouter from "vue-router"

//① 引入文件 
const Home  = () => import ('../view/home/Home')
const Car  = () => import ('../view/car/Car')
const Category  = () => import ('../view/category/Category')
const Profile  = () => import ('../view/profile/Profile')

// 2.安装插件
Vue.use(VueRouter)

// 3.创建路由对象
// ② 配置映射关系
const routes = [
    {
        path:"",
        redirect:"/home"
    },
    {
        path:"/home",
        component:Home
    },
    {
        path:"/category",
        component:Category
    },
    {
        path:"/car",
        component:Car
    },
    {
        path:"/profile",
        component:Profile
    }
    
]
const router = new VueRouter({
    routes,
    mode:'history'
})

// 4.导出路由
export default router
代码语言:javascript
复制
<!-- App.vue-->
<template>
    <div id="App">
        <router-view></router-view>
        <tabbar>
            <tabbarItem path='/home'>
                <img slot="item-icon" src="./assets/img/tabbar/home.png" alt="">
                <img slot="item-icon-active" src="./assets/img/tabbar/home2.png" alt="">
                <div slot="item-text">首页</div>
            </tabbarItem>
            <tabbarItem path='/category'>
                <img slot="item-icon" src="./assets/img/tabbar/phone.png" alt="">
                <img slot="item-icon-active" src="./assets/img/tabbar/phone2.png" alt="">
                <div slot="item-text">分类</div>
            </tabbarItem>
            <tabbarItem path='/car'>
                <img slot="item-icon" src="./assets/img/tabbar/4.png" alt="">
                <img slot="item-icon-active" src="./assets/img/tabbar/5.png" alt="">
                <div slot="item-text">购物车</div>
            </tabbarItem>
            <tabbarItem path='/profile'>
                <img slot="item-icon" src="./assets/img/tabbar/my.png" alt="">
                <img slot="item-icon-active" src="./assets/img/tabbar/my2.png" alt="">
                <div slot="item-text">我的</div>
            </tabbarItem>
        </tabbar>
    </div>
</template>

<script>
import tabbar from "./components/Tabbar/tabbar.vue"
import tabbarItem from "./components/Tabbar/tabbar-item.vue"
import router from "./router/index.js"
export default {
  name: 'App',
  components: {
    tabbar,
    tabbarItem
  }
}
</script>

<style>
    @import url("./assets/css/base.css");
</style>
代码语言:javascript
复制
//main,js
import Vue from 'vue'
import App from './App'
import router from './router'

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,
  render: h => h(App)
})

Tabbar 动态颜色控制

一、计算属性

1.图片动态颜色

① 不动态的原因   回顾之前的知识,我们是通过设置标志位 isActive 的true 和 false 的值来决定图片和文字的活跃状态,显示isActive不是动态的,很难满足我们的要求,所接下来我们就要对isActive进行劳改 ⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄ ②解决方法   大致的思路是,通过计算属性computed来声明isActive,然后通过this.$route来决定isActive的值,具体代码如下:

代码语言:javascript
复制
//tabbar-item.vue
data(){
    return {
         // isActive:false
      }
},
computed:{
    isActive(){
        return this.$route.path.indexOf(this.path) !== -1
    }
}

上述代码中,用 this.$route.path 获取当前活跃状态下的路由的path,通过活跃状态下的路由的path来查找item中的path,没有找到就返回-1。所以总结上面的代码就是:当活跃状态下的路由的path在item中找到相应的path就返回-1,以为着此时的isActive结果为true。我们来看看效果图:

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021.11.30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Tabbar实现
    • 一、实现思路
      • 二、实现代码
        • 知识小卡片1--flex:
          • 知识小卡片2-- box-shadow
          • Tabbar实现版之组件抽取
            • 一、组件抽取
              • 二、插槽
                • 三、插槽实现数据灵活变通
                • Tabbar传入active图片和文字
                • 一、实现active图片
                  • 二、实现active文字
                  • Tabbar链接路由
                    • 一、搭建路由基本框架
                    • 二、路由配置
                      • 三、点击事件
                        • 完整代码演示:
                        • Tabbar 动态颜色控制
                          • 一、计算属性
                          相关产品与服务
                          容器服务
                          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                          领券
                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档