美文网首页
vue左侧菜单栏,传入数据即可用

vue左侧菜单栏,传入数据即可用

作者: 一个健康马 | 来源:发表于2020-07-01 19:27 被阅读0次
//app.js
<template>
  <div id="app">
    <el-container :class="{'hideSidebar':collapse}">
            <layout-com  class="sidebar-container" :dataList='permission_routers' :collapse='collapse'/>
      <el-container>
        <el-button style="margin-left:230px;z-index:1002; position: absolute;;width:50px" :class="['el-icon-menu',{'active':collapse}]" @click="collapseShow()"> </el-button>
        <el-header height="auto">
          
          <div :class="['headerss',{'active':collapse}]" >导航栏</div>
        </el-header>
        <el-main :class="['mains',{'active':collapse}]">
          <!-- <div>Main</div> -->
          <router-view></router-view>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
import layoutCom from '@/components/Sidebar/index.vue'
export default {
  name: 'app',
  components: {
    HelloWorld,layoutCom
  },
  data () {
    return {
      collapse:false,
      permission_routers:[{   
          hidden: false,
          meta: {
             icon: "el-icon-phone-outline",
              title: "pag1",
          },
          path: "/page1",               
        },
        { 
          hidden: false,
          meta: {
             icon: "el-icon-document",
              title: "page2",
          },
          path: "/page2",    
        },
        { 
          hidden: false,
          meta: {
             icon: "el-icon-location",
              title: "page3",
          },
          path: "/page3",    
        },
        { 
          hidden: false,
          meta: {
             icon: "el-icon-mobile-phone",
              title: "page4",
          },
          path: "/page4",    
        },
        { 
          hidden: false,
          meta: {
             icon: "el-icon-bell",
              title: "page5",
          },
          path: "/page5",    
        }]
    }
  },
  created () {},
  mounted () {},
  methods: {
    collapseShow(){
      this.collapse=!this.collapse
    },
    go(routerUrl){
      // 字符串
      this.$router.push(routerUrl)

      // // 对象
      // router.push({ path: 'home' })

      // // 命名的路由
      // router.push({ name: 'user', params: { userId: '123' }})

      // // 带查询参数,变成 /register?plan=private
      // router.push({ path: 'register', query: { plan: 'private' }})
    },
  }
}
</script>

<style lang='less'>
#app {
  display: flex;
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  // margin-top: 60px;
}

.headerss{
  margin-left: 230px;
  height: 54px;
  line-height: 54px;
 
}
.mains{
  flex: 1;
}
.active{
  margin-left:64px !important;
}
.el-header, .el-footer {
  margin-left: 230px;
  background: rgba(255,255,255,1);
  color: #333;
  text-align: center;
}
// .el-aside {
//   background: rgba(30,34,53,1);
//   color: #333;
//   text-align: center;
// }
.el-main {
  margin-left: 230px;
  background: rgba(244,245,248,1);
  color: #333;
}
</style>

//main.js引入
import '@/components/Sidebar/style/sidebar.scss' // global css
//sidebar.scss
@import './variables.scss';
@import './transition.scss';
  // 侧边栏
  .sidebar-container {
    transition: width 0.28s;
    text-align: left;
    width: 230px !important;//180px
    height: 100%;
    position: fixed;
    font-size: 0px;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 1001;
    overflow: hidden;
    //reset element-ui css
    .horizontal-collapse-transition {
      transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
    }
    .el-scrollbar__bar.is-vertical{
      right: 0px;
    }
    .scrollbar-wrapper {
      overflow-x: hidden!important;
      .el-scrollbar__view {
        height: 100%;
      }
    }
    .is-horizontal {
      display: none;
    }
    a {
      display: inline-block;
      width: 100%;
      overflow: hidden;
    }
    .svg-icon {
      margin-right: 16px;
    }
    .el-menu {
      border: none;
      height: 100%;
      // width: 100% ;
    }
    .is-active > .el-submenu__title{
      color: #f4f4f5!important;
    }
  }
  .hideSidebar {
    text-align: center;
    .sidebar-container {
      // width: 36px !important;
      
    }
    .main-container {
      margin-left: 36px;
    }
    .submenu-title-noDropdown {
      padding-left: 10px !important;
      position: relative;
      .el-tooltip {
        padding: 0 10px !important;
      }
    }
    .el-submenu {
      overflow: hidden;
      &>.el-submenu__title {
        padding-left: 10px !important;
        .el-submenu__icon-arrow {
          display: none;
        }
      }
    }
    .el-menu--collapse {
      .el-submenu {
        &>.el-submenu__title {
          &>span {
            height: 0;
            width: 0;
            overflow: hidden;
            visibility: hidden;
            display: inline-block;
          }
        }
      }
    }
  }
  .sidebar-container .nest-menu .el-submenu>.el-submenu__title,
  .sidebar-container .el-submenu .el-menu-item {
    min-width: 180px !important;
    background-color: $subMenuBg !important;
    &:hover {
      background-color: $menuHover !important;
    }
  }
  .el-menu--collapse .el-menu .el-submenu {
    min-width: 180px !important;
  }

  //适配移动端
  .mobile {
    .main-container {
      margin-left: 0px;
    }
    .sidebar-container {
      transition: transform .28s;
      width: 180px !important;
    }
    &.hideSidebar {
      .sidebar-container {
        transition-duration: 0.3s;
        transform: translate3d(-180px, 0, 0);
      }
    }
  }
  .withoutAnimation {
    .main-container,
    .sidebar-container {
      transition: none;
    }
  }
.el-menu--vertical{
  & >.el-menu{
    .svg-icon{
      margin-right: 16px;
    }
  }
}

//transition.scss
//globl transition css

/*fade*/
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.28s;
}

.fade-enter,
.fade-leave-active {
  opacity: 0;
}

/*fade-transform*/
.fade-transform-leave-active,
.fade-transform-enter-active {
  transition: all .5s;
}
.fade-transform-enter {
  opacity: 0;
  transform: translateX(-30px);
}
.fade-transform-leave-to {
  opacity: 0;
  transform: translateX(30px);
}

/*fade*/
.breadcrumb-enter-active,
.breadcrumb-leave-active {
  transition: all .5s;
}

.breadcrumb-enter,
.breadcrumb-leave-active {
  opacity: 0;
  transform: translateX(20px);
}

.breadcrumb-move {
  transition: all .5s;
}

.breadcrumb-leave-active {
  position: absolute;
}

//variables.scss
$menuBg:#304156;
$subMenuBg:#1f2d3d;
$menuHover:#001528;

//s/index
<template>
  <el-scrollbar wrap-class="scrollbar-wrapper">
    <el-menu
      :show-timeout="200"
      :default-active="$route.path"
      :collapse="collapse"
      mode="vertical"
      background-color="#304156"
      text-color="#bfcbd9"
      active-text-color="#409EFF"
    >
      <sidebar-item v-for="route in dataList" :key="route.path" :item="route" :base-path="route.path"/>
    </el-menu>
  </el-scrollbar>
</template>

<script>
import SidebarItem from './SidebarItem'
//main.js导入import '@/components/Sidebar/style/sidebar.scss' // global css
export default {
  components: { SidebarItem },
  props:{
    dataList:{
      type: Array,
      default: ''
    },
    collapse:{
      type: Boolean,
      default: false
    }
  },
  data(){
    return {
    }
  },
  computed: { 
  }
}
</script>
<style lang="scss">
  

</style>

//item.vue
<script>
export default {
  name: 'MenuItem',
  functional: true,
  props: {
    icon: {
      type: String,
      default: ''
    },
    title: {
      type: String,
      default: ''
    }
  },
  render(h, context) {
    const { icon, title } = context.props
    const vnodes = []

    if (icon) {
      // vnodes.push(<svg-icon icon-class={icon}/>)
     vnodes.push( <i class={icon}/>)
    }

    if (title) {
      vnodes.push(<span slot='title'>{(title)}</span>)
    }
    return vnodes
  }
}
</script>

//Sidebaritem.vue
<template>
  <div class="menu-wrapper">
      <template v-if="!item.children||!item.children.length>0">
        <router-link :to="{path:item.path}">
          <el-menu-item :index="item.path" :class="{'submenu-title-noDropdown':!isNest}">
            <item v-if="item.meta" :icon="item.meta.icon||item.meta.icon" :title="item.meta.title" />
          </el-menu-item>
        </router-link>
      </template>

      <el-submenu v-else :index="item.meta.title">
        <template slot="title">
          <item v-if="item.meta" :icon="item.meta.icon" :title="item.meta.title" />
        </template>
        <template v-for="child in item.children" v-if="!child.hidden">
          <sidebar-item
            v-if="child.children&&child.children.length>0"
            :is-nest="true"
            :item="child"
            :isOne='false'
            :key="child.title"
            :base-path="child.path"
            class="nest-menu" />
          <router-link v-else :to="{path:child.path}" :key="child.name">
            <el-menu-item :index="child.meta.path">
              <item v-if="child.meta" :icon="child.meta.icon" :title="child.meta.title" />
            </el-menu-item>
          </router-link>
        </template>
      </el-submenu>
    </div>
</template>

<script>
import path from 'path'
import Item from './Item'

export default {
  name: 'SidebarItem',
  components: { Item },
  props: {
    // route object
    item: {
      type: Object,
      required: true
    },
    isNest: {
      type: Boolean,
      default: false
    },
    basePath: {
      type: String,
      default: ''
    },
    isOne:{
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      onlyOneChild: null
    }
  },
  methods: {
    hasOneShowingChild(children, parent) {
      const showingChildren = children.filter(item => {
        if (item.hidden) {
          return false
        } else {
          // Temp set(will be used if only has one showing child)
          this.onlyOneChild = item
          return true
        }
      })

      // When there is only one child router, the child router is displayed by default
      if (showingChildren.length === 1) {
        return true
      }

      // Show parent if there are no child router to display
      if (showingChildren.length === 0) {
        this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
        return true
      }

      return false
    },
    resolvePath(routePath) {
        return routePath
    },
  }
}
</script>

相关文章

网友评论

      本文标题:vue左侧菜单栏,传入数据即可用

      本文链接:https://www.haomeiwen.com/subject/ttihqktx.html