vue-PC端实现菜单栏拖拽改变菜单栏宽度
本文解决方案参考vue-split-pane插件
思路
页面布局中,菜单栏的宽度决定着页面的其他布局宽度,故改变菜单栏宽度,其他布局宽度随着菜单栏宽度变化即可。
菜单栏拖拽改变菜单栏宽度,使用原生事件:onmousedown(鼠标按下事件)、onmousemove(鼠标移动事件)、onmouseup(松开鼠标事件)。
实现
项目整体布局文件
<template>
<div
ref="layout"
@mouseup="onMouseUp"
@mousemove="onMouseMove"
>
<!-- 头部导航 -->
<navbar />
<!-- 左侧菜单栏 -->
<sidebar class="sidebar-container" />
<!-- 拖拽对象组件 -->
<resizer
v-show="isMenuOpend"
@mousedown.native="onMouseDown"
/>
<!-- 页面主内容组件 -->
<div class="main-container">
<tags-view />
<app-main />
</div>
</div>
</template>
<script>
import { Navbar, Sidebar, AppMain, TagsView } from './components';
import Resizer from './components/Resizer';
export default {
name: 'Layout',
components: {
Navbar,
Sidebar,
AppMain,
TagsView,
Resizer
},
data() {
return {
active: false
};
},
computed: {
isMenuOpend() {
return this.sidebar.opened;
},
sidebar() {
return this.$store.state.app.sidebar;
}
},
methods: {
onMouseDown() {
// 记录鼠标按下
this.active = true;
},
onMouseUp() {
// 记录鼠标抬起
this.active = false;
},
onMouseMove(e) {
// 鼠标没有按键或者是没有初始化
if (e.buttons === 0 || e.which === 0) {
// 认为鼠标抬起
this.active = false;
}
// 如果鼠标按下了
if (this.active) {
// 并且距离网页水平位置在200与400之间,就改变菜单栏的宽度
if (e.clientX > 200 && e.clientX < 400) {
this.$refs.layout.style.setProperty('--sideBarWidth', e.clientX + 'px');
}
}
}
}
};
</script>
resizer组件
<template>
<div :class="classes" />
</template>
<script>
export default {
props: {
className: String
},
computed: {
classes() {
const classes = ['splitter-pane-resizer', this.className];
return classes.join(' ');
}
}
};
</script>
<style lang="scss" scoped>
.splitter-pane-resizer {
box-sizing: border-box;
background: #000;
position: absolute;
opacity: .2;
z-index: 1;
background-clip: padding-box;
width: 11px;
height: 100%;
margin-left: -5px;
border-left: 5px solid rgba(255, 255, 255, 0);
border-right: 5px solid rgba(255, 255, 255, 0);
// 光标
cursor: col-resize;
// 使用了scss变量
left: $sideBarWidth;
}
</style>
tips
- e.which
e.which之前没接触过,百度了一下:
e.which不是一个事件,which是event对象的一个属性,大多数人e在事件处理程序中标注该属性。它包含被按下以触发事件的键的关键代码(例如:keydown,keyup)。
document.onkeypress = function(myEvent) { // doesn't have to be "e"
console.log(myEvent.which);
};
使用该代码,控制台将打印出您在键盘上按下的任何按键的代码。
e.which对应的输入字符
| e.which属性值 | 对应输入值 |
|---|---|
| 1 | 鼠标左键 |
| 2 | 鼠标中键(滚轮) |
| 3 | 鼠标右键 |
| 48-57 | 对应字符0-9 |
| 65-90 | 对应字符A-Z |
| 97-122 | 对应字符a-z |
| 8 | Backspace键 |
| 9 | Tab键 |
| 13 | Enter键 |
| 16 | Shift键 |
| 17 | Ctrl键 |
| 20 | Alt键 |
| 27 | Esc键 |
| 33-36 | 对应按键PageUp,PageDown,End,Home |
| 37-40 | 对应左上右下方向键 |
| 45-46 | 对应Insert,Delete键 |
| 48-57 | 对应按键0-9,非小键盘 |
| 65-90 | 对应按键A-Z |
| 91 | Windows键 |
| 96-105 | 对应按键0-9,小键盘 |
| 106,107,109,110,111 | 对应按键 * + - . / ,小键盘 |
| 112-123 | 对应按键f1-f12 |
- 使用js改变scss变量
scss变量首先要在scss文件中声明,并且在所有希望使用菜单栏宽度的地方都使用这个变量。
// scss变量名 js引用的变量名 默认值
$sideBarWidth: var(--sideBarWidth, 200px);
将scss文件引入到vue文件中(引入方式多种多样,任意一种都可以,全局也可以,局部也可以)。
在js中修改变量的值
this.$refs.layout.style.setProperty('--sideBarWidth', e.clientX + 'px');
끝
本文使用 mdnice 排版