1-vuejs2.0實(shí)戰(zhàn):仿豆瓣app項(xiàng)目,創(chuàng)建自定義組件tabbar

大家好聚谁,我給大家分享一下仿豆瓣app的教程垦巴。當(dāng)然了骤宣,我們不是用原生去實(shí)現(xiàn),而是用前端框架vuejs來(lái)實(shí)現(xiàn)豆瓣app等限⊥牛————第一次寫文章,寫得不好請(qǐng)見(jiàn)諒桐早。

為什么我們選擇豆瓣app 來(lái)做這樣一個(gè)教程哄酝?

是因?yàn)槲液茉缇徒佑|豆瓣這個(gè)網(wǎng)站陶衅,我比較喜歡看豆瓣里面電影和文章的點(diǎn)評(píng)直晨。并且豆瓣提供了非常豐富的一個(gè)api接口供我們使用勇皇。也就是說(shuō)我們可以不通過(guò)后端儒士,直接通過(guò)前端ajax來(lái)獲取電影和圖書的數(shù)據(jù),來(lái)組裝我們app诅福。

我們可以看一下豆瓣app首頁(yè)是一個(gè)什么樣子 gif

Paste_Image.png

以上就是豆瓣app的一個(gè)截圖氓润。

我們先來(lái)分析一下

首頁(yè)分為四個(gè)部分咖气。第一個(gè)就是頂部的搜索框崩溪。搜索框下面就是一個(gè)banner圖切換斩松。在下面就是一些熱點(diǎn)的文章列表惧盹。最底部就是一個(gè)tab切換。在這篇教程中粹断,我們通過(guò)vue的組件來(lái)實(shí)現(xiàn)這樣一個(gè)首頁(yè)的布局瓶埋。


創(chuàng)建豆瓣項(xiàng)目
如果沒(méi)有安裝node养筒,請(qǐng)到官網(wǎng)下載安裝闽颇,或者通過(guò)淘寶npm鏡像安裝

http://npm.taobao.org/

我們通過(guò)官方vue-cli初始化項(xiàng)目,這里我們采用webpack示例

vue init webpack douban

填寫項(xiàng)目描述兵多,作者橄仆,安裝vue-router

? Project name douban
? Project description douban
? Author afei
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? No
? Setup unit tests with Karma + Mocha? No
? Setup e2e tests with Nightwatch? No

   vue-cli · Generated "douban".

   To get started:

     cd douban
     npm install
     npm run dev

   Documentation can be found at https://vuejs-templates.github.io/webpack

初始化后盆顾,通過(guò)npm install安裝依賴

cd douban
npm install

由于我們是做的移動(dòng)端您宪,所以在index.html里面加上meta宪巨,

<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">

運(yùn)行項(xiàng)目,可以看到基于官方vue-cli的模版就創(chuàng)建好了

npm run dev
Paste_Image.png

將所需要用的資源捏卓,拷貝到項(xiàng)目中怠晴,這里我通過(guò)解壓豆瓣app獲得他的一些圖片素材,拷入到src/assets/images目錄里稿械。

css這里我用到了normaliz.css

在src下溜哮,新建了一個(gè)pages目錄茂嗓,存放每一個(gè)頁(yè)面組件,可以看一下我們的目錄

Paste_Image.png

由于我們的首頁(yè)更改了位置,所以在router里面的index.js需要更改為

import Vue from 'vue'
import Router from 'vue-router'
import Index from '../pages/Index'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Index',
      component: Index
    }
  ]
})

每一個(gè)組件的css我們通過(guò)less來(lái)編寫道批,所有需要通過(guò)npm安裝less插件

npm install less less-loader --save

使用less預(yù)處理器需要在頁(yè)面添加 lang='less'

<style scoped lang="less">
    
</style>

第一個(gè)組件 tabbar

如何創(chuàng)建自定義組件tabbar隆豹,也就是豆瓣app底部的工具欄茅逮。這里的結(jié)構(gòu)我們參考了mint-ui

這是我們將要實(shí)現(xiàn)的效果圖献雅。

Paste_Image.png

我們先來(lái)分析一下這個(gè)組件的結(jié)構(gòu)挺身。

這個(gè)組件分為兩部分:第一個(gè)是組件的外層容器章钾,第二個(gè)是組件的子容器item贱傀,子組件里面又分為圖片和文字組合。子組件有2個(gè)狀態(tài)串纺,一個(gè)默認(rèn)灰色的狀態(tài)纺棺,一個(gè)選中狀態(tài)祷蝌,我們來(lái)實(shí)現(xiàn)一下這個(gè)組件的布局帆卓。在index.vue里面

template

<div class="m-tabbar">
  <a class="m-tabbar-item is-active">
    <span class="m-tabbar-item-icon">
       < img src="../assets/images/ic_tab_home_normal.png" alt="">
    </span> 
    <span class="m-tabbar-item-text">  
          首頁(yè)
    </span>
  </a> 
  <a class="m-tabbar-item">
    <span class="m-tabbar-item-icon">
       < img src="../assets/images/ic_tab_subject_normal.png" alt="">
    </span> 
    <span class="m-tabbar-item-text">  
          書影音
    </span>
  </a> 
  <a class="m-tabbar-item">
    <span class="m-tabbar-item-icon">
       < img src="../assets/images/ic_tab_status_normal.png" alt="">
    </span> 
    <span class="m-tabbar-item-text">  
          廣播
    </span>
  </a> 
  <a class="m-tabbar-item">
    <span class="m-tabbar-item-icon">
       < img src="../assets/images/ic_tab_group_normal.png" alt="">
    </span> 
    <span class="m-tabbar-item-text">  
          小組
    </span>
  </a> 
  <a class="m-tabbar-item">
    <span class="m-tabbar-item-icon">
       < img src="../assets/images/ic_tab_profile_normal.png" alt="">
    </span> 
    <span class="m-tabbar-item-text">  
          我的
    </span>
  </a> 
</div>

style

<style lang="less">
.m-tabbar{
    display: flex;
    flex-direction: row;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    width: 100%;
    overflow: hidden;
    height: 50px;
    background: #fff;
    border-top: 1px solid #e4e4e4;
    
    .m-tabbar-item{
      flex: 1;
      text-align: center;
      .m-tabbar-item-icon{
          display: block;
          padding-top: 2px;
          img{
              width: 28px;
              height: 28px;
          }
      }
      .m-tabbar-item-text{
          display: block;
          font-size: 10px;
          color:#949494;
      }
      &.is-active{
          .m-tabbar-item-text{
              color: #42bd56;
          }
      }
  }
}
</style>

布局大功告成~~~~

前面我們說(shuō)的是糊啡,通過(guò)組件的方式來(lái)實(shí)現(xiàn)這個(gè)app棚蓄。

如果像上面代碼這樣的話肯定是不行的!既然我們大體布局已經(jīng)寫好了稍算,現(xiàn)在就可以通過(guò)組件的方式來(lái)調(diào)用糊探。當(dāng)然我們還要改造一下代碼侧到。

先在components文件夾下面,新建兩個(gè)組件故源,通過(guò)這兩個(gè)組件來(lái)組合實(shí)現(xiàn)我們底部的tab組件:

一個(gè)是tabbar-item.vue绳军,實(shí)現(xiàn)子組件的item項(xiàng)门驾,

tabbar-item.vue

<template>
    <a class="m-tabbar-item" >
        <span class="m-tabbar-item-icon"><slot name="icon-normal"></slot></span>
        <span class="m-tabbar-item-text"><slot></slot></span>
    </a>
</template>

<style lang="less">
.m-tabbar-item{
    flex: 1;
    text-align: center;
    .m-tabbar-item-icon{
        display: block;
        padding-top: 2px;
        img{
            width: 28px;
            height: 28px;
        }

    }
    .m-tabbar-item-text{
        display: block;
        font-size: 10px;
        color:#949494;
    }
    &.is-active{
        .m-tabbar-item-text{
            color: #42bd56;
        }
    }
}
</style>

一個(gè)是tabbar.vue奶是,實(shí)現(xiàn)tab的外層容器聂沙,

tabbar.vue

<template>
    <div class="m-tabbar">
       <slot></slot>
    </div>
</template>
<style lang="less">
.m-tabbar{
    display: flex;
    flex-direction: row;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    width: 100%;
    overflow: hidden;
    height: 50px;
    background: #fff;
    border-top: 1px solid #e4e4e4;
}
</style>

在Index.vue中組合這兩個(gè)組件及汉,實(shí)現(xiàn)tab組件效果

<template>
  <div>
    <m-tabbar>
      <m-tabbar-item id='tab1'>
        < img src="../assets/images/ic_tab_home_normal.png" alt="" slot="icon-normal"> 
        首頁(yè)
      </m-tabbar-item>
      <m-tabbar-item id='tab2'>
        < img src="../assets/images/ic_tab_subject_normal.png" alt="" slot="icon-normal"> 
        書影音
      </m-tabbar-item>
      <m-tabbar-item id='tab3'>
        < img src="../assets/images/ic_tab_status_normal.png" alt="" slot="icon-normal"> 
        廣播
      </m-tabbar-item>
      <m-tabbar-item id='tab4'>
        ![](../assets/images/ic_tab_group_normal.png) 
        小組
      </m-tabbar-item>
       <m-tabbar-item id='tab5'>
        < img src="../assets/images/ic_tab_profile_normal.png" alt="" slot="icon-normal"> 
        我的
      </m-tabbar-item>
    </m-tabbar>
  </div>
</template>

<script>
  import mTabbar from '../components/tabbar'
  import mTabbarItem from '../components/tabbar-item'
  export default {
    name: 'index',
    components: {
      mTabbar,
      mTabbarItem
    }
  }
</script>

完成的效果房铭。

Paste_Image.png

光有一個(gè)死的界面缸匪,沒(méi)有點(diǎn)擊切換的效果怎么能行豪嗽?

以下我們通過(guò)vue使用自定義事件的表單輸入組件來(lái)實(shí)現(xiàn)點(diǎn)擊切換的效果。


先給Index.vue里面的tab組件加上v-model 來(lái)進(jìn)行數(shù)據(jù)雙向綁定隐锭,通過(guò)select來(lái)達(dá)到選擇item钦睡,在item里面再添加一個(gè)選中的active圖片

<template>
  <div>
    測(cè)試
    <m-tabbar v-model="select">
      <m-tabbar-item id='tab1'>
        < img src="../assets/images/ic_tab_home_normal.png" alt="" slot="icon-normal"> 
        < img src="../assets/images/ic_tab_home_active.png" alt="" slot="icon-active"> 
        首頁(yè)
      </m-tabbar-item>
      <m-tabbar-item id='tab2'>
        < img src="../assets/images/ic_tab_subject_normal.png" alt="" slot="icon-normal"> 
        < img src="../assets/images/ic_tab_subject_active.png" alt="" slot="icon-active"> 
        書影音
      </m-tabbar-item>
      <m-tabbar-item id='tab3'>
        < img src="../assets/images/ic_tab_status_normal.png" alt="" slot="icon-normal"> 
        < img src="../assets/images/ic_tab_status_active.png" alt="" slot="icon-active"> 
        廣播
      </m-tabbar-item>
      <m-tabbar-item id='tab4'>
        < img src="../assets/images/ic_tab_group_normal.png" alt="" slot="icon-normal"> 
        < img src="../assets/images/ic_tab_group_active.png" alt="" slot="icon-normal"> 
        小組
      </m-tabbar-item>
       <m-tabbar-item id='tab5'>
        < img src="../assets/images/ic_tab_profile_normal.png" alt="" slot="icon-normal"> 
        < img src="../assets/images/ic_tab_profile_active.png" alt="" slot="icon-normal"> 
        我的
      </m-tabbar-item>
    </m-tabbar>
  </div>
</template>

<script>
  import mTabbar from '../components/tabbar'
  import mTabbarItem from '../components/tabbar-item'
  export default {
    name: 'index',
    components: {
      mTabbar,
      mTabbarItem
    },
    data() {
      return {
        select:"tab1"
      }
    }
  }
</script>

tabbar.vue里面通過(guò)props來(lái)傳遞數(shù)據(jù)vaule

<template>
    <div class="m-tabbar">
       <slot></slot>
    </div>
</template>
<script>
    import mTabbarItem from './tabbar-item';
    export default {
        props: ['value']
    }
</script>
<style lang="less">
.m-tabbar{
    display: flex;
    flex-direction: row;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    width: 100%;
    overflow: hidden;
    height: 50px;
    background: #fff;
    border-top: 1px solid #e4e4e4;
}
</style>

tabbar-item.vue組件:根據(jù)父組件的value和當(dāng)前組件的id判斷是否為選中狀態(tài),通過(guò) $parent.$emit('input',id) - 觸發(fā)父組件的自定義事件,添加選中的圖片躁倒,根據(jù)isActive來(lái)顯示隱藏

<template>
    <a class="m-tabbar-item" :class="{'is-active':isActive}" @click="$parent.$emit('input',id)">
        <span class="m-tabbar-item-icon" v-show="!isActive"><slot name="icon-normal"></slot></span>
        <span class="m-tabbar-item-icon" v-show="isActive"><slot name="icon-active"></slot></span>
        <span class="m-tabbar-item-text"><slot></slot></span>
    </a>
</template>
<script>
    export default{
        props: ['id'],
        computed: {
           isActive(){
               if(this.$parent.value===this.id){
                   return true;
               }
           }
        }
    }
</script>
<style lang="less">
.m-tabbar-item{
    flex: 1;
    text-align: center;
    .m-tabbar-item-icon{
        display: block;
        padding-top: 2px;
        img{
            width: 28px;
            height: 28px;
        }

    }
    .m-tabbar-item-text{
        display: block;
        font-size: 10px;
        color:#949494;
    }
    &.is-active{
        .m-tabbar-item-text{
            color: #42bd56;
        }
    }
}
</style>

大功告成荞怒,tabbar組件就完成了~~~~~

錄像1_轉(zhuǎn).gif

感謝餓了么團(tuán)隊(duì)給我們帶來(lái)了這么好的ui組件!

git地址:
https://github.com/MrMoveon/doubanApp

第一章
源碼下載 鏈接:http://pan.baidu.com/s/1qYlR8g0 密碼:9yph

下載安裝

npm install
npm run dev
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末秧秉,一起剝皮案震驚了整個(gè)濱河市褐桌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌象迎,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件砾淌,死亡現(xiàn)場(chǎng)離奇詭異啦撮,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)汪厨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門赃春,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人劫乱,你說(shuō)我怎么就攤上這事织中。” “怎么了衷戈?”我有些...
    開(kāi)封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵抠璃,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我脱惰,道長(zhǎng)搏嗡,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮采盒,結(jié)果婚禮上旧乞,老公的妹妹穿的比我還像新娘。我一直安慰自己磅氨,他們只是感情好尺栖,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著烦租,像睡著了一般延赌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上叉橱,一...
    開(kāi)封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天挫以,我揣著相機(jī)與錄音,去河邊找鬼窃祝。 笑死掐松,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的粪小。 我是一名探鬼主播大磺,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼探膊!你這毒婦竟也來(lái)了杠愧?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤逞壁,失蹤者是張志新(化名)和其女友劉穎流济,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體猾担,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年刺下,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了绑嘹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡橘茉,死狀恐怖工腋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情畅卓,我是刑警寧澤擅腰,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站翁潘,受9級(jí)特大地震影響趁冈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一渗勘、第九天 我趴在偏房一處隱蔽的房頂上張望沐绒。 院中可真熱鬧,春花似錦旺坠、人聲如沸乔遮。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蹋肮。三九已至,卻和暖如春璧疗,著一層夾襖步出監(jiān)牢的瞬間坯辩,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工病毡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留濒翻,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓啦膜,卻偏偏與公主長(zhǎng)得像有送,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子僧家,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

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