Vue封装一个Tabbar组件 带组件路由跳转方式

目录
  • Vue封装Tabbar组件
    • 在App.vue 封装 路由跳转 利用router-view的特性
    • 子组件Tabbar
    • 然后就是配置的路由
  • 从零开始封装一个Tabbar
    • 首先底部菜单栏最外层是一个div,
    • 代码如下
    • 封装完每一个tabbaritem后
    • 使用者在使用我们封装的控件时

Vue封装Tabbar组件

话不多说直接上代码

在App.vue 封装 路由跳转 利用router-view的特性

<template>
  <div id="app">
    <router-view />
    //引入子组件 把items 这个数组传进去
    <Tabr :items="items" />
  </div>
</template>
<script>
import Tabr from "./components/Tabr";
export default {
  components: {
    Tabr,
  },
  data() {
    return {
      items: [
        {
          title: "首页",
          path: "/",
          img: require("./assets/img/shouye.png"),
          imgs: require("./assets/img/shouye_1.png"),
        },
        {
          title: "分类",
          path: "/About",
          img: require("./assets/img/fenlei.png"),
          imgs: require("./assets/img/fenlei_1.png"),
        },
        {
          title: "购物车",
          path: "/Cart",
          img: require("./assets/img/gouwuchezhengpin.png"),
          imgs: require("./assets/img/gouwuchezhengpin_1.png"),
        },
        {
          title: "我的",
          path: "/Mime",
          img: require("./assets/img/wode.png"),
          imgs: require("./assets/img/wode_1.png"),
        },
      ],
    };
  },
};
</script>

子组件Tabbar

<template>
  <div class="Yanxuan_tab">
    <div v-for="(item,index) in items" :key="index" @click="Onclick(index)">
      <div>
        <img :src="index===Tabindex?item.imgs:item.img" alt  />
        //动态绑定
      </div>
      <div :class="index===Tabindex?'title':'Yanxuan_title'">
      //
      {{item.title}}</div>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    items: {
      type: Array,
      required: true,
      validator: function (value) {
        return value.length <= 6;
        //市面常见的Tabbar的栏 不能超过6个
      },
    }
  },
  data() {
      return {
          item:this.items,
          Tabindex:0
      }
  },
  methods:{
     Onclick(index){
     //这里是根据下标切换 图片样式跟字体颜色 动态绑定
       this.Tabindex = index
       var temp = this.item[index]
      this.$router.push(temp.path)
     }
  }
};
</script>
<style scoped>
.Yanxuan_tab {
  width: 100%;
  height: 64px;
  border: 1px solid gainsboro;
  position: fixed;
  bottom: 0px;
  left: 0px;
  display: inline-flex;
  justify-content: space-around;
  align-items: center;
  text-align: center;
 
}
.Yanxuan_title{
     font-size: 14px;
}
.title{
    font-size: 14px;
    color:red
}
</style>

然后就是配置的路由

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
  const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home,
    meta:{
      isShowTabbar:true
    }
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
    meta:{
      isShowTabbar:true
    }
  }
  ,
  {
    path: '/Cart',
    name: 'Cart',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/Cart.vue'),
    meta:{
      isShowTabbar:false
    }
  },
  {
    path: '/Mime',
    name: 'Mime',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/Mime.vue'),
    meta:{
      isShowTabbar:true
    }
  },
]
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})
export default router

最后的效果完成图

代码就直接可以用了

从零开始封装一个Tabbar

首先底部菜单栏最外层是一个div,

在div中整体上存在四个或五个小div,每个div中包含icon和text,如下图

对于每一个icon对象,它包含图标以及文字,但十实际中我们肯定不会将img和text写死,以及处于active状态时text的颜色也不会写死,以方便调用者传入想要的参数,这样才算一个彻底的封装。

代码如下

<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 :style="activeStyle">
      <slot name="item-text"></slot>
    </div>
    
  </div>
</template>
 
<!--
    上方代码设置三个插槽,为什么不是两个呢,因为还要包含当item处于活跃状态时要显示的image,所以是三个,使用v-if控制当非活跃时显示默认icon插槽,活跃时显示亮色icon插槽。因为插槽是要被传入其中的内容覆盖的,所以传入的内容可能会将我们slot中的一些属性覆盖掉,所以常常我们需要将slot包裹在div中,这样就可以避免这个问题。
    icon下方文同理也放在div中,style绑定一个计算属性,看下方代码可以这个计算属性当item处于活跃时会返回颜色属性,当然这个属性也是可以在调用tab-bar时传入的,默认为红色。
-->
<script>
  export default {
    name:'TabBarItem',
    props:{
      path: String,  // 当前item对应的路由,由调用者指定
      activeColor:{  // 当前item的文字在活跃时的颜色,默认红色,可由使用者指定
        type:String,
        default:"red"
      }
    },
    data() {
      return {
        // isActive:false,
      }
    },
    computed:{
      // 判断当前item是否处于活跃状态
      isActive(){
        return this.$route.path.indexOf(this.path)!==-1;
      },
      // 计算属性,如果处于活跃状态则设置style,否则去除style
      activeStyle(){
        return this.isActive? {color:this.activeColor}:{};
      }
    },
    methods:{
      itemClick(){
        if(this.$route.path!==this.path){
          this.$router.push(this.path);
          // this.isActive = true;
        } 
      }
    }
  }
</script>
<style scoped>
<!--一些默认样式-->
  .tab-bar-item {
    flex: 1;
    text-align: center;
    height: 49px;
    font-size: 10px;
  }
  .tab-bar-item img {
    margin-top: 4px;
    width: 22px;
    height: 22px;
    vertical-align: middle;
    margin-bottom: 2px;
  }
</style>

封装完每一个tabbaritem后

接下来是整体的tabbar,试想,我们肯定还是放入一个插槽代码如下:

<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: 0px -2px 1px rgba(100, 100, 100, 0.1);
}
 
</style>

tabbar预留的插槽则用于放入每一个item,我们在这里也是不能写死的,因为控件开发者并不知需要放入多少个item。

使用者在使用我们封装的控件时

则可以如下代码,放入内容:

<template>
  <tab-bar>
      <tab-bar-item path="/home" activeColor="deepPink">
        <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" activeColor="deepPink">
        <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="/cart" activeColor="deepPink">
        <img slot="item-icon" src="~assets/img/tabbar/cart.svg" alt="">
        <img slot="item-icon-active" src="~assets/img/tabbar/cart_active.svg" alt="">
        <div slot="item-text">购物车</div>
      </tab-bar-item>
      <tab-bar-item path="/profile" activeColor="deepPink">
        <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>
  
</template>
<script>
  import TabBar from "components/tabbar/TabBar";
  import TabBarItem from "components/tabbar/TabBarItem";
  export default {
    name:'MainTabBar',
    components:{
      TabBar,
      TabBarItem
    }
  }
</script>
<style scoped>
</style>

到此结束。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • vue.js移动端tab组件的封装实践实例

    这是vue.js系列文章第二遍,第一篇讲述的是如何搭建vue.js的开发环境,计划按进度做成一款完整的app,当然前提是时间允许的话.本文用到了stylus语法,至于为什么使用stylus而不去用sass,主要是因为stylus来自于Node.js社区.总之stylus是一款高效的CSS预处理器,具体使用不在本文讨论范围.好了,废话不说了,下面讲述怎么封装tababr的切换. 底部tab进行页面切换,会用到vue里面的路由,也就是vue-router 我们在安装vue-cli时选中默认安装vu

  • vue组件tabbar使用方法详解

    本文实例为大家分享了vue组件tabbar的具体使用方法,供大家参考,具体内容如下 1.App.vue <!-- 入口文件 --> <template> <div id="app"> <!-- 视图层 --> <router-view></router-view> <!-- 底部选项卡 --> <tabbar @on-index-change="onIndexChange" v

  • vue实现tab路由切换组件的方法实例

    前言 本文介绍的是使用vue自带的vue-router.js路由实现分页切换功能,下面话不多说了,来一起看看详细的实现代码吧 实现图片如下 下列为实现代码 css: *{ margin: 0; padding: 0; } #app ul{ width: 300px; height: 30px; list-style: none; } #app>ul>li{ width: 100px; height: 30px; float: left; } html: <div id="app

  • vue封装TabBar组件的完整步骤记录

    目录 实现思路: 步骤一:TabBar和TabBarItem的组件封装 步骤二:给TabBarItem传入active图片 步骤三:TabBarItem和路由的结合效果 步骤四:TabBarItem的颜色控制 用字体图标实现 引入字体图标 运用 总结 实现思路: 步骤一:TabBar和TabBarItem的组件封装 做到这,可以发现页面的基本布局已经实现了,但是item的点击活跃状态还没实现 步骤二:给TabBarItem传入active图片 为了防止替换的内容直接整个替换掉插槽,从而插槽上定义

  • vue封装一个图案手势锁组件

    目录 说在前面 效果展示 预览地址 实现步骤 1.组件设计 2.组件分析 3.组件实现 4.组件使用 组件库引用 源码地址 组件文档 说在前面 现在很多人都喜欢使用图案手势锁,这里我使用vue来封装了一个可以直接使用的组件,在这里记录一下这个组件的开发步骤. 效果展示 组件实现效果如下图: 预览地址 http://jyeontu.xyz/jvuewheel/#/JAppsLock 实现步骤 完成一个组件需要几步? 1.组件设计 首先我们应该要知道我们要做怎样的组件,具备怎样的功能,这样才可以开始

  • Vue封装一个Tabbar组件 带组件路由跳转方式

    目录 Vue封装Tabbar组件 在App.vue 封装 路由跳转 利用router-view的特性 子组件Tabbar 然后就是配置的路由 从零开始封装一个Tabbar 首先底部菜单栏最外层是一个div, 代码如下 封装完每一个tabbaritem后 使用者在使用我们封装的控件时 Vue封装Tabbar组件 话不多说直接上代码 在App.vue 封装 路由跳转 利用router-view的特性 <template>   <div id="app">     &

  • Vue实现封装一个切片上传组件

    目录 组件效果 使用文档 封装过程 1. 文件切片 2. 构造切片请求参数 3. 控制分片请求的并发 完整代码 待完善 组件效果 单文件切片上传 多文件切片上传 组件使用案例 <template> <div id="app"> <div class="upload-wrap"> <UploadSlice :action="uploadInfoSlice.actionChunk" :headers=&quo

  • vue封装一个弹幕组件详解

    目录 前言 功能实现 1.获取随机颜色 随机数生成 随机颜色编码生成 2.随机生成弹幕出现的高度坐标 3.格式化弹幕对象 颜色 定位 4.创建弹幕对象 滚动动画定义 创建弹幕dom对象实例 弹幕销毁 弹幕循环 5.实时弹幕发送 html JavaScript 源码地址 前言 现在很多地方都有使用到弹幕,最近在捣鼓自己的个人博客网站,也想着在里面加入一个弹幕模块,所以在这里封装了一个可复用的弹幕组件,目前已经实现了基本的功能,可能还会有存在缺陷,后续会继续优化.这里给大家介绍分享一下实现的过程.

  • Vue实现一个返回顶部backToTop组件

    最近在学习VUE.自己就在研究怎么用VUE实现一个组件的封装,今日就算留个笔记 前言 返回顶部这个功能用jq实现,好容易实现,一个animate配合scrollTo就搞定了 今天我们来试试vue封装一个原生js实现的返回顶部; 写起来够呛,借助github,看了别人的gist,稍微封装了下; 当然不是用scrollTo直接调位那种,没有过渡效果怎么说得过去!!还是捣鼓出来了. 废话不多说,看效果图- 效果图 实现思路 过渡用的是requestAnimationFrame,这货只支持IE10+,所

  • Vue封装远程下拉框组件的实现示例

    之前封装了一个远程搜索的输入框,静态在Vue官网看到一个类似的远程搜索下拉框,今天也封装一个远程搜索下拉框,面对不同的需求 我们修改了官方提供的代码来封装了 父组件 RemoteSearch.vue <template> <el-row> <el-select v-if="chooseFlag ==0" v-model="selectKey" :multiple="false" :filterable="t

  • vue设计一个倒计时秒杀的组件详解

    简介: 倒计时秒杀组件在电商网站中层出不穷  不过思路万变不离其踪,我自己根据其他资料设计了一个vue版的 核心思路: 1.时间不能是本地客户端的时间  必须是服务器的时间这里用一个settimeout代替 以为时间必须统一 2.开始时间,结束时间通过父组件传入,当服务器时间在这个开始时间和结束时间的范围内  参加活动按钮可以点击,并且参加过活动以后不能再参加, 3.在组件创建的时候 同步得到现在时间服务时间差,并且在这里边设置定时器,每秒都做判断看秒杀是否开始和结束, 4.在更新时间的函数中是

  • Vue 封装防刷新考试倒计时组件的实现

    本文详细的介绍了防刷新考试倒计时组件 ,分享给大家,也给自己留个笔记,感兴趣的可以了解下 <!-- 考试倒计时组件 --> <template> <div class="time"> <p>00:{{timerCount2}}:{{timerCount1}}</p> <button @click="reset">重新计时</button> </div> </temp

  • Vue封装一个TodoList的案例与浏览器本地缓存的应用实现

    本文主要介绍了Vue封装一个TodoList的案例与浏览器本地缓存的应用实现,分享给大家,具体如下: 使用Vue封装一个简易的Todolist的小案例. 同时加入了浏览器本地缓存的技术手段. 浏览器本地缓冲: 前提: 一般我们定义的变量,或者用Vuex保存的数据, 当浏览器进行了一个刷新 那么这个数据就会丢失, 这样就做不出历史记录的效果了, 但是, 使用浏览器缓存就可以帮助我们解决这个问题- 浏览器缓存分为二种 sessionStorage 和 localStorage, 二种原型链分别如下:

  • Vue路由跳转方式区别汇总(push,replace,go)

    目录 声明式导航router-link 1. 不带参数 2.带参数 编程式导航 1.this.$router.push 2.this.$router.replace 3.this.$router.go(n) 总结区别: 在浏览器中,点击链接实现导航的方式,叫做声明式导航.例如:普通网页中点击 a标签链接.vue项目中点击router-link标签链接都属于声明式导航.在浏览器中,调用API方法实现导航的方式,叫做编程式导航.例如:普通网页中调用location.href跳转到新页面的方式,属于编

随机推荐