Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 如何在React中创建可调整大小的组件_Reactjs - Fatal编程技术网

Reactjs 如何在React中创建可调整大小的组件

Reactjs 如何在React中创建可调整大小的组件,reactjs,Reactjs,正如标题中所说。我想创建一个React组件,它可以通过拖动调整其宽度,就像windows操作系统中的windows一样。处理这个问题的最佳方法是什么 编辑 我将我目前对该问题的处理方法包括在内: 首先,我在容器的右上角放置了一个“dragger”元素。当我在该元素上按下鼠标时,我想创建一个mousemove事件监听器,该监听器将根据光标相对于容器边缘初始X位置的X坐标修改容器宽度。我已经让事件监听器在按下鼠标按钮后触发并记录坐标,但不幸的是,由于某种原因,在鼠标未按下(mouseUp事件)后,事

正如标题中所说。我想创建一个React组件,它可以通过拖动调整其宽度,就像windows操作系统中的windows一样。处理这个问题的最佳方法是什么

编辑
我将我目前对该问题的处理方法包括在内:

首先,我在容器的右上角放置了一个“dragger”元素。当我在该元素上按下鼠标时,我想创建一个mousemove事件监听器,该监听器将根据光标相对于容器边缘初始X位置的X坐标修改容器宽度。我已经让事件监听器在按下鼠标按钮后触发并记录坐标,但不幸的是,由于某种原因,在鼠标未按下(mouseUp事件)后,事件没有被删除,这不是我想要的。欢迎提出任何建议,以及关于我将来可能会遇到的与本主题相关的一些问题的建议。谢谢

type Props = MasterProps & LinkStateToProps & LinkDispatchToProps;
const Test3 = (Props: Props) => {

  const [containerWidth, setContainerWidth] = React.useState(640)
  const [isBeingStretched, setIsBeingStretched] = React.useState(false);
  const masterRef = React.useRef(null);


  const logMousePosition = React.useCallback((event:MouseEvent)=>{
    console.log(event.clientX);
  },[])


  const handleMouseDown=()=>{
    document.addEventListener('mousemove', logMousePosition);
    masterRef.current.addEventListener('mouseup', ()=>{
      document.removeEventListener('mouseup', logMousePosition)
    })
  }
  const handleMouseUp = () => { 
    document.removeEventListener('mousemove', logMousePosition);
  }
  return (
    <div className="master-wrapper" ref={masterRef}>
      <div className="stretchable-div" style={{ width: `${containerWidth}px` }}>
        <div className="dragger-wrapper">
          <h2>This is supposed to change width</h2>
          <div className="dragger"
            id="dragger"
            onMouseDown={handleMouseDown}
            onMouseUp={handleMouseUp}/>
        </div>
      </div>

    </div>
  );

}

export default connect(mapStateToProps, mapDispatchToProps)(Test3);
type Props=MasterProps&linkstatetrops&LinkDispatchToProps;
常量Test3=(道具:道具)=>{
常量[containerWidth,setContainerWidth]=React.useState(640)
常量[IsBeingStretch,SetIsBeingStretch]=React.useState(false);
const masterRef=React.useRef(null);
const logMousePosition=React.useCallback((事件:MouseEvent)=>{
console.log(event.clientX);
},[])
常量handleMouseDown=()=>{
文档。添加的事件列表器('mousemove',logMousePosition);
masterRef.current.addEventListener('mouseup',()=>{
document.removeEventListener('mouseup',logMousePosition)
})
}
const handleMouseUp=()=>{
document.removeEventListener('mousemove',logMousePosition);
}
返回(
这应该改变宽度
);
}
导出默认连接(mapStateToProps、mapDispatchToProps)(Test3);

我以前从未做过类似的事情,所以我决定试一试,结果是,通过React状态管理实现它非常简单。我可以理解,如果您是新手,您可能不知道从哪里开始反应,这没关系,但在我介绍解决方案之前,有两件事需要注意:

  • 诸如
    document.getElementById
    document.addEventListener
    之类的语句将不再按预期运行。使用React,您正在操作一个虚拟DOM,它会为您更新实际的DOM,您应该尽可能让它这样做
  • 使用
    refs
    来回避这个事实是不好的做法。它们的行为方式可能与上述声明类似,但这不是它们的预期用途。阅读关于
    ref
    的良好用例的说明
  • 下面是我演示的JSX部分的样子:

    return (
        <div className="container" onMouseMove={resizeFrame} onMouseUp={stopResize}>
          <div className="box" style={boxStyle}>
            <button className="dragger" onMouseDown={startResize}>
              Size Me
            </button>
          </div>
        </div>
      );
    
    我们将使用一些状态来跟踪正在进行的调整大小。我将所有内容压缩到一个对象中,以避免膨胀并使其更具可读性,尽管如果您有其他依赖于该状态的钩子,如
    useffect
    usemo
    ,这并不总是理想的。第一个事件只保存用户鼠标的初始x和y位置,并将active设置为true,以供下一个要引用的事件使用

    const [dims, setDims] = useState({
        w: 200,
        h: 200
    });
    
    const resizeFrame = e => {
        const { active, x, y } = drag;
        if (active) {
          const xDiff = Math.abs(x - e.clientX);
          const yDiff = Math.abs(y - e.clientY);
          const newW = x > e.clientX ? dims.w - xDiff : dims.w + xDiff;
          const newH = y > e.clientY ? dims.h + yDiff : dims.h - yDiff;
    
          setDrag({ ...drag, x: e.clientX, y: e.clientY });
          setDims({ w: newW, h: newH });
        }
    };
    
    第二个状态将初始化元素,然后在其值更改时更新元素的尺寸。这可以使用您想要的任何度量,尽管它必须与某些CSS属性相关

    resizeFrame
    功能执行以下操作:

  • 通过分解分配,使
    拖动的属性易于使用。这将使代码更可读,更容易键入
  • 检查调整大小功能是否处于活动状态
    onMouseMove
    将为鼠标在相关元素上移动的每个像素触发,因此我们希望确保它已正确调节
  • 使用
    Math.abs()
    将当前鼠标位置和保存的鼠标位置之间的差值作为正整数。这将使我们不必进行第二轮条件语句
  • 根据新鼠标位置在任一轴上大于还是小于上一个鼠标位置,使用turnary语句从尺寸中添加或减去差值
  • 使用扩展运算符
    将状态设置为新值,使
    拖动的不相关部分保持原样
  • 然后,一旦用户完成,我们只需将拖动状态的活动设置为false。JS样式的对象通过状态变量传递给元素,以便自动处理

    下面是完成效果的示例



    这样做的一个缺点是,基本上需要将
    mouseMove
    事件侦听器分配给最大的站点容器,因为在调整大小期间,鼠标不会停留在框的边界内。如果希望多个元素具有相同的功能,那么这可能是一个问题,尽管没有什么是好的状态管理无法解决的。您可以对此进行微调,使鼠标始终停留在拖动元素上,尽管这需要一个更复杂的实现。

    到目前为止您尝试了什么?一般的方法可能是:在
    mouseDown上获取用户的x和y屏幕坐标
    >获取
    mouseMove
    >的每一帧上的坐标之间的差值,将这些值转换成一些新的值
    width/height
    transform
    相关元素的样式。@JMadelaine我进行了编辑并包含了当前元素approach@LawrenceWitt这正是我之前的计划。我做了一个编辑,包括一些代码,我真的很感激一些建议这是一个伟大的回应,代码工作非常顺利!最后一个问题是,最终将不仅仅是
    const [dims, setDims] = useState({
        w: 200,
        h: 200
    });
    
    const resizeFrame = e => {
        const { active, x, y } = drag;
        if (active) {
          const xDiff = Math.abs(x - e.clientX);
          const yDiff = Math.abs(y - e.clientY);
          const newW = x > e.clientX ? dims.w - xDiff : dims.w + xDiff;
          const newH = y > e.clientY ? dims.h + yDiff : dims.h - yDiff;
    
          setDrag({ ...drag, x: e.clientX, y: e.clientY });
          setDims({ w: newW, h: newH });
        }
    };
    
    const stopResize = e => {
        setDrag({ ...drag, active: false });
    };
    
    const boxStyle = {
        width: `${dims.x}px`,
        height: `${dims.y}px`
    };