Vue封裝一個Tabbar組件?帶組件路由跳轉(zhuǎn)方式
Vue封裝Tabbar組件
話不多說直接上代碼
在App.vue 封裝 路由跳轉(zhuǎn) 利用router-view的特性
<template> ? <div id="app"> ? ? <router-view /> ? ? //引入子組件 把items 這個數(shù)組傳進去 ? ? <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 ?/> ? ? ? ? //動態(tài)綁定 ? ? ? </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){ ? ? ?//這里是根據(jù)下標(biāo)切換 圖片樣式跟字體顏色 動態(tài)綁定 ? ? ? ?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對象,它包含圖標(biāo)以及文字,但十實際中我們肯定不會將img和text寫死,以及處于active狀態(tài)時text的顏色也不會寫死,以方便調(diào)用者傳入想要的參數(shù),這樣才算一個徹底的封裝。
代碼如下
<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> ? <!-- ? ? 上方代碼設(shè)置三個插槽,為什么不是兩個呢,因為還要包含當(dāng)item處于活躍狀態(tài)時要顯示的image,所以是三個,使用v-if控制當(dāng)非活躍時顯示默認icon插槽,活躍時顯示亮色icon插槽。因為插槽是要被傳入其中的內(nèi)容覆蓋的,所以傳入的內(nèi)容可能會將我們slot中的一些屬性覆蓋掉,所以常常我們需要將slot包裹在div中,這樣就可以避免這個問題。 ? ? icon下方文同理也放在div中,style綁定一個計算屬性,看下方代碼可以這個計算屬性當(dāng)item處于活躍時會返回顏色屬性,當(dāng)然這個屬性也是可以在調(diào)用tab-bar時傳入的,默認為紅色。 -->
<script> ? export default { ? ? name:'TabBarItem', ? ? props:{ ? ? ? path: String, ?// 當(dāng)前item對應(yīng)的路由,由調(diào)用者指定 ? ? ? activeColor:{ ?// 當(dāng)前item的文字在活躍時的顏色,默認紅色,可由使用者指定 ? ? ? ? type:String, ? ? ? ? default:"red" ? ? ? } ? ? }, ? ? data() { ? ? ? return { ? ? ? ? // isActive:false, ? ? ? } ? ? }, ? ? computed:{ ? ? ? // 判斷當(dāng)前item是否處于活躍狀態(tài) ? ? ? isActive(){ ? ? ? ? return this.$route.path.indexOf(this.path)!==-1; ? ? ? }, ? ? ? // 計算屬性,如果處于活躍狀態(tài)則設(shè)置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預(yù)留的插槽則用于放入每一個item,我們在這里也是不能寫死的,因為控件開發(fā)者并不知需要放入多少個item。
使用者在使用我們封裝的控件時
則可以如下代碼,放入內(nèi)容:
<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>
到此結(jié)束。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue中created、watch和computed的執(zhí)行順序詳解
由于vue的雙向數(shù)據(jù)綁定,自動更新數(shù)據(jù)的機制,在數(shù)據(jù)變化后,對此數(shù)據(jù)依賴?的所有數(shù)據(jù),watch事件都會被更新、觸發(fā),下面這篇文章主要給大家介紹了關(guān)于vue中created、watch和computed的執(zhí)行順序,需要的朋友可以參考下2022-11-11使用vue自定義指令開發(fā)表單驗證插件validate.js
今天就來介紹一下如何利用vue的自定義指令directive來開發(fā)一個表單驗證插件的過程,需要的朋友可以參考下2019-05-05