这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战css
页面布局也是在实际开发中常常用到的技术。react
在 react 中实现,和经典实现其实没什么大的区别。浏览器
实现布局有这几种方式:markdown
antd
Grid
:24 栅格系统Layout
:页面级总体布局.app-layout1 {
width: 500px;
height: 400px;
position: relative;
text-align: center;
}
.app-layout1 .header {
line-height: 60px;
}
.app-layout1 .content {
position: absolute;
bottom: 60px;
top: 60px;
left: 0;
right: 0;
}
.app-layout1 .footer {
line-height: 60px;
bottom: 0;
left: 0;
right: 0;
position: absolute;
}
复制代码
使用 left: 150px,留出 Sider 的位置antd
.app-layout2 {
width: 500px;
height: 400px;
position: relative;
text-align: center;
}
.app-layout2 .header {
position: absolute;
left: 150px;
top: 0;
right: 0;
}
.app-layout2 .content {
position: absolute;
bottom: 60px;
top: 60px;
left: 150px;
right: 0;
}
.app-layout2 .footer {
bottom: 0;
left: 150px;
right: 0;
position: absolute;
}
.app-layout2 .sider {
width: 150px;
position: absolute;
top: 0;
left: 0;
bottom: 0;
}
复制代码
.layout {
position: relative;
width: 100%;
height: 400px;
}
.sider {
position: absolute;
top: 0;
left: 0;
bottom: 0;
background-color: #ddd;
}
.header {
background-color: #aaa;
height: 60px;
}
复制代码
经过状态 siderWidth
控制 layout
的 paddingLeft
app
import { useState } from 'react';
import './style.css';
export default function ResizeLayout() {
const [siderWidth, setSiderWidth] = useState(150);
const pxWidth = `${siderWidth}px`;
return (
<div className="layout" style={{ paddingLeft: pxWidth }}> <div className="sider" style={{ width: pxWidth }}> sider </div> <div className="header">header</div> <div className="content">content</div> </div>
);
}
复制代码
视觉上,咱们拖拽的是侧边栏 Sider 的右边框,其实并非。咱们会在右边框位置放置一个“隐身”的 bar -- sider-resizer
:ide
.sider-resizer {
position: absolute;
width: 6px;
top: 0;
bottom: 0;
cursor: col-resize;
}
复制代码
当鼠标在 sider-resizer
上,触发 onMouseDown
时,记录下鼠标的初始位置,同时标记 dragging
状态为 true
:布局
const handleMouseDown = (event) => {
setStartPageX(event.pageX);
setDragging(true);
};
复制代码
伴随着 dragging
状态的改变,咱们会为页面铺上一层遮罩 -- resize-mask
,以便后续 事件的监听:post
{
dragging && (
<div className="resize-mask" onMouseMove={handleMouseMove} onMouseUp={handleMouseUp} />
);
}
复制代码
.resize-mask {
background: rgba(0, 0, 0, 0);
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
cursor: col-resize;
}
复制代码
onMouseMove
的过程当中,实时更新 siderWidth
以及对 startPageX
的更新,就会产生拖拽的效果。ui
最终在 onMouseUp
时,结束拖拽状态。
const handleMouseMove = (event) => {
const currentSiderWidth = siderWidth + event.pageX - startPageX;
setSiderWidth(currentSiderWidth);
setStartPageX(event.pageX);
};
const handleMouseUp = () => {
setDragging(false);
};
复制代码
在拖拽结束时,保存 siderWidth
到 localStorage
;初始化 siderWidth
时,检查 localStorage
是否有值。
const [siderWidth, setSiderWidth] = useState(
parseInt(localStorage.getItem('siderWidth')) || 150,
);
const handleMouseUp = () => {
setDragging(false);
localStorage.setItem('siderWidth', siderWidth);
};
复制代码
.layout {
position: relative;
width: 100%;
height: 400px;
}
.sider {
position: absolute;
top: 0;
left: 0;
bottom: 0;
background-color: #ddd;
}
.header {
background-color: #aaa;
height: 60px;
}
.sider-resizer {
position: absolute;
width: 6px;
top: 0;
bottom: 0;
cursor: col-resize;
}
.resize-mask {
background: rgba(0, 0, 0, 0);
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
cursor: col-resize;
}
复制代码
import { useState } from 'react';
import './style.css';
export default function ResizeLayout() {
const [siderWidth, setSiderWidth] = useState(
parseInt(localStorage.getItem('siderWidth')) || 150,
);
const [dragging, setDragging] = useState(false);
const [startPageX, setStartPageX] = useState(0);
const pxWidth = `${siderWidth}px`;
const handleMouseDown = (event) => {
setStartPageX(event.pageX);
setDragging(true);
};
const handleMouseMove = (event) => {
const currentSiderWidth = siderWidth + event.pageX - startPageX;
setSiderWidth(currentSiderWidth);
setStartPageX(event.pageX);
};
const handleMouseUp = () => {
setDragging(false);
localStorage.setItem('siderWidth', siderWidth);
};
return (
<div className="layout" style={{ paddingLeft: pxWidth }}> <div className="sider" style={{ width: pxWidth }}> sider </div> <div className="header">header</div> <div className="content">content</div> <div className="sider-resizer" style={{ left: pxWidth }} onMouseDown={handleMouseDown} > {dragging && ( <div className="resize-mask" onMouseMove={handleMouseMove} onMouseUp={handleMouseUp} /> )} </div> </div>
);
}
复制代码