教你用vue2实现一个tabbar(2024年11月教程)

简介: 欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。自学前端2年半,正向全栈进发。博客分享技术心得,助你成长。关注我,获取更多优质内容,你的支持是我前进的动力!🎉🎉🎉

🎉🎉🎉欢迎来到我的博客,我是一名自学了2年半前端的大一学生,熟悉的技术是JavaScript与Vue.目前正在往全栈方向前进, 如果我的博客给您带来了帮助欢迎您关注我,我将会持续不断的更新文章!!!🙏🙏🙏

@[toc]

1. 实现Tab-Bar思路

  1. 下方单独的Tab-Bar组件如何封装?
    • 自定义Tab-Bar组件,在APP中使用
    • Tab-Bar位置在底部,并设置你需要的样式
  2. Tab-Bar中显示的内容由外部决定
    • 定义插槽
    • flex布局平分Tab-Bar
  3. 自定义Tab-Bar-Item,可以传入图片和文字
    • 定义Tab-Bar-Item,并定义两个插槽:图片和文字
    • 给插槽外层包装div,设置样式
    • 填充插槽,实现底部Tab-Bar的效果
  4. 传入高亮图片
    • 定义另一个插槽,插入active-icon的数据
    • 定义一个变量isActicve,通过v-show来决定是否显示对应的icon
  5. Tab-Bar-Item绑定路由数据
    • 安装路由:npm install vue-router --save
    • router/index.js配置路由信息,并创建对应的组件
    • main.js中注册router
    • App.vue中使用router-linkrouter-view
  6. 点击item跳转到对应的路由,并且动态决定isActive
    • 监听item的点击,通过this.$router.replace()替换路由路径
    • 通过this.$route.path.indexOf(this.link)!==-1来判断是否使active
  7. 动态计算active样式
    • 封装新的计算属性:this.isActive?{'color': 'red'}:{}

2. 代码实现

使用vue init webpack 02-vue-router-tabbar-v1新建一个项目工程(使用vuecli2)。

  1. 在文件夹assest下新建css/base.css,用于初始化css

    base.css

   body {
   
     padding: 0;
     margin: 0;
   }

修改App.vue,添加初步样式

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

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

   <style>
       /* style中引用使用@import */
     @import url('./assets/css/base.css');

     #tar-bar {
       display: flex;
       background-color: #f6f6f6;

       position: fixed;
       left: 0;
       right: 0;
       bottom: 0;

       box-shadow: 0 -1px  1px rgba(100, 100, 100, .2);
     }

     .tar-bar-item {
       flex: auto;
       text-align: center;
       height: 49px;
       font-size: 20px;
     }
   </style>

使用npm run dev,查看网页效果

                                               ![](https://img-blog.csdnimg.cn/img_convert/d2bcac64e250c41047295ecc0ec2a609.png)

思考:如果每次都要复用tabbar,那每次都需要复制粘贴,应该要把tabbar抽离出来,vue就是组件化思想。

  1. 将tabbar抽离成组件

    在components下新建tabbar文件夹,新建TarBar.vueTabBarItem.vue,TabBarItem组件是在组件TarBar中抽取出来的,可以传入图片和文字(比如首页),所有需要使用插槽<slot>代替。

    TarBar.vue

   <template>
          <div id="tab-bar">
            <!-- 插槽代替tabbaritem -->
            <slot></slot>
          </div>
      </template>
      <script type="text/ecmascript-6">
      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 -1px  1px rgba(100, 100, 100, .2);
         }
    </style>

TabBar弄一个slot插槽用于插入TabBarItem组件(可能插入多个).

TabBarItem.vue

<template>
    <div class="tab-bar-item">
      <!-- item-icon表示图片插槽 item-text表示文字插槽,例如首页 -->
      <slot name="item-icon"></slot>
      <slot name="item-text"></slot>
    </div>
</template>
<script type="text/ecmascript-6">
  export default {
    name: 'TabBarItem'
  }
</script>
<style scoped>
  .tab-bar-item {
    flex: auto;
    text-align: center;
    height: 49px;
    font-size: 14px;
  }
  .tab-bar-item img {
    height: 24px;
    width: 24px;
    margin-top: 3px;
    vertical-align: middle;
    margin-bottom: 2px;
  }
</style>

TabBarItem组件中插入2个插槽一个用于插入图片一个用于插入文字。

MainTabBar.vue

<template>
  <div class="main-tab-bar">
    <TabBar>
      <TabBarItem path="/home" activeColor="blue">
        <img slot="item-icon" src="~assets/img/tabbar/home.png" alt="" srcset="">
        <template v-slot:item-text>
          <div>首页</div>
        </template>
      </TabBarItem>
      <TabBarItem path="/categories">
        <template #item-icon>
          <img src="~assets/img/tabbar/categories.png" alt="" srcset="">
        </template>
        <template #item-text>
          <div>分类</div>
        </template>
      </TabBarItem>
      <TabBarItem path="/shop">
        <template #item-icon>
          <img src="~assets/img/tabbar/shopcart.png" alt="" srcset="">
        </template>
        <template #item-text>
          <div>购物车</div>
        </template>
      </TabBarItem>
      <TabBarItem path="/me">
        <template #item-icon>
          <img src="~assets/img/tabbar/profile.png" alt="" srcset="">
        </template>
        <template #item-text>
          <div>我的</div>
        </template>
      </TabBarItem>
    </TabBar>
  </div>
</template>
<script type="text/ecmascript-6">
  import TabBar from "@/components/tabbar/TabBar"
  import TabBarItem from "@/components/tabbar/TabBarItem"
  export default {
    name: "MainTabBar",
    components: {
      TabBar,
      TabBarItem
    }
  }
</script>
<style scoped>
</style>

在MainTabBar组件中加入另外2个组件。

注意此处使用~assets@/components是使用了别名配置,详情请看3.别名配置

最后在app.vue中导入MainTabBar组件。

<template>
  <div id="app">
    <MainTabBar></MainTabBar>
  </div>
</template>
<script>
  import MainTabBar from '@/components/MainTabBar'
  export default {
    name: 'App',
    components: {
      MainTabBar
    }
  }
</script>
<style>
    /* style中引用使用@import */
  @import url('./assets/css/base.css');
</style>

效果如图所示,将组件进行了分离重组,只要修改MainTabBar组件就可以修改图片和文字描述,可以复用。

  1. 如何实现点击首页首页字体变红图片变红色

    这里需要用到路由的active-class

    思路:引用2张图片,一张是正常颜色一张是红色,使用v-ifv-else来处理是否变色,在路由处于活跃状态的时候,变红色。

    引入路由使用路由就不细说了,这里仅贴上tabbar的修改代码。

    TabBarItem.vue组件

    <template>
        <div class="tab-bar-item" :style="activeStyle" @click="itemClick">
          <!-- item-icon表示图片插槽 item-text表示文字插槽,例如首页 -->
          <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 type="text/ecmascript-6">
      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} : {}
          }
        },
        methods: {
          itemClick(){
            this.$router.push(this.path)
          }
        }
      }
    </script>
    
    <style scoped>
      .tab-bar-item {
        flex: auto;
        text-align: center;
        height: 49px;
        font-size: 14px;
      }
    
      .tab-bar-item img {
        height: 24px;
        width: 24px;
        margin-top: 3px;
        vertical-align: middle;
        margin-bottom: 2px;
      }
    </style>
    
  1. 使用props获取传递的值,这里传递是激活颜色,默认是红色
  2. 设置计算属性isActiveactiveStyle,分别表示激活状态和激活的样式
  3. 定义itemClick()方法用于获取点击事件,点击后使用代码实现路由跳转,这里使用默认的hash模式
  4. 使用v-ifv-else来进行条件判断

    MainTabBar.vue组件

       <TabBarItem path="/home">
         <img slot="item-icon" src="~assets/img/tabbar/home.png" alt="" srcset="">
         <img slot="item-icon-active" src="~assets/img/tabbar/home_active.png" alt="" srcset="">
         <template v-slot:item-text>
           <div>首页</div>
         </template>
       </TabBarItem>
    

    添加激活状态的图片与未激活的图片并列。

  1. 配置路由信息,参考之前的代码

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

Vue.use(Router)

const routes = [
{
path: '/',
redirect: '/home'//缺省时候重定向到/home
},
{
path: '/home',
component: () => import ('../views/home/Home.vue')
},
{
path: '/categories',
component: () => import ('../views/categories/Categories.vue')
},
{
path: '/shop',
component: () => import ('../views/shop/Shop.vue')
},
{
path: '/profile',
component: () => import ('../views/profile/Profile.vue')
},
]

export default new Router({
routes,
// linkActiveClass:"active"
})


   ![](https://img-blog.csdnimg.cn/img_convert/ae74ed82b3195905237cf13507385c9e.png)

5. 修改main.js和App.vue

   ```js
   import Vue from 'vue'
   import App from './App'
   import router from './router'

   Vue.config.productionTip = false

   /* eslint-disable no-new */
   new Vue({
     el: '#app',
     router,
     render: h => h(App)
   })
   <template>
     <div id="app">
       <router-view></router-view>
       <MainTabBar></MainTabBar>
     </div>
   </template>

   <script>
     import MainTabBar from '@/components/MainTabBar'
     export default {
       name: 'App',
       components: {
         MainTabBar
       }
     }
   </script>

   <style>
       /* style中引用使用@import */
     @import url('./assets/css/base.css');

   </style>

3. 别名配置

经常的我们向引入图片文件等资源的时候使用相对路径,诸如../assets/xxx这样的使用../获取上一层,如果有多个上层就需要../../xxx等等这样不利于维护代码。此时就需要一个能获取到指定目录的资源的就好了。

配置

webpack.base.config中配置使用别名,找到resolve:{}模块,增加配置信息

  resolve: {
   
    extensions: ['.js', '.vue', '.json'],
    alias: {
   
      '@': resolve('src'),
      'assets': resolve('src/assets'),
      'components': resolve('src/components'),
      'views': resolve('scr/views')
    }
  },

这里@指定目录是src,例如@/components表示src/components目录,assets表示src/assets前缀,如果是assets/img就表示src/assets/img目录。

Hi👋,这里是瑞雨溪一个喜欢JavaScript和Vue的大学生,如果我的文章给你带来的帮助,欢迎您关注我,我会持续不断的更新更多优质文章.你的关注就是我的动力!!!🎉🎉🎉

相关文章
|
6月前
|
JavaScript
vue实现瀑布流
vue实现瀑布流
|
6月前
|
JavaScript
Vue 项目使用 iconfont
Vue 项目使用 iconfont
201 0
|
3月前
|
JavaScript
Vue3瀑布流(Waterfall)
这是一个基于 Vue2 的瀑布流(Waterfall)组件,支持多种自定义属性,如图片数组、列数、间隙、宽度、圆角、背景色及 Spin 加载样式。组件通过计算每张图片的位置实现动态布局,并利用 Vue 的响应式系统自动调整布局。提供了在线预览和详细代码示例,方便集成到项目中。
Vue3瀑布流(Waterfall)
|
3月前
|
JavaScript
基于Vue3实现简约型侧边栏
本文介绍了如何在Vue3项目中实现一个简约型侧边栏导航,包括配置路由、页面布局和导航交互,以及如何通过Vue Router和条件渲染实现动态内容展示。
537 1
|
3月前
在Vue3项目中使用 vue3-seamless-scroll 无缝滚动插件
本文介绍了如何在Vue3项目中使用`vue3-seamless-scroll`插件实现无缝滚动效果,并提供了详细的示例代码和运行效果。
1405 0
|
4月前
|
JavaScript
【vue】 vue2 中使用 Tinymce 富文本编辑器
【vue】 vue2 中使用 Tinymce 富文本编辑器
562 6
|
4月前
【vue2】vue2 实现手风琴效果,复制粘贴直接使用
【vue2】vue2 实现手风琴效果,复制粘贴直接使用
152 1
|
4月前
|
JavaScript
Vue 轮播图
Vue 轮播图
41 4
|
5月前
Vue3——tdesign-vue-next如何按需加载动态渲染ICON
如题,在vue3中进行按需加载来动态的渲染icon图标;
63 1
|
6月前
|
存储 JavaScript 前端开发
用Vue写一个简单好看的菜单组件(Vue实战系列)
用Vue写一个简单好看的菜单组件(Vue实战系列)
524 2