使用.map()和内联事件处理程序调整组件大小



我正在尝试使用下面的示例(第一个代码片段(来实现数据呈现的可调整大小的组件。我试着用useRef编写它,但这需要在一个循环中放入一个钩子,这与React的文档相反。

这是包含所需功能的代码段。

const App = () => {
const ref = React.useRef(null);
const refRight = React.useRef(null);
React.useEffect(() => {
const resizeableEle = ref.current;
const styles = window.getComputedStyle(resizeableEle);
let width = parseInt(styles.width, 10);
let x = 0;
resizeableEle.style.top = '20px';
resizeableEle.style.left = '20px';
// Right resize
const onMouseMoveRightResize = (event) => {
const dx = event.clientX - x;
x = event.clientX;
width = width + dx;
resizeableEle.style.width = `${width}px`;
};
const onMouseUpRightResize = () => {
document.removeEventListener('mousemove', onMouseMoveRightResize);
};
const onMouseDownRightResize = (event) => {
x = event.clientX;
resizeableEle.style.left = styles.left;
resizeableEle.style.right = null;
document.addEventListener('mousemove', onMouseMoveRightResize);
document.addEventListener('mouseup', onMouseUpRightResize);
};
// Add mouse down event listener
const resizerRight = refRight.current;
resizerRight.addEventListener('mousedown', onMouseDownRightResize);
return () => {
resizerRight.removeEventListener('mousedown', onMouseDownRightResize);
};
}, []);
return (
<div className="container">
<div ref={ref} className="resizeable">
<p>Hello this is text</p>
<div ref={refRight} className="resizer resizer-r"></div>
</div>
</div>
);
};
ReactDOM.render(
<App />,
document.getElementById("root")
);
.container {
border-radius: 5px;
width: 100vw;
height: 100vh;
background: #FFBC97;
position: relative;
}
.resizeable {
position: absolute;
top: 20px;
left: 150px;
border: 2px solid #533535;
width: 100px;
height: 100px;
border-radius: 3px;
display:block;
/* justify-content: center; */
align-items: center;
min-width: 15px;
min-height: 15px;
text-overflow: ellipsis !important;
white-space: nowrap !important;
overflow: hidden !important;
}
.resizer {
position: absolute;
background: black;
}
.resizer-r {
cursor: col-resize;
height: 100%;
right: 0;
top: 0;
width: 2px;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>

基本上,我试图重现相同的调整大小功能,但我不想使用useRef,而是想像<div onMouseMove={handleMouseMove}>一样内联定义事件侦听器。主要是因为在React中,在循环中使用钩子不是一个好的做法。

我希望它看起来有点像下面的第二个剪辑,这是正确的方法吗?

const App = () => {
const data = ['item1', 'item2', 'item3', 'item4', 'item5'];
return (
<div className="App">
{data.map((x, i) => {
function handleMouseDown(e) {
console.log('trying to resize');
}
function handleMouseUp() {
console.log('handling mouseUp');
}
const onMouseMoveRightResize = (e) => {
console.log('moving...');
};
return (
<div className="item" key={data[i]}>
{x}
<div key={`i${i}`} className="resizer" onMouseMove={onMouseMoveRightResize} onMouseDown={handleMouseDown} onMouseUp={handleMouseUp}></div>
</div>
);
})}
</div>
);
};
ReactDOM.render(
<App />,
document.getElementById("root")
);
.App {
text-align: center;
}
.item{
position: relative;
border: 1px solid black;
width: 300px;
margin: 10px auto;
border-radius: 3px;
cursor: pointer;
}
.resizer {
position: absolute;
background: black;
cursor: col-resize;
height: 100%;
right: 0;
top: 0;
width: 5px;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

我试着复制了很多次。我设法改变了组件的宽度,但在实现平滑调整大小功能方面一直失败。有人能帮我吗?

因此,为了确保我们正确回答了这个问题,首先,如果您的意图是多次渲染同一个可调整大小的组件,您可以将该逻辑移动到另一个组件并重新渲染,如此代码沙盒中所示。

如果你想为每个项目做一些自定义的事情,对于这3个函数,函数handleMouseDown、handleMouseUp和onMouseMoveRightResize,那么我们可以将这些函数传递给孩子,并期望孩子传递所需的道具并处理更改-此外,从索引中我们知道哪个项目被点击、调整大小和释放。Codesandbox链接(打开控制台,日志应该会显示出来(。

因此,它的要点是,您可以创建另一个组件,该组件可以在映射函数中呈现,从而避免在映射函数中将不直接使用钩子的要求。

App.js

import "./styles.css";
import ResizableComponent from "./ResizableComponent";
const App = () => {
const data = ["item1", "item2", "item3", "item4", "item5"];
return (
<div className="container">
{data.map((x, index) => (
<ResizableComponent index={index} key={x} />
))}
</div>
);
};
export default App;

ResizableComponent.js

import { useEffect, useRef } from "react";
const ResizableComponent = ({
index,
handleMouseDown,
handleMouseUp,
handleMouseMoveRightResize
}) => {
const ref = useRef(null);
const refRight = useRef(null);
useEffect(() => {
const resizeableEle = ref.current;
const resizerRight = refRight.current;
if (resizeableEle && resizerRight) {
const styles = window.getComputedStyle(resizeableEle);
// let width = parseInt(styles.width, 10);
// let x = 0;
resizeableEle.style.top = `${index * 120 + 20}px`;
resizeableEle.style.left = "20px";
// Right resize
const onMouseMoveRightResize = (event) => {
// const dx = event.clientX - x;
// x = event.clientX;
// width = width + dx;
// resizeableEle.style.width = `${width}px`;
handleMouseMoveRightResize();
// pass whatever props you want to the parent component
};
const onMouseUpRightResize = () => {
handleMouseUp();
document.removeEventListener("mousemove", onMouseMoveRightResize);
};
const onMouseDownRightResize = (event) => {
handleMouseDown();
// pass wahtever props you want to the parent component
// x = event.clientX;
// resizeableEle.style.left = styles.left;
// resizeableEle.style.right = '';
document.addEventListener("mousemove", onMouseMoveRightResize);
document.addEventListener("mouseup", onMouseUpRightResize);
};
resizerRight.addEventListener("mousedown", onMouseDownRightResize);
return () => {
if (resizerRight)
resizerRight.removeEventListener("mousedown", onMouseDownRightResize);
};
}
}, [handleMouseDown, handleMouseMoveRightResize, handleMouseUp, index]);
return (
<div ref={ref} className="resizeable">
<p>Hello this is text</p>
<div ref={refRight} className="resizer resizer-r"></div>
</div>
);
};
export default ResizableComponent;

此外,通过取消注释第二个解决方案中的代码,您可以拥有默认的调整大小功能,并在handleMouseDown、handleMouseUp和handleMouseMoveRightResize函数中执行其他操作。

如果有更可行的解决方案,我会努力找到,但我认为这应该做到

相关内容

  • 没有找到相关文章

最新更新