Javascript 尝试在React中创建可调整大小的列时遇到问题

Javascript 尝试在React中创建可调整大小的列时遇到问题,javascript,reactjs,web,frontend,responsive,Javascript,Reactjs,Web,Frontend,Responsive,我试图在react中创建可调整大小的列,我做得很好,我可以在只使用几列的情况下使其工作,但当我尝试嵌套它们时,情况开始变得很糟糕,例如,当我拖动列以调整其大小时,它无法正常工作,就像如果我移动得不太慢,它会停止听我的鼠标移动一样,而它不会发生在非嵌套列上。这听起来很离谱,但如果你看到代码,它会变得更清晰。我想不出这个问题:( 列文件 import React, { useState, useEffect } from 'react'; function Columns( props ) {

我试图在react中创建可调整大小的列,我做得很好,我可以在只使用几列的情况下使其工作,但当我尝试嵌套它们时,情况开始变得很糟糕,例如,当我拖动列以调整其大小时,它无法正常工作,就像如果我移动得不太慢,它会停止听我的鼠标移动一样,而它不会发生在非嵌套列上。这听起来很离谱,但如果你看到代码,它会变得更清晰。我想不出这个问题:(

列文件

import React, { useState, useEffect } from 'react';

function Columns( props ) {
  const [ isResizing, setIsResizing ] = useState( false );
  const [ target, setTarget ] = useState();
  const [ parentClientRect, setParentClientRect ] = useState();
  const [ columnsPercentages, setColumnsPercentages ] = useState([{}]);
  const count = props.children.length;
  const minWidth = 5;

  useEffect(()=>{
    const initialColumnPercentage = 100 / count;
    const initialColumnsPercentageArray = [];
    for( let i = 0; i < count; i++ ){
      initialColumnsPercentageArray.push( initialColumnPercentage );
    }
    setColumnsPercentages([...initialColumnsPercentageArray]);
  },[]);// eslint-disable-line react-hooks/exhaustive-deps

  const handleMouseMove = ( e ) =>{
    if ( !isResizing ) return;
    console.log( target );
    let newPerc = ((( e.pageX - parentClientRect.x ) * 100 ) / parentClientRect.width ) + 1;
    if ( target !== 0 ){
      let percentageToSubtract = 0;
      for( let i = 0; i < target; i++ ){
        percentageToSubtract = percentageToSubtract + columnsPercentages[i];
      }
      newPerc = newPerc - percentageToSubtract;
    }
    if ( newPerc > 100 - ( count - 1 ) * minWidth ){
      newPerc = 100 - ( count - 1 ) * minWidth;
    }
    let newPercentagesArray = columnsPercentages;
    newPercentagesArray.splice( target, 1, newPerc );
    let totalPercentage = newPercentagesArray.reduce(( a, b ) => a + b );
    if ( totalPercentage !== 100 ){
      let nextColumnPerc = 100 - newPercentagesArray[target] - ( totalPercentage - ( newPercentagesArray[target] + newPercentagesArray[target + 1]));
      if ( nextColumnPerc < minWidth ){
        nextColumnPerc = minWidth;
      }
      newPercentagesArray.splice( target + 1, 1, nextColumnPerc );
    }
    setColumnsPercentages([...newPercentagesArray]);
  };

  const handleMouseUp = ( e ) =>{
    setIsResizing( false );
    setTarget( null );
    setParentClientRect( null );
  };

  const handleMouseDown = ( e, key ) =>{
    e.stopPropagation();
    setTarget( key );
    setParentClientRect( e.target.parentElement.getBoundingClientRect());
    setIsResizing( true );
  };

  return (
    <main className="columns" onMouseMove={handleMouseMove} onMouseUp={handleMouseUp} >
      {
        React.Children.map( props.children, (( x, index )=> React.cloneElement( x, {
          key: index,
          onMouseDown: ( e ) => handleMouseDown( e, index ),
          initialWidth: 100 / count,
          maxWidth: 100 - ( count - 1 ) * minWidth,
          columnsPercentages,
          index
        })))
      }
    </main>
  );
}

export default Columns;
import React, { useState, useEffect } from 'react';

function Column( props ) {
  const { index, className = '', maxWidth, minWidth = '5%', initialWidth, columnsPercentages, onMouseDown } = props;
  const [ width, setWidth ] = useState( initialWidth );

  useEffect(()=>{
    console.log( columnsPercentages );
    if ( columnsPercentages[index] != null ){
      if ( columnsPercentages[index] !== width ){
        setWidth( columnsPercentages[index]);
      }
    }
  },[columnsPercentages]);// eslint-disable-line react-hooks/exhaustive-deps

  return (
    <section className={`column ${className}`} style={{ maxWidth:`${maxWidth}%`, minWidth, width:`${width}%` }}
      onMouseDown={onMouseDown} >
      {props.children}
    </section>
  );
}

export default Column;
import React,{useState,useffect}来自“React”;
功能栏(道具){
const[IsResising,setIsResising]=useState(false);
const[target,setTarget]=useState();
const[parentClientRect,setParentClientRect]=useState();
const[columnsPercentages,setColumnsPercentages]=useState([{}]);
const count=props.children.length;
常数最小宽度=5;
useffect(()=>{
常量initialColumnPercentage=100/计数;
const initialColumnsPercentageArray=[];
for(设i=0;i{
如果(!IsResising)返回;
控制台日志(目标);
设newPerc=((e.pageX-parentClientRect.x)*100)/parentClientRect.width)+1;
如果(目标!==0){
设percentageToSubtract=0;
for(设i=0;i100-(计数-1)*最小宽度){
newPerc=100-(计数-1)*最小宽度;
}
让newPercentagesArray=columnsPercentages;
newPercentagesArray.拼接(目标,1,newPerc);
让totalPercentage=newPercentagesArray.reduce((a,b)=>a+b);
如果(总百分比!==100){
设nextColumnPerc=100-newPercentagesArray[target](totalPercentage-(newPercentagesArray[target]+newPercentagesArray[target+1]);
if(nextColumnPerc<最小宽度){
nextColumnPerc=最小宽度;
}
newPercentagesArray.splice(目标+1,1,下一列PERC);
}
setColumnsPercentages([…newPercentagesArray]);
};
常数handleMouseUp=(e)=>{
SetIsResising(假);
setTarget(空);
setParentClientRect(空);
};
常量handleMouseDown=(e,键)=>{
e、 停止传播();
设置目标(键);
setParentClientRect(e.target.parentElement.getBoundingClientRect());
SetIsResising(真);
};
返回(
{
React.Children.map(props.Children,((x,index)=>React.cloneElement(x{
关键词:索引,,
onMouseDown:(e)=>handleMouseDown(e,索引),
初始宽度:100/计数,
最大宽度:100-(计数-1)*最小宽度,
柱状结构,
指数
})))
}
);
}
导出默认列;
列文件

import React, { useState, useEffect } from 'react';

function Columns( props ) {
  const [ isResizing, setIsResizing ] = useState( false );
  const [ target, setTarget ] = useState();
  const [ parentClientRect, setParentClientRect ] = useState();
  const [ columnsPercentages, setColumnsPercentages ] = useState([{}]);
  const count = props.children.length;
  const minWidth = 5;

  useEffect(()=>{
    const initialColumnPercentage = 100 / count;
    const initialColumnsPercentageArray = [];
    for( let i = 0; i < count; i++ ){
      initialColumnsPercentageArray.push( initialColumnPercentage );
    }
    setColumnsPercentages([...initialColumnsPercentageArray]);
  },[]);// eslint-disable-line react-hooks/exhaustive-deps

  const handleMouseMove = ( e ) =>{
    if ( !isResizing ) return;
    console.log( target );
    let newPerc = ((( e.pageX - parentClientRect.x ) * 100 ) / parentClientRect.width ) + 1;
    if ( target !== 0 ){
      let percentageToSubtract = 0;
      for( let i = 0; i < target; i++ ){
        percentageToSubtract = percentageToSubtract + columnsPercentages[i];
      }
      newPerc = newPerc - percentageToSubtract;
    }
    if ( newPerc > 100 - ( count - 1 ) * minWidth ){
      newPerc = 100 - ( count - 1 ) * minWidth;
    }
    let newPercentagesArray = columnsPercentages;
    newPercentagesArray.splice( target, 1, newPerc );
    let totalPercentage = newPercentagesArray.reduce(( a, b ) => a + b );
    if ( totalPercentage !== 100 ){
      let nextColumnPerc = 100 - newPercentagesArray[target] - ( totalPercentage - ( newPercentagesArray[target] + newPercentagesArray[target + 1]));
      if ( nextColumnPerc < minWidth ){
        nextColumnPerc = minWidth;
      }
      newPercentagesArray.splice( target + 1, 1, nextColumnPerc );
    }
    setColumnsPercentages([...newPercentagesArray]);
  };

  const handleMouseUp = ( e ) =>{
    setIsResizing( false );
    setTarget( null );
    setParentClientRect( null );
  };

  const handleMouseDown = ( e, key ) =>{
    e.stopPropagation();
    setTarget( key );
    setParentClientRect( e.target.parentElement.getBoundingClientRect());
    setIsResizing( true );
  };

  return (
    <main className="columns" onMouseMove={handleMouseMove} onMouseUp={handleMouseUp} >
      {
        React.Children.map( props.children, (( x, index )=> React.cloneElement( x, {
          key: index,
          onMouseDown: ( e ) => handleMouseDown( e, index ),
          initialWidth: 100 / count,
          maxWidth: 100 - ( count - 1 ) * minWidth,
          columnsPercentages,
          index
        })))
      }
    </main>
  );
}

export default Columns;
import React, { useState, useEffect } from 'react';

function Column( props ) {
  const { index, className = '', maxWidth, minWidth = '5%', initialWidth, columnsPercentages, onMouseDown } = props;
  const [ width, setWidth ] = useState( initialWidth );

  useEffect(()=>{
    console.log( columnsPercentages );
    if ( columnsPercentages[index] != null ){
      if ( columnsPercentages[index] !== width ){
        setWidth( columnsPercentages[index]);
      }
    }
  },[columnsPercentages]);// eslint-disable-line react-hooks/exhaustive-deps

  return (
    <section className={`column ${className}`} style={{ maxWidth:`${maxWidth}%`, minWidth, width:`${width}%` }}
      onMouseDown={onMouseDown} >
      {props.children}
    </section>
  );
}

export default Column;
import React,{useState,useffect}来自“React”;
功能栏(道具){
const{index,className='',maxWidth,minWidth='5%',initialWidth,columnsPercentages,onMouseDown}=props;
const[width,setWidth]=useState(initialWidth);
useffect(()=>{
console.log(columnsPercentages);
if(columnsPercentages[index]!=null){
if(columnsPercentages[索引]!==宽度){
setWidth(columnsPercentages[索引]);
}
}
},[columnsPercentages];//eslint禁用行反应挂钩/穷举deps
返回(
{props.children}
);
}
导出默认列;
实施

import React, { useState } from 'react';
import Columns from '../common/Columns.jsx';
import Column from '../common/Column.jsx';

function ImplementationColumns( props ){
  return (
    <>
      <Columns>
        <Column>
          <p style={{ textAlign: 'center', lineHeight: '100px' }}>section 1</p>
          <Columns>
            <Column>
              <p style={{ textAlign: 'center', lineHeight: '100px' }}>nested 1</p>
            </Column>
            <Column>
              <p style={{ textAlign: 'center', lineHeight: '100px' }}>nested 2</p>
            </Column>
            <Column>
              <p style={{ textAlign: 'center', lineHeight: '100px' }}>nested 3</p>
            </Column>
          </Columns>
        </Column>
        <Column>
          <p style={{ textAlign: 'center', lineHeight: '100px' }}>section 2</p>
        </Column>
      </Columns>
    </>
  );
}

export default ImplementationColumns;
import React,{useState}来自“React”;
从“../common/Columns.jsx”导入列;
从“../common/Column.jsx”导入列;
功能实现列(道具){
返回(

第1节

嵌套1

nested 2

嵌套3

第2节

); } 导出默认实现列;