1,安装scss插件

cnpm i node-sass sass-loader -S

2,安装element-ui

cnpm i element-ui -S

main.js中引入element-ui

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)

3,项目结构

App.vue

<template>
  <div id="app">
    <router-view/>
  </div>
</template>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
*{
  margin: 0;
  padding: 0;
}
</style>

main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

 router文件夹下的index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'home',
    redirect:'/index',
    component: Home,
    meta:{title:'首页'},
    children:[
      {
        path:'/index',
        name:'index',
        component:()=>import('@/views/index.vue'),
        meta:{
          title:'系统首页',
          hideclose:true
        }
      },
      {
        path:'/test/test1',
        name:'test1',
        component:()=>import('@/views/test/test1.vue'),
        meta:{
          title:'test1'
        }
      },
      {
        path:'/test/test2',
        name:'test2',
        component:()=>import('@/views/test/test2.vue'),
        meta:{
          title:'test2'
        }
      }
    ]
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

common文件夹目录

bus.js

import Vue from 'vue';
// 使用 Event Bus
const bus = new Vue();
export default bus;

header.vue

<template>
<div class="header">
  <div class="left">
    <ul>
      <li  class="collapse-btn"  @click="collapseChange">
        <i class="el-icon-menu"></i>
      </li>
    </ul>
  </div>

  </div>
  
</template>
<script>
  import bus from './bus'
  export default{
    data(){
      return{
        isCollapse:false,
      }
    },
    methods:{
      collapseChange(){
        this.isCollapse=!this.isCollapse
        bus.$emit('collapse',this.isCollapse)
  }}}
</script>

<style lang='scss'>

.header {
  display: flex;
  flex-flow: row nowrap;
  justify-content: space-between;
  // font-size: 22px;
  color: #fff;
  background-color: #11c26d;
  height: 60px;
      .left{
         .collapse-btn {
                   width: 45px;
         }
    }
      ul {
    list-style: none;
    li {
      float: left;
      line-height: 60px;
      height: 60px;
      text-align: center;
      padding: 0 10px;
      cursor: pointer;
    }
    i {
      line-height: 60px;
    }
    li:hover {
      background-color: #337ecc;
      
    }
  }
}
</style>

 aside.vue

<template>
  <div class="sidebar">
    <el-menu
      :collapse="isCollapse"
      :default-active="$route.path"
      class="el-menu-vertical-demo menu"
      active-text-color="#10B9D3"
      unique-opened
      router
    >
      <el-menu-item index="/index">
        <i class="el-icon-s-home"></i>
        <span slot="title">首页</span>
      </el-menu-item>
     <template v-for="(menu_one,i) in menuData" >
        <el-submenu :key="i" :index="menu_one.path">
          <template slot="title">
            <i :class="menu_one.icon"></i>
            <span>{{menu_one.title}}</span>
          </template>
          <el-menu-item
            v-for="(menu_two,i) in menu_one.subs"
            :key="i"
            :index="menu_two.path"
          >
            <i :class="menu_two.icon"></i>
            <span>{{menu_two.title}}</span>
          </el-menu-item>
        </el-submenu>
      </template>
   </el-menu>
  </div>
</template>
<script>
import bus from './bus';
export default {
  data() {
    return {
      isCollapse: false,
      menuData: [
        {
          icon: "el-icon-map-location",
          title: "Test",
          path: "p_mapManger",
          subs: [
            {
              path: "/test/test1",
              title: "test1",
              icon: "el-icon-crop"
            },
            {
              path: "/test/test2",
              title: "test2",
              icon: "el-icon-crop"
            }
          ]
        }
      ]
    };
  },
  created() {
    bus.$on('collapse', msg => {
      this.isCollapse = msg;
    });
   }
}
</script>
<style lang='scss'>
.sidebar {
  display: flex;
  flex-flow: column nowrap;
  height: 100vh;
  .el-menu-vertical-demo:not(.el-menu--collapse) {
    width: 300px;
  }
  .menu{
    height: 100%;
  }
}
</style>

tag.vue

<template>
  <div class="_tag">
    <el-scrollbar style="margin-right: 6px;">
      <div class="left">
        <el-tag
          v-for="tag in tagsList"
          :key="tag.title"
          :closable="!tag.hideclose"
          :type="isActive(tag)"
          @close="handleCloseTag(tag)"
        >
          <router-link :to="tag.path" class="tag-title">{{ tag.title }}</router-link>
        </el-tag>
      </div>
    </el-scrollbar>

    <el-dropdown @command="handleCloseBtn" class="_dropdown">
      <el-button type="primary" size="small">
        标签选项
        <i class="el-icon-arrow-down el-icon--right"></i>
      </el-button>
      <el-dropdown-menu slot="dropdown">
        <el-dropdown-item command="closeOther">关闭其它</el-dropdown-item>
        <el-dropdown-item command="closeAll">关闭所有</el-dropdown-item>
      </el-dropdown-menu>
    </el-dropdown>
  </div>
</template>
<style lang="scss">
._tag {
  // border: 1px solid green;
  flex: 0 0 40px;
  display: flex;
  align-items: center;
  background-color: white;
  border-bottom: 1px solid #e6e6e6;
  justify-content: space-between;
  .left {
    display: flex;
    height: 40px;
    align-items: center;
    .el-tag {
      margin-left: 6px;
      .tag-title {
        color: black;
        padding: 8px 2px;
        text-decoration: none;
      }
    }
  }
  ._dropdown {
    height: 40px;
    display: flex;
    align-items: center;
    background-color: white;
    box-shadow: rgba(0, 0, 0, 0.1) -3px 0px 15px 3px;
    padding: 0 5px;
  }
}
</style>

<script>
export default {
  data() {
    return {
      tagsList: []
    };
  },
  mounted() {
    this.setTags(this.$route);
    // console.log("this.$route:", this.$route);
  },
  methods: {
    //设置标签
    setTags(route) {
      const isExsit = this.tagsList.some(item => {
        return item.path === route.fullPath;
      });
      if (isExsit == false) {
        this.tagsList.push({
          title: route.meta.title, //标签名
          name: route.name, //路由里的name对应vue页的name,标签列表里的name可以做vue页面缓存
          path: route.fullPath, //路由
          hideclose: route.meta.hideclose ? route.meta.hideclose : false //是否隐藏关闭
        });
      }
    },
    //关闭标签
    handleCloseTag(tag) {
      this.tagsList.splice(this.tagsList.indexOf(tag), 1);
      // array.splice(index,howmany) 从索引为index处删除howmany个元素
      if (this.tagsList.length > 0) {
        this.$router.push(this.tagsList[this.tagsList.length - 1].path);
      } else {
        // this.$router.push("/index");
        this.$router.push({ name: "sadmasMain" });
      }
    },
    //关闭功能按钮
    handleCloseBtn(command) {
      if (command == "closeOther") {
        //关闭其它,保留没有删除的标签。find() 方法返回通过测试(函数内判断)的数组的第一个元素的值。
        var activeTag = this.tagsList.find(item => {
          return item.path == this.$route.fullPath;
        }); //查找第一个满足的
        var noCloseTags = this.getNoCloseTabs();
        if (
          noCloseTags.some(item => {
            return item.path == activeTag.path && item.title == activeTag.title;
          }) == false
        ) {
          //不包含
          noCloseTags = noCloseTags.concat(activeTag);
        }
        this.tagsList = noCloseTags;
      } else if (command == "closeAll") {
        //关闭所有,保留没有删除的标签
        this.tagsList = this.getNoCloseTabs();
        this.$router.push(this.tagsList[this.tagsList.length - 1].path);
      }
    },
    getNoCloseTabs() {
      //获取没有删除的标签
      var noCloseList = this.tagsList.filter(item => {
        return item.hideclose == true;
      });
      return noCloseList;
    },
    //是否选中
    isActive(tag) {
      if (tag.path == this.$route.fullPath) {
        return "";
      } else {
        return "info";
      }
    }
  },
  watch: {
    //路由变化,设置标签
    $route(newValue, oldValue) {
      this.setTags(newValue);
    }
  }
};
</script>

footer.vue

<template>
  <el-footer class="_footer">
    <span class="text">footer@2019</span>
  </el-footer>
</template>
<style lang="scss">
._footer {
  display: flex;
  justify-content: center;
  align-items: center;
  border-top:1px solid #e6e6e6;
  .text {
    color: #606266;
  }
}
</style>

test文件夹目录

test1.vue

<template>
    <div class="test1">这是test1.vue</div>
</template>
<style lang="scss">
.test1 {
  display: flex;
  flex: auto;
}
</style>

test2.vue

<template>
    <div class="test2">这是test2.vue</div>
</template>
<style lang="scss">
.test2 {
  display: flex;
  flex: auto;
}
</style>

index.vue

<template>
    <div>首页</div>
</template>

Home.vue

<template>

  <div class="homeContainer">
     <vAside></vAside>
     <div class="headContainer">
        <vHeader></vHeader>
           <div class="tagContainer">
               <vTag></vTag>
               <div class="mainContainer">
                  <div class="main">
                     <router-view></router-view>
                  </div>
                  <vFooter class="footer"></vFooter>
               </div>
            </div>
      </div>
  </div>
  
</template>
<script>
import vHeader from '@/views/common/header';
import vAside from '@/views/common/aside';
import vTag from '@/views/common/tag';
import vFooter from '@/views/common/footer';

export default {
  data() {
    return {
         isCollapse: false
    };
  },
  components: { vHeader, vAside,vTag,vFooter}
};
</script>
<style lang='scss'>
.homeContainer{
  // border: 1px solid red;
        box-sizing: border-box;

  height: 100vh;
  display: flex;
  flex-flow: row nowrap;
    .headContainer{
        // border: 1px solid red;
        box-sizing: border-box;

      display: flex;
      flex-flow: column nowrap;
      flex: auto;
      .tagContainer{
        //  border: 1px solid blue;
         display: flex;
         flex-flow: column nowrap;
         flex: auto;

          .mainContainer{
            // border: 1px solid blue;
            background-color: #f0f0f0; //灰色背景

            box-sizing: border-box;
            display: flex;
            flex-flow: column nowrap;
            flex: auto;
            
            overflow: auto;
            height: calc(100vh - 100px);

            .main{
              // border:1px solid green;
              padding: 10px;

              display: flex;
                flex: auto;
            // overflow: auto;

            }
            .footer{
            // border: 1px solid orange;

              flex: 0 0 60px;
            }

          }
      }

  }
  
}

</style>


运行效果

Logo

前往低代码交流专区

更多推荐