Selaa lähdekoodia

feat[sidebar]: add resonsive sidebar

Pan 7 vuotta sitten
vanhempi
commit
c3ee00472d

+ 1 - 0
src/store/getters.js

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

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

@@ -3,8 +3,10 @@ import Cookies from 'js-cookie'
3
 const app = {
3
 const app = {
4
   state: {
4
   state: {
5
     sidebar: {
5
     sidebar: {
6
-      opened: !+Cookies.get('sidebarStatus')
7
-    }
6
+      opened: !+Cookies.get('sidebarStatus'),
7
+      withoutAnimation: false
8
+    },
9
+    device: 'desktop'
8
   },
10
   },
9
   mutations: {
11
   mutations: {
10
     TOGGLE_SIDEBAR: state => {
12
     TOGGLE_SIDEBAR: state => {
@@ -14,11 +16,25 @@ const app = {
14
         Cookies.set('sidebarStatus', 0)
16
         Cookies.set('sidebarStatus', 0)
15
       }
17
       }
16
       state.sidebar.opened = !state.sidebar.opened
18
       state.sidebar.opened = !state.sidebar.opened
19
+    },
20
+    CLOSE_SIDEBAR: (state, withoutAnimation) => {
21
+      Cookies.set('sidebarStatus', 1)
22
+      state.sidebar.opened = false
23
+      state.sidebar.withoutAnimation = withoutAnimation
24
+    },
25
+    TOGGLE_DEVICE: (state, device) => {
26
+      state.device = device
17
     }
27
     }
18
   },
28
   },
19
   actions: {
29
   actions: {
20
     ToggleSideBar: ({ commit }) => {
30
     ToggleSideBar: ({ commit }) => {
21
       commit('TOGGLE_SIDEBAR')
31
       commit('TOGGLE_SIDEBAR')
32
+    },
33
+    CloseSideBar({ commit }, { withoutAnimation }) {
34
+      commit('CLOSE_SIDEBAR', withoutAnimation)
35
+    },
36
+    ToggleDevice({ commit }, device) {
37
+      commit('TOGGLE_DEVICE', device)
22
     }
38
     }
23
   }
39
   }
24
 }
40
 }

+ 32 - 3
src/styles/sidebar.scss

@@ -1,11 +1,13 @@
1
 #app {
1
 #app {
2
+
2
   // 主体区域
3
   // 主体区域
3
   .main-container {
4
   .main-container {
4
     min-height: 100%;
5
     min-height: 100%;
5
     transition: margin-left .28s;
6
     transition: margin-left .28s;
6
     margin-left: 180px;
7
     margin-left: 180px;
7
   }
8
   }
8
-  // 侧边栏
9
+
10
+   // 侧边栏
9
   .sidebar-container {
11
   .sidebar-container {
10
     .horizontal-collapse-transition {
12
     .horizontal-collapse-transition {
11
       transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
13
       transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
@@ -32,6 +34,7 @@
32
       width: 100% !important;
34
       width: 100% !important;
33
     }
35
     }
34
   }
36
   }
37
+
35
   .hideSidebar {
38
   .hideSidebar {
36
     .sidebar-container {
39
     .sidebar-container {
37
       width: 36px !important;
40
       width: 36px !important;
@@ -62,8 +65,9 @@
62
       }
65
       }
63
     }
66
     }
64
   }
67
   }
65
-  .nest-menu .el-submenu>.el-submenu__title,
66
-  .el-submenu .el-menu-item {
68
+
69
+  .sidebar-container .nest-menu .el-submenu>.el-submenu__title,
70
+  .sidebar-container .el-submenu .el-menu-item {
67
     min-width: 180px !important;
71
     min-width: 180px !important;
68
     background-color: $subMenuBg !important;
72
     background-color: $subMenuBg !important;
69
     &:hover {
73
     &:hover {
@@ -73,4 +77,29 @@
73
   .el-menu--collapse .el-menu .el-submenu {
77
   .el-menu--collapse .el-menu .el-submenu {
74
     min-width: 180px !important;
78
     min-width: 180px !important;
75
   }
79
   }
80
+
81
+  //适配移动端
82
+  .mobile {
83
+    .main-container {
84
+      margin-left: 0px;
85
+    }
86
+    .sidebar-container {
87
+      top: 50px;
88
+      transition: transform .28s;
89
+      width: 180px !important;
90
+    }
91
+    &.hideSidebar {
92
+      .sidebar-container {
93
+        transition-duration: 0.3s;
94
+        transform: translate3d(-180px, 0, 0);
95
+      }
96
+    }
97
+  }
98
+
99
+  .withoutAnimation {
100
+    .main-container,
101
+    .sidebar-container {
102
+      transition: none;
103
+    }
104
+  }
76
 }
105
 }

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

@@ -1,5 +1,5 @@
1
 <template>
1
 <template>
2
-  <div class="app-wrapper" :class="{hideSidebar:!sidebar.opened}">
2
+  <div class="app-wrapper" :class="classObj">
3
     <sidebar class="sidebar-container"></sidebar>
3
     <sidebar class="sidebar-container"></sidebar>
4
     <div class="main-container">
4
     <div class="main-container">
5
       <navbar></navbar>
5
       <navbar></navbar>
@@ -9,7 +9,8 @@
9
 </template>
9
 </template>
10
 
10
 
11
 <script>
11
 <script>
12
-import { Navbar, Sidebar, AppMain } from '@/views/layout/components'
12
+import { Navbar, Sidebar, AppMain } from './components'
13
+import ResizeMixin from './mixin/ResizeHandler'
13
 
14
 
14
 export default {
15
 export default {
15
   name: 'layout',
16
   name: 'layout',
@@ -18,20 +19,31 @@ export default {
18
     Sidebar,
19
     Sidebar,
19
     AppMain
20
     AppMain
20
   },
21
   },
22
+  mixins: [ResizeMixin],
21
   computed: {
23
   computed: {
22
     sidebar() {
24
     sidebar() {
23
       return this.$store.state.app.sidebar
25
       return this.$store.state.app.sidebar
26
+    },
27
+    device() {
28
+      return this.$store.state.app.device
29
+    },
30
+    classObj() {
31
+      return {
32
+        hideSidebar: !this.sidebar.opened,
33
+        withoutAnimation: this.sidebar.withoutAnimation,
34
+        mobile: this.device === 'mobile'
35
+      }
24
     }
36
     }
25
   }
37
   }
26
 }
38
 }
27
 </script>
39
 </script>
28
 
40
 
29
 <style rel="stylesheet/scss" lang="scss" scoped>
41
 <style rel="stylesheet/scss" lang="scss" scoped>
30
-@import "src/styles/mixin.scss";
31
-.app-wrapper {
32
-  @include clearfix;
33
-  position: relative;
34
-  height: 100%;
35
-  width: 100%;
36
-}
42
+  @import "src/styles/mixin.scss";
43
+  .app-wrapper {
44
+    @include clearfix;
45
+    position: relative;
46
+    height: 100%;
47
+    width: 100%;
48
+  }
37
 </style>
49
 </style>

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

@@ -0,0 +1,41 @@
1
+import store from '@/store'
2
+
3
+const { body } = document
4
+const WIDTH = 1024
5
+const RATIO = 3
6
+
7
+export default {
8
+  watch: {
9
+    $route(route) {
10
+      if (this.device === 'mobile' && this.sidebar.opened) {
11
+        store.dispatch('CloseSideBar', { withoutAnimation: false })
12
+      }
13
+    }
14
+  },
15
+  beforeMount() {
16
+    window.addEventListener('resize', this.resizeHandler)
17
+  },
18
+  mounted() {
19
+    const isMobile = this.isMobile()
20
+    if (isMobile) {
21
+      store.dispatch('ToggleDevice', 'mobile')
22
+      store.dispatch('CloseSideBar', { withoutAnimation: true })
23
+    }
24
+  },
25
+  methods: {
26
+    isMobile() {
27
+      const rect = body.getBoundingClientRect()
28
+      return rect.width - RATIO < WIDTH
29
+    },
30
+    resizeHandler() {
31
+      if (!document.hidden) {
32
+        const isMobile = this.isMobile()
33
+        store.dispatch('ToggleDevice', isMobile ? 'mobile' : 'desktop')
34
+
35
+        if (isMobile) {
36
+          store.dispatch('CloseSideBar', { withoutAnimation: true })
37
+        }
38
+      }
39
+    }
40
+  }
41
+}