Prechádzať zdrojové kódy

feat[sidebar]: add resonsive sidebar

Pan 7 rokov pred
rodič
commit
c3ee00472d

+ 1 - 0
src/store/getters.js

@@ -1,5 +1,6 @@
 const getters = {
   sidebar: state => state.app.sidebar,
+  device: state => state.app.device,
   token: state => state.user.token,
   avatar: state => state.user.avatar,
   name: state => state.user.name,

+ 18 - 2
src/store/modules/app.js

@@ -3,8 +3,10 @@ import Cookies from 'js-cookie'
 const app = {
   state: {
     sidebar: {
-      opened: !+Cookies.get('sidebarStatus')
-    }
+      opened: !+Cookies.get('sidebarStatus'),
+      withoutAnimation: false
+    },
+    device: 'desktop'
   },
   mutations: {
     TOGGLE_SIDEBAR: state => {
@@ -14,11 +16,25 @@ const app = {
         Cookies.set('sidebarStatus', 0)
       }
       state.sidebar.opened = !state.sidebar.opened
+    },
+    CLOSE_SIDEBAR: (state, withoutAnimation) => {
+      Cookies.set('sidebarStatus', 1)
+      state.sidebar.opened = false
+      state.sidebar.withoutAnimation = withoutAnimation
+    },
+    TOGGLE_DEVICE: (state, device) => {
+      state.device = device
     }
   },
   actions: {
     ToggleSideBar: ({ commit }) => {
       commit('TOGGLE_SIDEBAR')
+    },
+    CloseSideBar({ commit }, { withoutAnimation }) {
+      commit('CLOSE_SIDEBAR', withoutAnimation)
+    },
+    ToggleDevice({ commit }, device) {
+      commit('TOGGLE_DEVICE', device)
     }
   }
 }

+ 32 - 3
src/styles/sidebar.scss

@@ -1,11 +1,13 @@
 #app {
+
   // 主体区域
   .main-container {
     min-height: 100%;
     transition: margin-left .28s;
     margin-left: 180px;
   }
-  // 侧边栏
+
+   // 侧边栏
   .sidebar-container {
     .horizontal-collapse-transition {
       transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
@@ -32,6 +34,7 @@
       width: 100% !important;
     }
   }
+
   .hideSidebar {
     .sidebar-container {
       width: 36px !important;
@@ -62,8 +65,9 @@
       }
     }
   }
-  .nest-menu .el-submenu>.el-submenu__title,
-  .el-submenu .el-menu-item {
+
+  .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 {
@@ -73,4 +77,29 @@
   .el-menu--collapse .el-menu .el-submenu {
     min-width: 180px !important;
   }
+
+  //适配移动端
+  .mobile {
+    .main-container {
+      margin-left: 0px;
+    }
+    .sidebar-container {
+      top: 50px;
+      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;
+    }
+  }
 }

+ 21 - 9
src/views/layout/Layout.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="app-wrapper" :class="{hideSidebar:!sidebar.opened}">
+  <div class="app-wrapper" :class="classObj">
     <sidebar class="sidebar-container"></sidebar>
     <div class="main-container">
       <navbar></navbar>
@@ -9,7 +9,8 @@
 </template>
 
 <script>
-import { Navbar, Sidebar, AppMain } from '@/views/layout/components'
+import { Navbar, Sidebar, AppMain } from './components'
+import ResizeMixin from './mixin/ResizeHandler'
 
 export default {
   name: 'layout',
@@ -18,20 +19,31 @@ export default {
     Sidebar,
     AppMain
   },
+  mixins: [ResizeMixin],
   computed: {
     sidebar() {
       return this.$store.state.app.sidebar
+    },
+    device() {
+      return this.$store.state.app.device
+    },
+    classObj() {
+      return {
+        hideSidebar: !this.sidebar.opened,
+        withoutAnimation: this.sidebar.withoutAnimation,
+        mobile: this.device === 'mobile'
+      }
     }
   }
 }
 </script>
 
 <style rel="stylesheet/scss" lang="scss" scoped>
-@import "src/styles/mixin.scss";
-.app-wrapper {
-  @include clearfix;
-  position: relative;
-  height: 100%;
-  width: 100%;
-}
+  @import "src/styles/mixin.scss";
+  .app-wrapper {
+    @include clearfix;
+    position: relative;
+    height: 100%;
+    width: 100%;
+  }
 </style>

+ 41 - 0
src/views/layout/mixin/ResizeHandler.js

@@ -0,0 +1,41 @@
+import store from '@/store'
+
+const { body } = document
+const WIDTH = 1024
+const RATIO = 3
+
+export default {
+  watch: {
+    $route(route) {
+      if (this.device === 'mobile' && this.sidebar.opened) {
+        store.dispatch('CloseSideBar', { withoutAnimation: false })
+      }
+    }
+  },
+  beforeMount() {
+    window.addEventListener('resize', this.resizeHandler)
+  },
+  mounted() {
+    const isMobile = this.isMobile()
+    if (isMobile) {
+      store.dispatch('ToggleDevice', 'mobile')
+      store.dispatch('CloseSideBar', { withoutAnimation: true })
+    }
+  },
+  methods: {
+    isMobile() {
+      const rect = body.getBoundingClientRect()
+      return rect.width - RATIO < WIDTH
+    },
+    resizeHandler() {
+      if (!document.hidden) {
+        const isMobile = this.isMobile()
+        store.dispatch('ToggleDevice', isMobile ? 'mobile' : 'desktop')
+
+        if (isMobile) {
+          store.dispatch('CloseSideBar', { withoutAnimation: true })
+        }
+      }
+    }
+  }
+}