Bottom navigation bar for Vue development

Posted by zbert on Fri, 29 Nov 2019 08:50:45 +0100

1. Navigation Switching

Encapsulate a common component, Tabbar, to include components in pages that require navigation pages.The code is as follows:

<template>
  <div class="tabbar">
	<!-- Place holder -->
	<div class="placegolder-container"></div>
	<!-- Bottom navigation bar -->
	<div class="bottom-tabs">
	  <div class="tabs-item" v-for="(item, index) in tabsList" :key="index" @click="tabsChange(index)" >
		<img class="tab-icon" :src="tabIndex==index?item.src:item.src1">
		<p class="tab-text" :class="tabIndex==index?'active':''">{{item.text}}</p>
	  </div>
	</div>
  </div>
</template>

<script>
export default {
  name: "tabbar",
  components: {},
  created() {
	this.tabIndex = localStorage.getItem("tabIndex");
	console.log(this.tabIndex, "222222222222222");
  },
  data() {
	return {
	  tabIndex: 0,
	  tabsList: [
		{
		  src: require("../../assets/icon/home.png"),
		  src1: require("../../assets/icon/home1.png"),
		  text: "home page",
		  path: "/"
		},
		{
		  src: require("../../assets/icon/brand.png"),
		  src1: require("../../assets/icon/brand1.png"),
		  text: "gift",
		  path: "/Gift"
		},
		{
		  src: require("../../assets/icon/find.png"),
		  src1: require("../../assets/icon/find1.png"),
		  text: "find",
		  path: "/Test"
		},
		{
		  src: require("../../assets/icon/my.png"),
		  src1: require("../../assets/icon/my1.png"),
		  text: "My",
		  path: "/UploadFile"
		}
	  ]
	};
  },
  methods: {
	tabsChange(index) {
	  this.tabIndex = index;
	  this.$router.push({
		path: this.tabsList[index].path
	  });
	  console.log(this.tabsList[index].path);
	  localStorage.setItem("tabIndex", this.tabIndex);
	}
  },
  watch: {
	$route(newVal, oldVal) {
	  // console.log(newVal, oldVal);
	  if (newVal.meta.index >= 0) {
		this.tabIndex = newVal.meta.index;
		localStorage.setItem("tabIndex", this.tabIndex);
	  }
	}
  }
};
</script>


<style scoped lang="less">
.tabbar {
  height: 70px;
  position: fixed;
  bottom: 0;
  left: 0;
}
.placegolder-container {
  height: 70px;
}

.bottom-tabs {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 5;
  display: flex;
  flex-direction: row;
  justify-content: space-around;
  align-items: center;
  box-shadow: 0px -1px 1px #e6e6e6;
  background-color: #fff;

  .tabs-item {
	padding: 5px 0;
	flex: 1;
	height: 60px;
	display: flex;
	flex-direction: column;
	justify-content: space-around;
	align-items: center;

	.tab-icon {
	  width: 30px;
	  height: 30px;
	  border-radius: 4px;
	}

	.tab-text {
	  font-size: 14px;
	  margin: 0;

	  &.active {
		color: #624980;
	  }
	}
  }
}
</style>

Be careful:

  • Page placeholders are set to offset the fixed positioning height of the bottom navigation bar.
  • tabIndex marks the currently selected route.
  • tabsChange(index) bottom navigation bar routing switch.
  • watch listens for route changes and maintains the resident (checked/activated) style of the route selection.

2. Cache usage

  • Why use caching?What is cached?
  • A: The cache is used to save the tabIndex of the selected route, which remains (checked/activated) when the page is refreshed.

3. Routing Configuration and Monitoring

(1) Configuration

When configuring routes, we can add meta objects, which add the attributes you need, and get meta values for route switching. For example, meta.needLogin specifies that no login is required to enter a route

{
	  path: '/',
	  name: 'Home',
	  meta: { index: 0, title: 'home page',needLogin: false },
	  component: Home
	},
	{
	  path: '/Gift',
	  name: 'Gift',
	  meta: { index: 1, title: 'gift' },
	  component: Gift
	},
	{
	  path: '/Test',
	  name: 'Test',
	  meta: { index: 2, title: 'find',needLogin: true },
	  component: Test,
	  children:[
		{
		  path: '/title1',
		  name: 'Title1',
		  component: Title1
		},
		{
		  path: '/title2',
		  name: 'Title2',
		  component: Title2
		},
		{
		  path: '/title3',
		  name: 'Title3',
		  component: Title3
		}
	  ]
	}, 
	{
	  path: '/UploadFile',
	  name: 'UploadFile',
	  meta: { index: 3, title: 'My' },
	  component: UploadFile
	},

(2) Monitoring

  • The purpose of using monitoring is to maintain the resident (checked/activated) style of routing checks when using the browser forward and backward.

    watch: {
      $route(newVal, oldVal) {
        // console.log(newVal, oldVal);
        if (newVal.meta.index >= 0) {
      	this.tabIndex = newVal.meta.index;
      	localStorage.setItem("tabIndex", this.tabIndex);
        }
      }
    }
    

4. Modify page titles dynamically and increase routing interception

(1) When modifying the title of a page, we can use the title property of the configuration route to control it.

//main.js

import store from "./store/index";

// Used to do some page entry restrictions, i.e. route interception
router.beforeEach((to, from, next) => {
  console.log({ to, from })
  /*Routing changed Modify title of page */
  if (to.meta.title) {
	document.title = to.meta.title
  }else{
	document.title = "Little fish bud"
  }
  /*Determine if a route requires permission to enter */
  if(to.meta.needLogin){
	if(store.state.person.userInfo.userId){ //Get userId from vuex
	  next()
	}else{
	  next({path:'/login'})
	}
  }
  next();
})

(2) Add a module person.js to the modules under the store, then use vuex to complete a userId

const state = {
  userInfo: {
	userId: 11,
  },
};
// getters
const getters = {
  userInfo: (state) => state.userInfo
};

// actions
const actions = {
  UpdatePerson({ commit }, userInfo) {
	commit("UpdatePerson", userInfo);
  },
};

// mutations
const mutations = {

  UpdatePerson(state, userInfo) {
	// Change status
	state.userInfo=userInfo
  },
};

export default {
  state,
  getters,
  actions,
  mutations
};

(3) Create a new index.js in the store directory which introduces the person module through the modules property.

import Vue from "vue";
import Vuex from "vuex";
import actions from "./actions";
import getters from "./getter";
import createPersistedState from "vuex-persistedstate";
import person from "./modules/person";

Vue.use(Vuex);

const state = {};

export default new Vuex.Store({
  state,
  mutations,
  actions,
  getters,
  modules: {
	person,
  },
  strict: debug,
  plugins: [createPersistedState({ storage: window.sessionStorage })]
});

5. Component References

Reference subcomponents in pages that require bottom navigation, as follows

import Tabbar from './common/Tabbar';//Reference subcomponents
//Register Components
components: {
	"Tabbar":Tabbar
},

//Add to bottom of html structure
<!-- Bottom Menu -->
<Tabbar />

VI. Effect Charts

Note: The project code address is https://gitee.com/xiaoyuleilei/vue-cli_demo

Topics: Front-end Vue less