feat[sidebar]: add resonsive sidebar (#636)
This commit is contained in:
parent
88429bd809
commit
0e4ea0871c
|
@ -1,6 +1,7 @@
|
||||||
const getters = {
|
const getters = {
|
||||||
sidebar: state => state.app.sidebar,
|
sidebar: state => state.app.sidebar,
|
||||||
language: state => state.app.language,
|
language: state => state.app.language,
|
||||||
|
device: state => state.app.device,
|
||||||
visitedViews: state => state.tagsView.visitedViews,
|
visitedViews: state => state.tagsView.visitedViews,
|
||||||
cachedViews: state => state.tagsView.cachedViews,
|
cachedViews: state => state.tagsView.cachedViews,
|
||||||
token: state => state.user.token,
|
token: state => state.user.token,
|
||||||
|
|
|
@ -3,8 +3,10 @@ import Cookies from 'js-cookie'
|
||||||
const app = {
|
const app = {
|
||||||
state: {
|
state: {
|
||||||
sidebar: {
|
sidebar: {
|
||||||
opened: !+Cookies.get('sidebarStatus')
|
opened: !+Cookies.get('sidebarStatus'),
|
||||||
|
withoutAnimation: false
|
||||||
},
|
},
|
||||||
|
device: 'desktop',
|
||||||
language: Cookies.get('language') || 'en'
|
language: Cookies.get('language') || 'en'
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
|
@ -15,6 +17,15 @@ const app = {
|
||||||
Cookies.set('sidebarStatus', 0)
|
Cookies.set('sidebarStatus', 0)
|
||||||
}
|
}
|
||||||
state.sidebar.opened = !state.sidebar.opened
|
state.sidebar.opened = !state.sidebar.opened
|
||||||
|
state.sidebar.withoutAnimation = false
|
||||||
|
},
|
||||||
|
CLOSE_SIDEBAR: (state, withoutAnimation) => {
|
||||||
|
Cookies.set('sidebarStatus', 1)
|
||||||
|
state.sidebar.opened = false
|
||||||
|
state.sidebar.withoutAnimation = withoutAnimation
|
||||||
|
},
|
||||||
|
TOGGLE_DEVICE: (state, device) => {
|
||||||
|
state.device = device
|
||||||
},
|
},
|
||||||
SET_LANGUAGE: (state, language) => {
|
SET_LANGUAGE: (state, language) => {
|
||||||
state.language = language
|
state.language = language
|
||||||
|
@ -25,6 +36,12 @@ const app = {
|
||||||
toggleSideBar({ commit }) {
|
toggleSideBar({ commit }) {
|
||||||
commit('TOGGLE_SIDEBAR')
|
commit('TOGGLE_SIDEBAR')
|
||||||
},
|
},
|
||||||
|
closeSideBar({ commit }, { withoutAnimation }) {
|
||||||
|
commit('CLOSE_SIDEBAR', withoutAnimation)
|
||||||
|
},
|
||||||
|
toggleDevice({ commit }, device) {
|
||||||
|
commit('TOGGLE_DEVICE', device)
|
||||||
|
},
|
||||||
setLanguage({ commit }, language) {
|
setLanguage({ commit }, language) {
|
||||||
commit('SET_LANGUAGE', language)
|
commit('SET_LANGUAGE', language)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
#app {
|
#app {
|
||||||
|
|
||||||
// 主体区域
|
// 主体区域
|
||||||
.main-container {
|
.main-container {
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
transition: margin-left .28s;
|
transition: margin-left .28s;
|
||||||
margin-left: 180px;
|
margin-left: 180px;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 侧边栏
|
// 侧边栏
|
||||||
.sidebar-container {
|
.sidebar-container {
|
||||||
.horizontal-collapse-transition {
|
.horizontal-collapse-transition {
|
||||||
|
@ -32,6 +34,7 @@
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.hideSidebar {
|
.hideSidebar {
|
||||||
.sidebar-container {
|
.sidebar-container {
|
||||||
width: 36px !important;
|
width: 36px !important;
|
||||||
|
@ -62,6 +65,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-container .nest-menu .el-submenu>.el-submenu__title,
|
.sidebar-container .nest-menu .el-submenu>.el-submenu__title,
|
||||||
.sidebar-container .el-submenu .el-menu-item {
|
.sidebar-container .el-submenu .el-menu-item {
|
||||||
min-width: 180px !important;
|
min-width: 180px !important;
|
||||||
|
@ -73,4 +77,29 @@
|
||||||
.el-menu--collapse .el-menu .el-submenu {
|
.el-menu--collapse .el-menu .el-submenu {
|
||||||
min-width: 180px !important;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="app-wrapper" :class="{hideSidebar:!sidebar.opened}">
|
<div class="app-wrapper" :class="classObj">
|
||||||
<sidebar class="sidebar-container"></sidebar>
|
<sidebar class="sidebar-container"></sidebar>
|
||||||
<div class="main-container">
|
<div class="main-container">
|
||||||
<navbar></navbar>
|
<navbar></navbar>
|
||||||
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Navbar, Sidebar, AppMain, TagsView } from './components'
|
import { Navbar, Sidebar, AppMain, TagsView } from './components'
|
||||||
|
import ResizeMixin from './mixin/ResizeHandler'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'layout',
|
name: 'layout',
|
||||||
|
@ -20,9 +21,20 @@ export default {
|
||||||
AppMain,
|
AppMain,
|
||||||
TagsView
|
TagsView
|
||||||
},
|
},
|
||||||
|
mixins: [ResizeMixin],
|
||||||
computed: {
|
computed: {
|
||||||
sidebar() {
|
sidebar() {
|
||||||
return this.$store.state.app.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'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue