From c3ee00472d06793edebd9ad08c07409daf2fe448 Mon Sep 17 00:00:00 2001 From: Pan Date: Wed, 2 May 2018 17:00:56 +0800 Subject: [PATCH] feat[sidebar]: add resonsive sidebar --- src/store/getters.js | 1 + src/store/modules/app.js | 20 ++++++++++-- src/styles/sidebar.scss | 35 +++++++++++++++++++-- src/views/layout/Layout.vue | 30 ++++++++++++------ src/views/layout/mixin/ResizeHandler.js | 41 +++++++++++++++++++++++++ 5 files changed, 113 insertions(+), 14 deletions(-) create mode 100644 src/views/layout/mixin/ResizeHandler.js diff --git a/src/store/getters.js b/src/store/getters.js index d99762d..7fbf1f4 100644 --- a/src/store/getters.js +++ b/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, diff --git a/src/store/modules/app.js b/src/store/modules/app.js index e49b16a..fca558f 100644 --- a/src/store/modules/app.js +++ b/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) } } } diff --git a/src/styles/sidebar.scss b/src/styles/sidebar.scss index 3641077..d69c434 100644 --- a/src/styles/sidebar.scss +++ b/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; + } + } } diff --git a/src/views/layout/Layout.vue b/src/views/layout/Layout.vue index dcdd549..369b902 100644 --- a/src/views/layout/Layout.vue +++ b/src/views/layout/Layout.vue @@ -1,5 +1,5 @@ diff --git a/src/views/layout/mixin/ResizeHandler.js b/src/views/layout/mixin/ResizeHandler.js new file mode 100644 index 0000000..b22c8bb --- /dev/null +++ b/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 }) + } + } + } + } +}