目录
介绍
- 实现左侧菜单收起展开,悬停展开
- 实现拖拽控制左右内容动态宽度
1.flex布局实现右侧内容自适应
- 左侧为 aside,右侧为 main
- 将 main 设置为 flex:1
index.html
<div class="container">
<aside class="transition">
<nav>
<ul>
<li>所有事务</li>
<li>未处理事务</li>
<li>最近已查看</li>
<li>最近已解决</li>
<li>最近已更新</li>
</ul>
</nav>
</aside>
<div class="side-bar">
<div class="switch-bar"><span class="iconfont icon-arrowleft">
<div class="switch-display"></div>
</span>
</div>
<div class="resize-bar"></div>
</div>
<main>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Voluptas unde recusandae esse, vitae nesciunt corporis ipsum quod harum natus sunt suscipit quaerat veritatis sequi sapiente provident sint temporibus cupiditate laboriosam.</main>
</div>
index.css
div.container {
display: flex;
width: 100%;
height: calc(100vh - var(--header-height));
margin-top: var(--header-height);
overflow: hidden;
}
2.控制菜单状态(展开/收起)
- 通过 css 变量 --left-side-width 即菜单的宽度,判断菜单收起展开状态
index.js
/**
* 修改菜单栏状态,展开或收起,同时修改按钮图标
*/
function changeSideState() {
let asideWidth = var_get('--left-side-width', 'px')
// 收起状态
if (asideWidth !== 20) {
collapseSide()
} else {
openSide()
}
}
- 折叠菜单,设置宽度,添加折叠类名 collapse,控制按钮图标,收起时不允许拖拽
index.js
// 折叠菜单,设置宽度,添加折叠类名,控制按钮图标,收起时不允许拖拽
function collapseSide() {
var_set('--left-side-width', '20px')
aside.classList.add('collapse')
switchBar.children[0].classList.remove('icon-arrowleft')
switchBar.children[0].classList.add('icon-arrow-right')
// 菜单收起状态,取消拖拽事件
sideBar.removeEventListener('mousedown', dragLine)
}
- 展开菜单,设置宽度,移除折叠类名 collapse,控制按钮图标,展开时允许拖拽
index.js
// 展开菜单,设置宽度,移除折叠类名,控制按钮图标,展开时允许拖拽
function openSide() {
var_set('--left-side-width', var_get('--left-side-base-width'))
aside.classList.remove('collapse')
switchBar.children[0].classList.add('icon-arrowleft')
switchBar.children[0].classList.remove('icon-arrow-right')
aside.classList.remove('fix')
// 菜单打开状态,添加拖拽事件
sideBar.addEventListener('mousedown', dragLine)
}
2.1 获取/设置 css 变量
var r = document.querySelector(':root');
// 设置
r.style.setProperty('变量名', '变量值');
// 获取
var rs = getComputedStyle(r);
var result = rs.getPropertyValue('变量名')
- 为了方便使用,我写成了两个函数
index.js
/** 获取css变量
* @param var_name 变量名称
* @param var_unit 变量单位,可选
**/
function var_get(var_name,var_unit) {
// Get the styles (properties and values) for the root
var rs = getComputedStyle(r);
var result = rs.getPropertyValue(var_name)
if (var_unit) {
return Number(result.replace(var_unit,''))
}
return result
}
/** 设置css变量
* @param var_name 变量名称
* @param var_value 变量值
**/
function var_set(var_name,var_value) {
// Set the value of variable --blue to another value (in this case "lightblue")
r.style.setProperty(var_name, var_value);
}
3.收起状态,鼠标移入后展开nav
- 通过类名 collapse,为 aside 添加 hover伪类,展开nav层,并控制sideBar位置
index.css
aside.collapse:hover nav{
width: var(--left-side-base-width);
background-color: var(--side-bg-color);
transition: all .3s;
z-index: 2;
visibility: visible;
}
aside.collapse:hover + .side-bar {
left: var(--left-side-base-width);
transition: all .3s;
}
3.1 “悬停”CSS伪状态冒泡DOM树。bug
- 实现 hover 展开菜单后,当鼠标放到 switchBar 上点击收起时,菜单确实改变宽度呈现收起状态,但是同时触发了 aside 的 hover 效果,nav层展开。
- 查阅后发现,如果悬停元素,则会自动悬停其所有祖先。
- 解决办法:将 sideBar 和 aside 设置成同级。
- 但是这样修改后又有了新的问题,hover展开菜单的情况下,不能点击 switchBar 了,只能在菜单收起的情况下点击 switchBar 。。。。TAT。
- 所以菜单收起时我把 switchBar 隐藏了
aside.collapse:hover + .side-bar .switch-bar {
opacity: 0;
}