Vue 2.x折騰記 - (1)寫一個不大靠譜的二級側邊欄

前言

原本想寫個新手系列教程,發現這種東西一搜索一大把。 那就寫點實戰類的吧,這篇文章你能學點什麼? 固然是一些常見內置指令的用法,組件過渡,遍歷的思路等等javascript

效果圖

實現思路css

  • 過渡用css -
  • 遍歷循環判斷(比對路由,點擊的項名等)
  • 增長標記位來默認展開刷新頁面當前所在項
  • 儘可能減小DOM的改動,能用v-show的區域毫不用v-if
  • 自定義菜單JSON儘可能格式簡潔,沒有一大坨標記位這些干擾物(越簡單越方便後期)

代碼

菜單menuList.js

export const MENULIST = [
  {
    menuName: "客戶管理",
    menuIcon: "fz-ad-icon-test",
    menuSubLink: [
      {
        menuName: "廣告主",
        menuUrl: "/customer/adhost"
      },
      {
        menuName: "渠道",
        menuUrl: "/customer/channel"
      }
    ]
  },
  {
    menuName: "廣告管理",
    menuIcon: "fz-ad-guanggao",
    menuSubLink: [
      {
        menuName: "廣告新增",
        menuUrl: "/ad/add"
      },
      {
        menuName: "廣告審覈",
        menuUrl: "/ad/check"
      }
    ]
  },
  {
    menuName: "投放管理",
    menuIcon: "fz-ad-toufang",
    menuSubLink: [
      {
        menuName: "廣告位",
        menuUrl: "/puton/area"
      },
      {
        menuName: "廣告規格",
        menuUrl: "/puton/regular"
      }
    ]
  },
  {
    menuName: "數據統計",
    menuIcon: "fz-ad-statistics",
    menuSubLink: [
      {
        menuName: "廣告主",
        menuUrl: "/status/adhost"
      },
      {
        menuName: "渠道",
        menuUrl: "/status/channel"
      }
    ]
  },
  {
    menuName: "管理者",
    menuIcon: "fz-ad-guanli",
    menuUrl: "/manager"
  },
  {
    menuName: "操做日誌",
    menuIcon: "fz-ad-rizhi",
    menuUrl: "/logger"
  }
];

複製代碼

Sidebar.vue

<template>
  <div class="sidebar" > <ul class="sidebar-menu ">` <template v-for="(item ,index) in menulist"> <li :class="currentUrl === item.menuUrl ? 'active':''"> <template v-if="item.menuUrl"> <router-link :to="item.menuUrl" @click.native="toggleName=''"> <i :class="['fzicon',item.menuIcon]"></i> <span>{{item.menuName}}</span> </router-link> </template> <template v-else-if="item.menuSubLink"> <a href="javascript:;" @click="isToggle(item.menuName,item.defaultActive)"> <i :class="['fzicon',item.menuIcon]"></i> <span>{{item.menuName}}</span> <i class="trangle" :class="[config.iconfont, (item.menuName === toggleName) || item.defaultActive? config.icon_expand: config.icon_collapse]"> </i> </a> <transition name="sliderToggle" mode="out-in"> <ul class="tree-menu" v-show="item.menuName === toggleName || item.defaultActive"> <li v-for="(subitem,subindex) in item.menuSubLink" :key="subitem" :class="currentUrl === subitem.menuUrl ? 'active':''"> <router-link :to="subitem.menuUrl"> <i :class="subitem.menuIcon"></i> <span>{{subitem.menuName}}</span> </router-link> </li> </ul> </transition> </template> </li> </template> </ul> </div> </template> <script> import { MENULIST } from './menuList'; // 引入的自定義菜單數據 export default { name: 'layout-sidebar', data: function () { return { menulist: MENULIST, // 自定義菜單數據 currentUrl: '', // 當前瀏覽器的url toggleName: '', // 菜單子項目名稱 config: { 'iconfont': 'fzicon', // iconfont的字體 'icon_collapse': 'fz-ad-jiantou', // 箭頭 'icon_expand': 'fz-ad-jiantou1' // 箭頭 } } }, props: ['toggle', 'padMode'], // 這裏是用來構成佈局響應傳遞的props,單一組件不用管他 watch: { '$route'() { this.currentUrl = this.$route.fullPath; // 實時監測當前路由的變化而且賦值 } }, methods: { isToggle(name, defaultActive) { this.clearDefaultActive(); // 清除標記位,是否當前爲默認展開 defaultActive ? false : name !== this.toggleName ? this.toggleName = name : this.toggleName = ''; // 判斷展開收縮的核心 }, clearDefaultActive() { this.menulist.forEach(item => { this.$delete(item, 'defaultActive') }) } }, created: function () { this.currentUrl = this.$route.fullPath; this.$nextTick(() => { this.menulist.forEach((item, index) => { // 增長標記位,判斷當前url而後自動展開或者激活對應項(刷新默認展開當前url的項) if (!item.menuSubLink && item.menuUrl) { this.currentUrl === item.menuUrl ? this.$set(item, 'defaultActive', true) : ''; } else { if (item.menuSubLink) { item.menuSubLink.forEach((subitem, index) => { this.currentUrl === subitem.menuUrl ? this.$set(item, 'defaultActive', true) : ''; }) } } }) }) }, mounted: function () { } } </script> <style scoped lang="scss"> // 自定義過渡效果 .sliderToggle-enter-active, .sliderToggle-leave-active { transition: all 0.5s linear; height: 100%; height: auto; overflow: hidden; } .sliderToggle-enter, .sliderToggle-leave-to { overflow: hidden; padding-top: 0; padding-bottom: 0; height: 0; opacity: 0; } // 側邊欄全局樣式 .sidebar { position: absolute; top: 0; left: 0; padding-top: 68px; min-height: 100%; z-index: 810; transition: all 0.3s linear; background-color: #222d32; .sidebar-menu { list-style: none; margin: 0; padding: 0; white-space: nowrap; span { cursor: pointer; } a { text-decoration: none; color: #8aa4af; &:hover { color: #fff; } } ul { list-style: none; margin: 0; padding: 0; white-space: nowrap; overflow: hidden; } >li { position: relative; margin: 0; padding: 0; text-align: left; &.active { color: #fff; } >a { border-left: 3px solid transparent; position: relative; padding: 15px 5px 15px 19px; display: block; font-size: 14px; >i { padding-right: 4px; } .trangle { float: right; padding-right: 10px; } } &.active { >a { border-left: 3px solid #3c8dbc; color: #fff; } } >.tree-menu { margin: 0 1px; background: #2c3b41; list-style: none; padding: 0; margin: 0; .tree-menu { padding-left: 20px; } >li { margin: 0; &.active { >a { border-left: 3px solid #3c8dbc; color: #fff; } } >a { padding: 15px 10px 15px 40px; display: block; font-size: 14px; border-left: 3px solid transparent; } } &.active { display: block; } } } } &.expand { width: 230px; } &.collapse { width: 50px; .sidebar-menu { >li { >a { padding: 15px 5px 15px 15px; span, i:last-child { display: none; } } .tree-menu { display: none; } &:hover { >a { display: block; span { display: block; position: absolute; left: 47px; width: 153px; padding: 15px 5px 15px 19px; background-color: #222d32; color: #fff; width: 177px; top: 0; border-radius: 0 5px 0 0; } i:last-child { display: inline-block; position: absolute; right: -165px; top: 50%; transform: translateY(-50%); color: #fff; } } >.tree-menu { display: block; position: absolute; left: 47px; width: 180px; background-color: #222d32; color: #fff; top: 46px; width: 180px; border-radius: 0 0 5px 5px; } } } } } } </style> 複製代碼

總結

實際上這貨就是把Admin Lte的風格用vue實現了,還有變形金剛版本,整個響應涉及幾個到組件間的通信;vue

就不把所有代碼丟出來了,一大坨,效果是這樣的java

相關文章
相關標籤/搜索