超詳細(xì)教程實(shí)現(xiàn)Vue底部導(dǎo)航欄TabBar
項(xiàng)目介紹:
需求:要求tabbar中的文字可動(dòng)態(tài)更改,文字對應(yīng)的圖片動(dòng)態(tài)更改動(dòng)態(tài)增加,文字顏色對應(yīng)更改,TabBarItem的圖片動(dòng)態(tài)更改和增加,整個(gè)項(xiàng)目靈活化,利用插槽,路由,父子組件的值傳遞,利用$router實(shí)現(xiàn)點(diǎn)擊item就會(huì)顯示對應(yīng)的頁面。綜合性極強(qiáng),項(xiàng)目開發(fā)中遇到類似項(xiàng)目,只需復(fù)制其中主要代碼即可搭建項(xiàng)目的大體框架。
項(xiàng)目目錄:


TabBar效果預(yù)覽:

TabBar實(shí)現(xiàn)思路
一、如果在下方有一個(gè)單獨(dú)的TabBar組件,如何封裝
- 自定義tabbar組件,在APP中使用。
- 讓TabBar處于底部,并且設(shè)置相關(guān)的樣式。
二、TabBar中現(xiàn)實(shí)的內(nèi)容由外界決定。
- 定義插槽。
- flex布局評分TabBar。
三、自定義TabBarItem,可以傳入圖片和文字
- 自定義tabbarItem,并且定義兩個(gè)插槽:圖片,文字。
- 給兩個(gè)插槽外層包裝div,用于設(shè)置樣式。
- 填充插槽,實(shí)現(xiàn)底部TabBar的效果。
方法可行,動(dòng)手實(shí)現(xiàn),首先介紹一下目錄
項(xiàng)目文件目錄建立


文件目錄介紹
我建立一個(gè)views文件夾,里面建立五個(gè)文件,五個(gè)文件里面包含了五個(gè)vue文件,分別對應(yīng)著導(dǎo)航欄下的每個(gè)按鈕。

在assets下建立css和img文件夾,放置tabbar按鈕所需的圖片和基礎(chǔ)類

在component文件夾中建立一個(gè)MainTabBar.vue文件和tabbar文件夾,tabbar文件夾里放置MainTabBar的子組件和各種插槽關(guān)聯(lián)文件。

router文件夾下的index文件配置路由文件

main.js是項(xiàng)目的入口文件,項(xiàng)目中所有的頁面都會(huì)加載main.js,所以main.js,主要有三個(gè)作用:
- 實(shí)例化VUE
- 放置項(xiàng)目中經(jīng)常會(huì)用到的插件和CSS樣式,例如網(wǎng)絡(luò)請求axios和vue-resource,圖片懶加載模塊:vue-;azyload
- 存儲(chǔ)全局變量例如基本信息等
各個(gè)文件夾中的代碼實(shí)現(xiàn)
第一步、文件很多,引用會(huì)常常帶來404錯(cuò)誤,這里開始先建立文件別名,vue建立文件別名詳解
找到resolve對象,在alias中寫入各個(gè)文件的別名:

文件起別名代碼
代碼:
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'@': resolve('src'),
'assets': resolve('src/assets'),
'components': resolve('src/components'),
'views': resolve('src/views'),
}
},
App.vue代碼
App.vue中引用MainTabBar組件和各個(gè)tabbaritem對應(yīng)的文件:
<template>
<div id="app">
<router-view></router-view>
<main-tab-bar></main-tab-bar>
</div>
</template>
<script type="module">
import MainTabBar from 'components/MainTabBar'
export default {
name: 'App',
components:{
MainTabBar
}
}
</script>
<style>
@import "assets/css/base";
</style>
MainTabBar.vue代碼
MainTabBar組件代碼:要求組件滿足可修改TabBarItem的個(gè)數(shù),顏色,文字,等都是動(dòng)態(tài)的。需要?jiǎng)?chuàng)建各類插槽。
<template>
<div>
<tab-bar>
<tab-bar-item path="/home" activeColor="purple">
<img slot="item-icon" src="~assets/img/tabbar/shouye.png" alt="" >
<img slot="item-icon-active" src="~assets/img/tabbar/shouye.active.png" alt="">
<div slot="item-text">首頁</div>
</tab-bar-item>
<tab-bar-item path="/category" activeColor="purple">
<img slot="item-icon" src="~assets/img/tabbar/fenlei.png" alt="">
<img slot="item-icon-active" src="~assets/img/tabbar/fenlei.active.png" alt="">
<div slot="item-text">分類</div>
</tab-bar-item>
<tab-bar-item path="/cart" activeColor="purple">
<img slot="item-icon" src="~assets/img/tabbar/gouwuche.png" alt="">
<img slot="item-icon-active" src="~assets/img/tabbar/gouwuche.active.png" alt="">
<div slot="item-text">購物車</div>
</tab-bar-item>
<tab-bar-item path="/profile" activeColor="purple">
<img slot="item-icon" src="~assets/img/tabbar/wode.png" alt="">
<img slot="item-icon-active" src="~assets/img/tabbar/wode.active.png" alt="">
<div slot="item-text">我的</div>
</tab-bar-item>
</tab-bar>
</div>
</template>
<script>
import TabBar from 'components/tabbar/TabBar'
import TabBarItem from 'components/tabbar/TabBarItem'
export default {
name:"MainTabBar",
components:{
TabBar,
TabBarItem
}
}
</script>
<style>
</style>
TabBar.vue代碼
TabBar.vue文件,改文件為MainTabBar.vue中的子組件:
<template>
<div id="tab-bar">
<slot></slot>
</div>
</template>
<script>
export default {
name:'TabBar'
}
</script>
<style>
</style>
TabBarItem.vue代碼
TabBarItem.vue為MainTabBar.vue的子組件
<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'
}
},
data(){
return {
// isActive:true
}
},
computed:{
isActive(){
//判斷
//return this.$route.path.indexOf(this.path) !== -1
//return this.$route.path === this.path
return this.$route.path.indexOf(this.path)?false:true
},
activeStyle(){
return this.isActive?{color:this.activeColor}:{}
}
},
methods:{
itemClick(){
this.$router.replace(this.path)
}
}
}
</script>
<style>
#tab-bar{
display: flex;
}
#tab-bar{
background-color: #f6f6f6;
border-top: 2px #ccc;
position: fixed;
left: 0;
right: 0;
bottom: 0;
box-shadow:0px -1px 1px rgba(100,100,100,.2) ;
}
.tab-bar-item{
flex: 1;
text-align: center;
height: 49px;
font-size: 14px;
}
.tab-bar-item img{
width: 24px;
height: 24px;
margin-top: 3px;
vertical-align: middle;
margin-bottom: 3px;
}
.active{
color: red;
}
</style>
index.js路由配置代碼
router文件夾下的index文件為路由的配置:
import Vue from 'vue'
import VueRouter from 'vue-router';
const Home = () => import('views/home/home')
const Category = () => import('views/category/category')
const Cart = () => import('views/cart/cart')
const Profile = () => import('../views/profile/profile')
//1.安裝插件
Vue.use(VueRouter)
//2.創(chuàng)建路由對象
const routes = [
{
path:'',
redirect:'/home'
},
{
path:'/home',
component:Home
},
{
path:'/category',
component:Category
},
{
path:'/cart',
component:Cart
},
{
path:'/profile',
component:Profile
}
]
const router = new VueRouter({
routes,
mode:'history'
})
//3.導(dǎo)出router
export default router
views中的home代碼,cart代碼,profile代碼,category代碼:
home.vue代碼
<template>
<h2>首頁</h2>
</template>
<script>
export default {
name:"Home"
}
</script>
<style>
</style>
category.vue代碼
<template>
<h2>分類</h2>
</template>
<script>
export default {
name:"Home"
}
</script>
<style>
</style>
profile.vue代碼
<template>
<h2>個(gè)人</h2>
</template>
<script>
export default {
name:"Home"
}
</script>
<style>
</style>
cart.vue代碼
<template>
<h2>購物車</h2>
</template>
<script>
export default {
name:"Home"
}
</script>
<style>
</style>
Base.css代碼
CSS文件下的base.css內(nèi)容:
body{
padding: 0px;
margin: 0px;
}
img圖片資源








實(shí)現(xiàn)完成~
總結(jié):
項(xiàng)目綜合性很大,其中有插槽,路由,子組件父組件的值得傳遞,別名設(shè)置的各種知識(shí)。
項(xiàng)目動(dòng)態(tài)內(nèi)容:tabbar的文字,圖片,顏色都可以動(dòng)態(tài)改變,下次類似項(xiàng)目直接可以引用這些文件。
主要難點(diǎn):
一、當(dāng)點(diǎn)擊到對應(yīng)的TabBarItem上的時(shí)候改變圖片顏色,文字顏色,這里是用當(dāng)前的活躍路由和傳過來的地址是否對應(yīng),如果對應(yīng)就會(huì)變?yōu)閠rue返貨來為false:
computed:{
isActive(){
//判斷
return this.$route.path.indexOf(this.path)?false:true
},
activeStyle(){
return this.isActive?{color:this.activeColor}:{}
}
},
methods:{
itemClick(){
this.$router.replace(this.path)
}
}
上面的代碼還有其他方法:
return this.$route.path.indexOf(this.path) !== -1
return this.$route.path === this.path
二、父組件傳值問題,父組件傳過來對應(yīng)的文件路徑,對應(yīng)的字體顏色,子組件接受并使用:
export default {
name:"TabBarItem",
props:{
path:String,
activeColor:{
type:String,
default:'red'
}
},
data(){
return {}
},
項(xiàng)目完成~
到此這篇關(guān)于Vue實(shí)現(xiàn)TabBar底部導(dǎo)航欄的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解在Vue中如何使用axios跨域訪問數(shù)據(jù)
本篇文章主要介紹了在Vue中如何使用axios跨域訪問數(shù)據(jù),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-07-07
element-ui自定義message-box自定義樣式不生效的解決
這篇文章主要介紹了element-ui自定義message-box自定義樣式不生效的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
vue實(shí)現(xiàn)點(diǎn)擊某個(gè)div顯示與隱藏內(nèi)容功能實(shí)例
最近做項(xiàng)目有用到某個(gè)div顯示與隱藏內(nèi)容,所以下面這篇文章主要給大家介紹了關(guān)于vue實(shí)現(xiàn)點(diǎn)擊某個(gè)div顯示與隱藏內(nèi)容功能的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-12-12
Vue實(shí)現(xiàn)開始時(shí)間和結(jié)束時(shí)間范圍查詢
這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)開始時(shí)間和結(jié)束時(shí)間的范圍查詢,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08

