封裝TabBar案例

封裝TabBar案例

TabBar.png

通過學習上面這個TabBar的封裝捅彻,感受一下組件化開發(fā)和封裝的思想组去。

一、第一步

先寫死步淹,就寫4個條目从隆,分別是首頁,分類缭裆,購物車键闺,我的,先寫在Vue.app中澈驼,把tab-bar的css樣式和tab-bar-item的樣式調(diào)整好

<template>
  <div id="app">
    <div id="tab-bar">
      <div class="tab-bar-item">
        <img src="./assets/img/tabbar/home.svg" alt="...">
        <div class="item-text">首頁</div>
      </div>
      <div class="tab-bar-item">
        <img src="./assets/img/tabbar/category.svg" alt="...">
        <div class="item-text">分類</div>
      </div>
      <div class="tab-bar-item">
        <img src="./assets/img/tabbar/shopcart.svg" alt="...">
        <div class="item-text">購物車</div>
      </div>
      <div class="tab-bar-item">
        <img src="./assets/img/tabbar/profile.svg" alt="...">
        <div class="item-text">我的</div>
      </div>
    </div>
  </div>
</template>

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

<style>
/* 在style中引用文件這樣子使用@import + url */
  @import './assets/css/base.css';
  #tab-bar{
    /* 流體布局艾杏,使得這個元素占據(jù)一行 */
    display: flex;
    height: 49px;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: #f6f6f6;
    font-size: 14px;
    /*
    <length>①: 第 1 個長度值定義元素的陰影水平偏移值。正值盅藻,陰影出現(xiàn)在元素右側(cè);負值畅铭,則陰影出現(xiàn)在元素左側(cè) 

    <length>②: 第 2 個長度值定義元素的陰影垂直偏移值氏淑。正值,陰影出現(xiàn)在元素底部硕噩;負值假残,則陰影出現(xiàn)在元素頂部 

    <length>③: 第 3 個長度值定義元素的陰影模糊值半徑(如果提供了)。該值越大陰影邊緣越模糊炉擅,若該值為0辉懒,陰影邊緣不出現(xiàn)模糊。不允許負值 <length>④: 第 4 個長度值定義元素的陰影外延值(如果提供了)谍失。正值眶俩,陰影將向四面擴展痴昧;負值裹匙,則陰影向里收縮 

    <color>: 定義元素陰影的顏色咪橙。如果該值未定義篮赢,陰影顏色將默認取當前最近的文本顏色 inset: 定義元素的陰影類型為內(nèi)陰影否灾。該值為空時昌犹,則元素的陰影類型為外陰影 
    */
    box-shadow: 0 -3px 1px rgba(100,100,100,.08);
  }
  .tab-bar-item{
    /* 使得這些元素均等分布在流體元素中 */
    flex: 1;
    text-align: center;
  }
  .tab-bar-item img{
    width: 24px;
    height: 24px;
    /* 使得圖片下面不要離文字太遠 */
    /* middle: 把當前盒的垂直中心和父級盒的基線加上父級的半x-height對齊 */
    vertical-align: middle;
  }
</style>

第二步盏档、把tab-bar抽成一個獨立的組件

TabBar組件

<template>
  <div id="tab-bar">
    <slot></slot>
  </div>
</template>

<script>
export default {
  name:"TabBar"
}
</script>

<style scoped>
#tab-bar{
    display: flex;
    height: 49px;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: #f6f6f6;
    font-size: 14px;
    box-shadow: 0 -3px 1px rgba(100,100,100,.08);
  }
</style>

第三步般哼、將TabBar中的每個條目抽成一個獨立的組件tab-bar-item

tab-bar-item組件

<template>
  <div class="tab-bar-item">
    <div v-if="isActive"><slot name="item-icon-active"></slot></div>
    <div v-else><slot name="item-icon"></slot></div>
    <div class="item-text">
      <slot name="item-text"></slot>
    </div>
  </div>
</template>

<script>
export default {
  name:"TabBarItem",
  data(){
    return {
      isActive:false
    }
  }
}
</script>

<style scoped>
  .tab-bar-item{
    flex: 1;
    text-align: center;
  }
  .tab-bar-item img{
    width: 24px;
    height: 24px;
    vertical-align: middle;
  }
</style>

第四步窃判、在進行完上面兩步后钞楼,現(xiàn)在的App.vue長這樣

<template>
  <div id="app">
    <tab-bar>
      <tab-bar-item>
        <img src="./assets/img/tabbar/home.svg" alt="..." slot="item-icon">
        <img src="./assets/img/tabbar/home_active.svg" alt="..." slot="item-icon-active">
        <div slot="item-text">首頁</div>
      </tab-bar-item>
      <tab-bar-item>
        <img src="./assets/img/tabbar/category.svg" alt="..." slot="item-icon">
        <img src="./assets/img/tabbar/category_active.svg" alt="..." slot="item-icon-active">
        <div slot="item-text">分類</div>
      </tab-bar-item>
      <tab-bar-item>
        <img src="./assets/img/tabbar/shopcart.svg" alt="..." slot="item-icon">
        <img src="./assets/img/tabbar/shopcart_active.svg" alt="..." slot="item-icon-active">
        <div slot="item-text">購物車</div>
      </tab-bar-item>
      <tab-bar-item>
        <img src="./assets/img/tabbar/profile.svg" alt="..." slot="item-icon">
        <img src="./assets/img/tabbar/profile_active.svg" alt="..." slot="item-icon-active">
        <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: 'App',
  components:{
    TabBar,
    TabBarItem
  }
}
</script>

<style>
/* 在style中引用文件這樣子使用@import + url */
  @import './assets/css/base.css';
</style>

第五步、配置路由

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

//使用懶加載來導入組件
const Home = () => import('../components/Home')  
const Category = () => import('../components/Category')  
const Profile = () => import('../components/Profile')  
const ShopCart = () => import('../components/ShopCart')  

//1.注入插件
Vue.use(Router)
//2.創(chuàng)建路由配置對象
const routes = [
  {
    path:'',
      //默認顯示首頁袄琳,重定向
    redirect:'/home'
  },
  {
    path:'/home',
    component:Home
  },
  {
    path:'/category',
    component:Category
  },
  {
    path:'/shopCart',
    component:ShopCart
  },
  {
    path:'/profile',
    component:Profile
  }
]

export default new Router({
  routes,
    //使用H5的history模式改變url
  mode:'history'
})

第六步询件、通過代碼跳轉(zhuǎn)路由燃乍,設(shè)置活躍時候的字體顏色可由外界傳入

<template>
  <div class="tab-bar-item" @click="itemClick">
    <div v-if="isActive"><slot name="item-icon-active"></slot></div>
    <div v-else><slot name="item-icon"></slot></div>
    <div class="item-text" :style="finalColor">
      <slot name="item-text"></slot>
    </div>
  </div>
</template>

<script>
export default {
  name:"TabBarItem",
  data(){
    return {
      
    }
  },
  props:{
    path:{
      type:String,
      require:true
    },
    color:{
      type:String,
      default:"red"
    }
  }
  ,
  computed:{
    isActive(){
      return this.$route.path.indexOf(this.path) !== -1;
    },
    finalColor(){
      return this.isActive?{color:this.color}:{};
    }
  },
  methods:{
    itemClick(){
      // 判斷是否正處于活躍狀態(tài),若是的話不進行跳轉(zhuǎn)
      this.$route.path.indexOf(this.path) !== -1?void(0):this.$router.replace(this.path);
    }
  }
}
</script>

<style scoped>
  .tab-bar-item{
    flex: 1;
    text-align: center;
  }
  .tab-bar-item img{
    width: 24px;
    height: 24px;
    vertical-align: middle;
  }
</style>

第七步雳殊、將最終的TabBar抽成組件橘沥,使得App中的代碼減少

<template>
  <div>
    <tab-bar>
      <tab-bar-item path='/home' color="deepPink">
        <img src="@/assets/img/tabbar/home.svg" alt="..." slot="item-icon">
        <img src="@/assets/img/tabbar/home_active.svg" alt="..." slot="item-icon-active">
        <div slot="item-text">首頁</div>
      </tab-bar-item>
      <tab-bar-item path='/category' color="deepPink">
        <img src="@/assets/img/tabbar/category.svg" alt="..." slot="item-icon">
        <img src="@/assets/img/tabbar/category_active.svg" alt="..." slot="item-icon-active">
        <div slot="item-text">分類</div>
      </tab-bar-item>
      <tab-bar-item path='/shopCart' color="deepPink">
        <img src="@/assets/img/tabbar/shopcart.svg" alt="..." slot="item-icon">
        <img src="@/assets/img/tabbar/shopcart_active.svg" alt="..." slot="item-icon-active">
        <div slot="item-text">購物車</div>
      </tab-bar-item >
      <tab-bar-item path='/profile' color="deepPink">
        <img src="@/assets/img/tabbar/profile.svg" alt="..." slot="item-icon">
        <img src="@/assets/img/tabbar/profile_active.svg" alt="..." slot="item-icon-active">
        <div slot="item-text">我的</div>
      </tab-bar-item>
    </tab-bar>
  </div>
</template>

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

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

<style scoped>

</style>

到了這里,基本的功能差不多實現(xiàn)了夯秃,不過座咆,我注意到一點,就是頻繁的復(fù)制粘貼代碼片段的時候仓洼,其中的一些涉及到路徑的東西很容易出問題介陶,因為寫的是相對路徑,所以為了使代碼更加強壯色建,可移植性更強哺呜,我們應(yīng)該把路徑從src開始寫起,但是一個個都這樣的話代碼量太大了箕戳,而且沒什么意義某残,所以我們可以給路徑改名

第八步、路徑改別名

在使用Vue/CLI2.xc創(chuàng)建的項目中陵吸,可以打開build/webpack.base.conf.js文件玻墅,找到這里進行路徑改別名

resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      '@': resolve('src'),
      
    }
  },

現(xiàn)在@已經(jīng)映射了src了,我們可以繼續(xù)添加一些別名

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

注意:使用別名的時候有兩種情況

  • 在import或者require 中使用別名

    這時候直接寫別名就可以了

  • 在其它情況下使用別名

    這時候在別名前面要加一個"~"

    使用別名后

    <template>
      <div>
        <tab-bar>
          <tab-bar-item path='/home' color="deepPink">
            <img src="~assets/img/tabbar/home.svg" alt="..." slot="item-icon">
            <img src="~assets/img/tabbar/home_active.svg" alt="..." slot="item-icon-active">
            <div slot="item-text">首頁</div>
          </tab-bar-item>
          <tab-bar-item path='/category' color="deepPink">
            <img src="~assets/img/tabbar/category.svg" alt="..." slot="item-icon">
            <img src="~assets/img/tabbar/category_active.svg" alt="..." slot="item-icon-active">
            <div slot="item-text">分類</div>
          </tab-bar-item>
          <tab-bar-item path='/shopCart' color="deepPink">
            <img src="~assets/img/tabbar/shopcart.svg" alt="..." slot="item-icon">
            <img src="~assets/img/tabbar/shopcart_active.svg" alt="..." slot="item-icon-active">
            <div slot="item-text">購物車</div>
          </tab-bar-item >
          <tab-bar-item path='/profile' color="deepPink">
            <img src="~assets/img/tabbar/profile.svg" alt="..." slot="item-icon">
            <img src="~assets/img/tabbar/profile_active.svg" alt="..." slot="item-icon-active">
            <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:"FinalTabBar",
      components:{
        TabBar,
        TabBarItem
      }
    }
    </script>
    
    <style scoped>
    
    </style>
    

    對配置文件進行修改之后一定要重新跑一下項目才會生效

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末壮虫,一起剝皮案震驚了整個濱河市澳厢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌囚似,老刑警劉巖剩拢,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異饶唤,居然都是意外死亡徐伐,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門募狂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來呵晨,“玉大人,你說我怎么就攤上這事熬尺∶溃” “怎么了?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵粱哼,是天一觀的道長季二。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么胯舷? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任刻蚯,我火速辦了婚禮,結(jié)果婚禮上桑嘶,老公的妹妹穿的比我還像新娘炊汹。我一直安慰自己,他們只是感情好逃顶,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布讨便。 她就那樣靜靜地躺著,像睡著了一般以政。 火紅的嫁衣襯著肌膚如雪霸褒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天盈蛮,我揣著相機與錄音废菱,去河邊找鬼。 笑死抖誉,一個胖子當著我的面吹牛殊轴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播袒炉,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼梳凛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了梳杏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤淹接,失蹤者是張志新(化名)和其女友劉穎十性,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體塑悼,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡劲适,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了厢蒜。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片霞势。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖斑鸦,靈堂內(nèi)的尸體忽然破棺而出愕贡,到底是詐尸還是另有隱情,我是刑警寧澤巷屿,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布固以,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏憨琳。R本人自食惡果不足惜诫钓,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望篙螟。 院中可真熱鬧菌湃,春花似錦、人聲如沸遍略。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽墅冷。三九已至纯路,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間寞忿,已是汗流浹背驰唬。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留腔彰,地道東北人叫编。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像霹抛,于是被迫代替她去往敵國和親搓逾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容