vue合家福實(shí)例(3):根據(jù)路由生成菜單

本章的最終效果

最終效果圖

這章的開(kāi)發(fā)在admin子項(xiàng)目中進(jìn)行件舵。這里我們?cè)趐roject/admin中創(chuàng)建文件App.vue。內(nèi)容如vue合家福實(shí)例(2):使用element-ui el-scrollbar中的脯厨,建立一個(gè)項(xiàng)目的頁(yè)面框架铅祸。統(tǒng)一的菜單和頂部狀態(tài)欄。
在開(kāi)發(fā)中俄认,要增加一個(gè)頁(yè)面个少。我是先寫(xiě)一個(gè)簡(jiǎn)單的組件(.vue)文件,然后配置路由眯杏。接下去是修改菜單(這樣的情況下夜焦,一般菜單會(huì)建立一個(gè)組件)。那么岂贩,如果路由配置好后就可以增加到菜單中茫经,即菜單是根據(jù)路由生成的,這樣修改路由就不用再去改菜單的代碼萎津。想想挺酷的卸伞。
目錄結(jié)構(gòu):
目錄結(jié)構(gòu)

我們?cè)诩t框中的文件目錄進(jìn)行工作。
BhLayout>src>menu-item.vue (一個(gè)菜單項(xiàng)組件锉屈,對(duì)element-ui的菜單組件進(jìn)行再封裝)
菜單的代碼在App.vue中荤傲,routers.js是路由配置文件。

App.vue:

<script>
import _ from 'lodash'
import {BhMenuItem} from '@/components/BhLayout' // 加入菜單項(xiàng)組件
export default {
  name: 'app',
  components: {
    BhMenuItem
  },
  data () {
    return {
      isCollapse: false,
      asideWidth: '230px',
      vmenus: [],
      defActive: this.activePath()
    }
  },
  created () {},
  watch: {
    $route () {
      this.defActive = this.activePath()
      this.setPageTitle()
    }
  },
  methods: {
    // 改變菜單欄的寬度
    changeCollapse () {
      this.isCollapse = !this.isCollapse
      this.$emit('collapse-change', this.isCollapse)
      if (this.isCollapse) {
        this.asideWidth = '65px'
      } else {
        this.asideWidth = '230px'
      }
    },
    // 設(shè)置頁(yè)面標(biāo)題
    setPageTitle () {
      let path = this.$route.path
      let pathArr = _.split(path, '/')
      let l = pathArr.length
      let menus = this.$router.options.routes
      if (_.isEmpty(menus) || l < 2) {
        return
      }
      let ts = ['vue全家福']
      let i = 1
      let children = menus
      while (i < l) {
        path = _.join(_.slice(pathArr, 0, i + 1), '/')
        let index = _.findIndex(children, menu => {
          let menuPath = menu.path
          let i = menuPath.indexOf('/:')
          if (i > 0) {
            menuPath = menuPath.substring(0, i)
          }
          return menuPath === path
        })
        if (index < 0) {
          break
        }
        if (!children[index]) {
          break
        }
        if (children[index]['text']) {
          ts.push(children[index]['text'])
        }
        if (!children[index]['children'] || _.isEmpty(children[index]['children'])) {
          break
        }
        children = children[index]['children']
        i++
      }
      this.title = _.clone(ts)
    },
    // 計(jì)算菜單當(dāng)前選中的路徑
    activePath () {
      let path = this.$route.path
      let pathArr = _.split(path, '/')
      let l = pathArr.length
      if (l <= 2) {
        return path
      }
      let menus = this.$router.options.routes
      if (_.isEmpty(menus)) {
        return path
      }
      let i = 1
      let children = menus
      while (i < l) {
        path = _.join(_.slice(pathArr, 0, i + 1), '/')
        let index = _.findIndex(children, {'path': path})
        if (index < 0) {
          break
        }
        if (!children[index]) {
          break
        }
        if (children[index]['hasChildren'] === false || !children[index]['children'] || _.isEmpty(children[index]['children'])) {
          break
        }
        children = children[index]['children']
        i++
      }
      return path
    }
  }
}
</script>

<template>
  <el-container>
    <!-- 菜單欄 -->
    <el-aside :width="asideWidth">
      <el-scrollbar class="default-scrollbar" wrap-class="default-scrollbar__wrap" view-class="default-scrollbar__view">
        <div :class="isCollapse ? 'menu-collapsed' : 'menu-expanded'">
          <el-menu
            :default-active="defActive"
            class="el-menu-vertical-demo"
            unique-opened
            router
            :collapse="isCollapse">
            <bh-menu-item :menu="item" :key="item.name" v-for="item in $router.options.routes" v-if="item.menu"></bh-menu-item>
          </el-menu>
        </div>
      </el-scrollbar>
    </el-aside>
    <el-container>
      <!-- 右邊上面的欄目 -->
      <el-header class="clear">
        <div class="collapse-btn" @click.prevent="changeCollapse">
          <i class="fas fa-bars" :class="{ rotate90: isCollapse }"></i>
        </div>
      </el-header>
      <!-- 路由容器 -->
      <router-view></router-view>
    </el-container>
  </el-container>
</template>

<style scoped>
.collapse-btn {
  float: left;
  font-size: 24px;
  cursor: pointer;
}
.rotate90 {
  filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
  -moz-transform: rotate(90deg);
  -o-transform: rotate(90deg);
  -webkit-transform: rotate(90deg);
  transform: rotate(90deg);
}
</style>

補(bǔ)充說(shuō)明:$router.options.routes(如果在js中是this.$router.options.routes)颈渊。取出當(dāng)前路由內(nèi)容遂黍,即src>project>admin>router>routers.js文件中的內(nèi)容
菜單是通過(guò)$router.options.routes(項(xiàng)目路由)自動(dòng)生成的。下面是路由(routers.js)的內(nèi)容:

import Wrap from '@/components/Wrap.vue'

const routers = [{
  path: '/',
  name: 'home',
  text: '首頁(yè)',
  menu: true,
  icon: 'fas fa-home',
  component: resolve => require(['../views/Home'], resolve)
}, {
  path: '/dashboard',
  name: 'dashboard',
  text: '儀表盤(pán)',
  menu: true,
  icon: 'fas fa-tachometer-alt',
  component: resolve => require(['../views/Dashboard'], resolve)
}, {
  path: '/user',
  name: 'user',
  text: '用戶管理',
  menu: true,
  hasChildren: true,
  icon: 'fas fa-user-cog',
  component: Wrap,
  children: [{
    path: '/user/permission',
    name: 'user_permission',
    text: '權(quán)限管理',
    menu: true,
    component: resolve => require(['../views/user/Permission'], resolve)
  }, {
    path: '/user/role',
    name: 'user_role',
    text: '角色管理',
    menu: true,
    component: resolve => require(['../views/user/Role'], resolve)
  }, {
    path: '/user/user',
    name: 'user_user',
    text: '用戶管理',
    menu: true,
    component: resolve => require(['../views/user/User'], resolve)
  }]
}]

export default routers

補(bǔ)充說(shuō)明:Wrap.vue文件只是一個(gè)簡(jiǎn)單的路由容器俊嗽,內(nèi)容如下雾家。因?yàn)関ue-cli3項(xiàng)目生成的,如果寫(xiě)component: { template: '<router-view></router-view>' } 會(huì)報(bào)異常绍豁。我的方案是建立一個(gè)組件芯咧,引入。

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

<template>
  <router-view></router-view>
</template>

生成菜單的組件BhMenuItem,關(guān)鍵內(nèi)容如下:

<template>
  <component v-bind:is="currentItemComponent" :index="menu.path" :key="menu.path">
    <i :class="menu.icon" v-if="menu.icon && !hc"></i><span v-if="!hc" slot="title">{{menu.text}}</span>
    <template slot="title" v-if="hc">
      <i :class="menu.icon" v-if="menu.icon"></i><span slot="title">{{menu.text}}</span>
    </template>
    <!-- 這里用了遞歸生成菜單項(xiàng) -->
    <bh-menu-item :menu="child" :key="child.name" v-for="child in menu.children" v-if="hc && child.menu"></bh-menu-item>
  </component>
</template>

<script>
export default {
  name: 'BhMenuItem',
  props: {
    menu: Object
  },
  data () {
    return {
      hc: false
    }
  },
  computed: {
    currentItemComponent: function () {
      return this.hasChildren() ? 'el-submenu' : 'el-menu-item'
    }
  },
  methods: {
    hasChildren () {
      this.hc = this.menu.hasChildren !== false && this.menu.children && this.menu.children.length > 0
      return this.hc
    }
  }
}
</script>

補(bǔ)充說(shuō)明:菜單的結(jié)構(gòu)是一棵樹(shù)敬飒,可以一層層深入邪铲。在這里判斷如果菜單項(xiàng)沒(méi)有子菜單的話就用element-ui的el-menu-item組件,如果還有子菜單驶拱,則用el-menu-item霜浴。最后如果有子菜單晶衷,遞歸使用組件蓝纲。
在App.vue用BhMenuItem組件生成菜單樹(shù)。完成后晌纫,菜單如圖:


生成的菜單

發(fā)現(xiàn)菜單的圖標(biāo)樣式不合理税迷,這是font awesome圖標(biāo)。下章補(bǔ)充font awesome圖標(biāo)使用方法锹漱,在這里與element-ui 圖標(biāo)的padding不一樣箭养。在全局樣式表中加入樣式:

.el-menu .fa,
.el-menu .fas,
.el-menu .far {
  margin-right: 10px;
}

最終效果


效果一

點(diǎn)擊圖標(biāo)后收縮菜單。


效果二
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末哥牍,一起剝皮案震驚了整個(gè)濱河市毕泌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌嗅辣,老刑警劉巖撼泛,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異澡谭,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)辣恋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)瞭空,“玉大人,你說(shuō)我怎么就攤上這事雁仲∽卸幔” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵攒砖,是天一觀的道長(zhǎng)缸兔。 經(jīng)常有香客問(wèn)我,道長(zhǎng)祭衩,這世上最難降的妖魔是什么灶体? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮掐暮,結(jié)果婚禮上蝎抽,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好樟结,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布养交。 她就那樣靜靜地躺著,像睡著了一般瓢宦。 火紅的嫁衣襯著肌膚如雪碎连。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天驮履,我揣著相機(jī)與錄音鱼辙,去河邊找鬼。 笑死玫镐,一個(gè)胖子當(dāng)著我的面吹牛倒戏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播恐似,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼杜跷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了矫夷?” 一聲冷哼從身側(cè)響起葛闷,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎双藕,沒(méi)想到半個(gè)月后淑趾,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蔓彩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年治笨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赤嚼。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡旷赖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出更卒,到底是詐尸還是另有隱情等孵,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布蹂空,位于F島的核電站俯萌,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏上枕。R本人自食惡果不足惜咐熙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望辨萍。 院中可真熱鬧棋恼,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至师崎,卻和暖如春默终,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背犁罩。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工齐蔽, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人昼汗。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓肴熏,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親顷窒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

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

  • 1源哩、通過(guò)CocoaPods安裝項(xiàng)目名稱(chēng)項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明先生_X自主閱讀 15,980評(píng)論 3 119
  • 活久見(jiàn)活久見(jiàn) 活得久了才能見(jiàn) 同志鞋吉! 無(wú)論生活以何種方式待你 請(qǐng)你 務(wù)必活下去! 活下去励烦! 并且 要活久谓着!
    林香文閱讀 263評(píng)論 0 0
  • 大多數(shù)人覺(jué)得想明白一個(gè)道理才能“從內(nèi)而外”的改變自己,然而這個(gè)想法卻在現(xiàn)實(shí)處處碰壁坛掠。 相比之下赊锚,《粉雄救兵》逆流而...
    小船子閱讀 874評(píng)論 1 1
  • 什么時(shí)候開(kāi)始喜歡唱反調(diào)舷蒲。 比如周?chē)察o的話,就會(huì)說(shuō)些有的沒(méi)的甚至?xí)鋱?chǎng)的笑話友多。但如果氣氛很熱烈牲平,大多就不怎么說(shuō)話...
    某日醒覺(jué)閱讀 449評(píng)論 0 0