我希望通过可拖动的手柄将材料ui抽屉的宽度调整大小。 我目前的方法是在整个应用程序上有一个mousevent监听器,它检查是否按下了句柄,并根据每次鼠标移动时的鼠标位置更新宽度。
然而,这需要在整个应用程序上使用一个持续的mouseevent监听器,这对于简单的调整大小功能来说似乎有些过分。
是否有更好/推荐的方法来调整大小?
答案 0 :(得分:6)
您可以在其上使用带有mousedown
的指标展示器。
这里例如
// styles
dragger: {
width: '5px',
cursor: 'ew-resize',
padding: '4px 0 0',
borderTop: '1px solid #ddd',
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
zIndex: '100',
backgroundColor: '#f4f7f9'
}
...
state = {
isResizing: false,
lastDownX: 0,
newWidth: {}
};
handleMousedown = e => {
this.setState({ isResizing: true, lastDownX: e.clientX });
};
handleMousemove = e => {
// we don't want to do anything if we aren't resizing.
if (!this.state.isResizing) {
return;
}
let offsetRight =
document.body.offsetWidth - (e.clientX - document.body.offsetLeft);
let minWidth = 50;
let maxWidth = 600;
if (offsetRight > minWidth && offsetRight < maxWidth) {
this.setState({ newWidth: { width: offsetRight } });
}
};
handleMouseup = e => {
this.setState({ isResizing: false });
};
componentDidMount() {
document.addEventListener('mousemove', e => this.handleMousemove(e));
document.addEventListener('mouseup', e => this.handleMouseup(e));
}
...
<Drawer
variant="permanent"
open
anchor={'right'}
classes={{
paper: classes.drawerPaper
}}
PaperProps={{ style: this.state.newWidth }}
>
<div
id="dragger"
onMouseDown={event => {
this.handleMousedown(event);
}}
className={classes.dragger}
/>
{drawer}
</Drawer>
这个想法是,当点击拖动器时,它会在鼠标移动后调整宽度Drawer
。
播放DEMO。
答案 1 :(得分:2)
只需在handle元素上使用synthetic event即可。这样,您可以避免拥有通用事件侦听器的混乱/性能成本。如下所示:
render() {
return (
<div onMouseDown={this.yourResizeFunc}>
</div>
);
}
答案 2 :(得分:1)
我想使用React Hooks添加最新的答案。
您可以这样操作,然后:
CSS:
sidebar-dragger: {
width: '5px',
cursor: 'ew-resize',
padding: '4px 0 0',
borderTop: '1px solid #ddd',
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
zIndex: '100',
backgroundColor: '#f4f7f9'
}
反应(使用带有引用和状态的钩子)
let isResizing = null;
function ResizeableSidebar (props) {
const sidebarPanel = React.useRef('sidebarPanel');
const cbHandleMouseMove = React.useCallback(handleMousemove, []);
const cbHandleMouseUp = React.useCallback(handleMouseup, []);
function handleMousedown (e) {
e.stopPropagation();
e.preventDefault();
// we will only add listeners when needed, and remove them afterward
document.addEventListener('mousemove', cbHandleMouseMove);
document.addEventListener('mouseup', cbHandleMouseUp);
isResizing = true;
};
function handleMousemove (e) {
if (!isResizing) {
return;
}
let offsetRight =
document.body.offsetWidth - (e.clientX - document.body.offsetLeft);
let minWidth = 50;
if (offsetRight > minWidth) {
let curSize = offsetRight - 60;
// using a ref instead of state will be way faster
sidebarPanel.current.style.width = curSize + 'px';
}
};
function handleMouseup (e) {
if (!isResizing) {
return;
}
isResizing = false;
document.removeEventListener('mousemove', cbHandleMouseMove);
document.removeEventListener('mouseup', cbHandleMouseUp);
};
return <div className="sidebar-container">
<div
className="sidebar-dragger"
onMouseDown={handleMousedown}
/>
<div>
Your stuff goes here
</div>
</div>;
}
答案 3 :(得分:0)
它可能是一个带有 API 的 useResize
钩子,用于启用调整大小和提供当前宽度。
import { useCallback, useEffect, useState } from 'react'
type UseResizeProps = {
minWidth: number
}
type UseResizeReturn = {
width: number
enableResize: () => void
}
const useResize = ({
minWidth,
}: UseResizeProps): UseResizeReturn => {
const [isResizing, setIsResizing] = useState(false)
const [width, setWidth] = useState(minWidth)
const enableResize = useCallback(() => {
setIsResizing(true)
}, [setIsResizing])
const disableResize = useCallback(() => {
setIsResizing(false)
}, [setIsResizing])
const resize = useCallback(
(e: MouseEvent) => {
if (isResizing) {
const newWidth = e.clientX // You may want to add some offset here from props
if (newWidth >= minWidth) {
setWidth(newWidth)
}
}
},
[minWidth, isResizing, setWidth],
)
useEffect(() => {
document.addEventListener('mousemove', resize)
document.addEventListener('mouseup', disableResize)
return () => {
document.removeEventListener('mousemove', resize)
document.removeEventListener('mouseup', disableResize)
}
}, [disableResize, resize])
return { width, enableResize }
}
export default useResize
然后你可以像这样从你的布局组件中分离调整大小的逻辑:
const Layout = () => {
const { width, enableResize } = useResize(200);
return (
<Drawer
variant="permanent"
open
PaperProps={{ style: { width } }}
>
{drawer}
<div
style={{
position: absolute,
width: '2px',
top: '0',
right: '-1px',
bottom: '0',
cursor: 'col-resize'
}}
onMouseDown={enableResize}
/>
</Drawer>
)
答案 4 :(得分:-1)
如果符合您的需要,您只能使用css。这是最简单的解决方案。看妈妈,没有javascript。
.resizable {
height: 150px;
width: 150px;
border: 1px solid #333;
resize: horizontal;
overflow: auto;
}
&#13;
<div class="resizable"></div>
&#13;