[Vue learning notes _16] case - Tabbar navigation bar

This case combines the previous knowledge points such as slot slot and Vue router front-end routing. The most important thing is to reflect the idea of component packaging.

Supporting executable code example = > GitHub

Project file structure

  • assets /: static resources, css, img, etc
  • Components /: common components
  • pages /: page component. Next, set a directory for each page
  • router /: route configuration
  • App.vue: root component
  • main.js: entry file

This case encapsulates a public Tabbar component under components / because navigation bars may be required on multiple pages.

Effect display & component structure

Encapsulate TabBar

TabBarItem.vue

The smallest element of the navigation bar.

The selected icon, unselected icon and text all use the form of slot to improve reusability.

The path path corresponding to the navigation bar element and the text style activeColor when selected all use the props attribute to allow users to pass in, which is also to improve reusability.

According to whether the current active route contains the path transmitted by props, judge whether the current < route View > displays the page component corresponding to the navigation bar element, so as to determine whether to display the icon when it is selected or not, as well as the text style.

Bind the click event and use code jump to route to the page component corresponding to the navigation bar element.

Note: class and other attributes cannot be directly bound to the slot, because the entire slot will be replaced when used, and the attribute cannot take effect. It is not recommended to bind v-if and other instructions. You can set a div outside the slot, and then bind attributes or instructions on the 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 :style="activeStyle" >
      <slot name="item-text"></slot>
    </div>
  </div>
</template>

<script>
  export default {
    name: "TabBarItem",
    props: {
      path: String,
      activeColor: {
        type: String,
        default: 'red'
      }
    },
    computed: {
      isActive() {
        //Judge whether the current active route contains the path transmitted by props
        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: 1;
    text-align: center;
    height: 49px;
    font-size: 14px;
    margin-top: 3px;
  }
  .tab-bar-item img {
    width: 24px;
    height: 24px;
    vertical-align: middle;
    margin-bottom: 2px;
  }
</style>

TabBar.vue

Add a layer of packaging for TabBarItem to unify layout and style.

<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 -1px 1px rgba(100,100,100,0.15);
  }
</style>

Use encapsulated TabBar

MainTabBar.vue

At the MainTabBar level, it is already business-related. The outermost layer uses < tab bar >, insert four < tab bar item >, corresponding to the four navigation bar elements of home page, category, shopping cart and me respectively, and insert the corresponding selected icon, unselected icon, text, and pass in path and activeColor attributes into each < tab bar item >.

<template>
  <div id="main-tab-bar">
    <tab-bar>
      <tab-bar-item path="/home" activeColor="red">
        <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">home page</div>
      </tab-bar-item>
      <tab-bar-item path="/category" activeColor="red">
        <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">classification</div>
      </tab-bar-item>
      <tab-bar-item path="/shopcart" activeColor="red">
        <img slot="item-icon" src="../../assets/img/tabbar/shopcart.svg" alt="">
        <img slot="item-icon-active" src="../../assets/img/tabbar/shopcart_active.svg" alt="">
        <div slot="item-text">Shopping Cart</div>
      </tab-bar-item>
      <tab-bar-item path="/profile" activeColor="red">
        <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">my</div>
      </tab-bar-item>
    </tab-bar>
  </div>
</template>

<script>
  import TabBar from '../tabbar/TabBar'
  import TabBarItem from '../tabbar/TabBarItem'

  export default {
    name: "MainTabBar",
    components: {
      TabBar,
      TabBarItem
    }
  }
</script>

<style scoped>
</style>

App.vue

Use < main tab bar > in the root component, side by side with the page component displayed by < router View >.

<template>
  <div id="app">
    <router-view></router-view>
    <main-tab-bar></main-tab-bar>
  </div>
</template>

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

Configure routing

router/index.js

Configure the correspondence between page components and paths.

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

const Home = () => import('../pages/home/Home')
const Category = () => import('../pages/category/Category')
const ShopCart = () => import('../pages/shopcart/ShopCart')
const Profile = () => import('../pages/profile/Profile')

//1. Install the routing plug-in
Vue.use(Router)

//2. Create routing object
const routes = [
  {
    path: '',
    redirect: '/home'
  },
  {
    path: '/home',
    component: Home
  },
  {
    path: '/category',
    component: Category
  },
  {
    path: '/cart',
    component: ShopCart
  },
  {
    path: '/profile',
    component: Profile
  }
]
const router = new Router({
  routes,
  mode: 'history'
})

//3. Export route
export default router

File directory configuration alias

You can configure aliases for file directories in build/webpack.base.conf.js to facilitate referencing files in the project:

module.exports = {
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      '@': resolve('src'),
      'assets': resolve('src/assets'),
      'components': resolve('src/components'),
      'pages': resolve('src/pages'),
    }
  }
}

Tags: Javascript Front-end Vue

Posted on Sun, 28 Nov 2021 17:23:45 -0500 by shelbytll