Flex子项会以很小的宽度消失

时间:2019-04-23 23:11:40

标签: javascript html css reactjs flexbox

我正在使用ReactJS构建一个调整大小的组件。下面的代码:

class Cell extends React.Component {
  handleMouseDown = event => {
    this.props.onMouseDown(this.props.index, event);
  };

  render() {
    let verticalGrip = ( <
      div onMouseDown = {
        this.handleMouseDown
      }
      className = "cell-vertical-grip" / >
    );

    return ( <
      div className = "cell-container"
      style = {
        {
          width: this.props.widths[this.props.index]
        }
      } >
      <
      div className = "cell-content"
      style = {
        {
          border: "10px solid transparent"
        }
      } >
      {
        "WIDTH " + this.props.widths[this.props.index]
      } <
      /div> {
        verticalGrip
      } <
      /div>
    );
  }
}

class Test extends React.Component {
  state = {
    widths: [100, 100, 100, 100],
    baseWidths: [100, 100, 100, 100],
    xBase: 0,
    resizeIndex: null
  };

  handleMouseDown = (index, event) => {
    console.log("MouseDown: index: " + index + ", pageX: " + event.pageX);

    this.setState({
      xBase: event.pageX,
      resizing: true,
      resizeIndex: index
    });
  };

  handleMouseMove = event => {
    if (this.state.resizing) {

      let delta = this.state.xBase - event.pageX;

      console.log("MouseMove " + delta);

      let widths = this.state.widths.slice();
      widths[this.state.resizeIndex] = this.state.baseWidths[this.state.resizeIndex] - delta;

      this.setState({
        widths: widths
      });
    }
  };

  handleMouseUp = event => {
    console.log("MouseUp");

    this.setState({
      resizing: false,
      resizeIndex: null
    });
  };

  render() {
    return ( <
      div className = "test-container"
      onMouseMove = {
        this.handleMouseMove
      }
      onMouseUp = {
        this.handleMouseUp
      } >
      <
      Cell widths = {
        this.state.widths
      }
      onMouseDown = {
        this.handleMouseDown
      }
      index = {
        0
      }
      /> <
      Cell widths = {
        this.state.widths
      }
      onMouseDown = {
        this.handleMouseDown
      }
      index = {
        1
      }
      /> <
      Cell widths = {
        this.state.widths
      }
      onMouseDown = {
        this.handleMouseDown
      }
      index = {
        2
      }
      /> <
      Cell widths = {
        this.state.widths
      }
      onMouseDown = {
        this.handleMouseDown
      }
      index = {
        3
      }
      /> <
      /div>
    );
  }
}

// Render it
ReactDOM.render( <
  Test / > ,
  document.body
);
.test-container {
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: row;
  background-color: cyan;
}

.cell-container {
  width: 100%;
  height: 100px;
  display: flex;
  flex-direction: row;
  background-color: grey;
  border: 1px solid black;
  overflow-y: hidden;
  overflow-x: hidden;
}

.cell-content {
  align-self: center;
  flex-shrink: 1;
  font-size: 12px;
  overflow-y: hidden;
  overflow-x: hidden;
  background-color: white;
}

.cell-vertical-grip {
  flex-shrink: 0;
  margin-left: auto;
  width: 3px;
  min-width: 3px;
  cursor: ew-resize;
  background-color: blue;
}
<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>

verticalGrip中,您可以抓住要调整大小的列。

很好,但是当我将任何列的大小调整为小于20px的宽度时,我的问题就会出现。在这种情况下,我的蓝色握把(verticalGrip项目)就消失了。因此,如果我将鼠标释放到该位置,则由于无法抓握(它消失了),因此无法再次扩展该列。

换句话说,如果他由于某种原因需要收缩色谱柱,由于没有抓地力,他不能再扩大它。

如何在所有可能的宽度上保持可见,使用户可以在任何情况下调整列的大小?

2 个答案:

答案 0 :(得分:1)

一个想法是使元素在右侧保持粘性,并且由于要应用到元素的边框而导致溢出时,元素不会消失。

class Cell extends React.Component {
  handleMouseDown = event => {
    this.props.onMouseDown(this.props.index, event);
  };

  render() {
    let verticalGrip = ( <
      div onMouseDown = {
        this.handleMouseDown
      }
      className = "cell-vertical-grip" / >
    );

    return ( <
      div className = "cell-container"
      style = {
        {
          width: this.props.widths[this.props.index]
        }
      } >
      <
      div className = "cell-content"
      style = {
        {
          border: "10px solid transparent"
        }
      } >
      {
        "WIDTH " + this.props.widths[this.props.index]
      } <
      /div> {
        verticalGrip
      } <
      /div>
    );
  }
}

class Test extends React.Component {
  state = {
    widths: [100, 100, 100, 100],
    baseWidths: [100, 100, 100, 100],
    xBase: 0,
    resizeIndex: null
  };

  handleMouseDown = (index, event) => {
    console.log("MouseDown: index: " + index + ", pageX: " + event.pageX);

    this.setState({
      xBase: event.pageX,
      resizing: true,
      resizeIndex: index
    });
  };

  handleMouseMove = event => {
    if (this.state.resizing) {

      let delta = this.state.xBase - event.pageX;

      console.log("MouseMove " + delta);

      let widths = this.state.widths.slice();
      widths[this.state.resizeIndex] = this.state.baseWidths[this.state.resizeIndex] - delta;

      this.setState({
        widths: widths
      });
    }
  };

  handleMouseUp = event => {
    console.log("MouseUp");

    this.setState({
      resizing: false,
      resizeIndex: null
    });
  };

  render() {
    return ( <
      div className = "test-container"
      onMouseMove = {
        this.handleMouseMove
      }
      onMouseUp = {
        this.handleMouseUp
      } >
      <
      Cell widths = {
        this.state.widths
      }
      onMouseDown = {
        this.handleMouseDown
      }
      index = {
        0
      }
      /> <
      Cell widths = {
        this.state.widths
      }
      onMouseDown = {
        this.handleMouseDown
      }
      index = {
        1
      }
      /> <
      Cell widths = {
        this.state.widths
      }
      onMouseDown = {
        this.handleMouseDown
      }
      index = {
        2
      }
      /> <
      Cell widths = {
        this.state.widths
      }
      onMouseDown = {
        this.handleMouseDown
      }
      index = {
        3
      }
      /> <
      /div>
    );
  }
}

// Render it
ReactDOM.render( <
  Test / > ,
  document.body
);
.test-container {
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: row;
  background-color: cyan;
}

.cell-container {
  width: 100%;
  height: 100px;
  display: flex;
  flex-direction: row;
  background-color: grey;
  border: 1px solid black;
  overflow-y: hidden;
  overflow-x: hidden;
}

.cell-content {
  align-self: center;
  flex-shrink: 1;
  font-size: 12px;
  overflow-y: hidden;
  overflow-x: hidden;
  background-color: white;
}

.cell-vertical-grip {
  flex-shrink: 0;
  margin-left: auto;
  width: 3px;
  min-width: 3px;
  cursor: ew-resize;
  background-color: blue;
  
  position:sticky;
  right:0;
}
<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>

或者您可以考虑另一个想法,而不是轮廓或框阴影之类的边框,这不会影响元素的宽度,并且您将获得相同的视觉输出:

class Cell extends React.Component {
  handleMouseDown = event => {
    this.props.onMouseDown(this.props.index, event);
  };

  render() {
    let verticalGrip = ( <
      div onMouseDown = {
        this.handleMouseDown
      }
      className = "cell-vertical-grip" / >
    );

    return ( <
      div className = "cell-container"
      style = {
        {
          width: this.props.widths[this.props.index]
        }
      } >
      <
      div className = "cell-content"
      style = {
        {
          outline: "10px solid #fff"
        }
      } >
      {
        "WIDTH " + this.props.widths[this.props.index]
      } <
      /div> {
        verticalGrip
      } <
      /div>
    );
  }
}

class Test extends React.Component {
  state = {
    widths: [100, 100, 100, 100],
    baseWidths: [100, 100, 100, 100],
    xBase: 0,
    resizeIndex: null
  };

  handleMouseDown = (index, event) => {
    console.log("MouseDown: index: " + index + ", pageX: " + event.pageX);

    this.setState({
      xBase: event.pageX,
      resizing: true,
      resizeIndex: index
    });
  };

  handleMouseMove = event => {
    if (this.state.resizing) {

      let delta = this.state.xBase - event.pageX;

      console.log("MouseMove " + delta);

      let widths = this.state.widths.slice();
      widths[this.state.resizeIndex] = this.state.baseWidths[this.state.resizeIndex] - delta;

      this.setState({
        widths: widths
      });
    }
  };

  handleMouseUp = event => {
    console.log("MouseUp");

    this.setState({
      resizing: false,
      resizeIndex: null
    });
  };

  render() {
    return ( <
      div className = "test-container"
      onMouseMove = {
        this.handleMouseMove
      }
      onMouseUp = {
        this.handleMouseUp
      } >
      <
      Cell widths = {
        this.state.widths
      }
      onMouseDown = {
        this.handleMouseDown
      }
      index = {
        0
      }
      /> <
      Cell widths = {
        this.state.widths
      }
      onMouseDown = {
        this.handleMouseDown
      }
      index = {
        1
      }
      /> <
      Cell widths = {
        this.state.widths
      }
      onMouseDown = {
        this.handleMouseDown
      }
      index = {
        2
      }
      /> <
      Cell widths = {
        this.state.widths
      }
      onMouseDown = {
        this.handleMouseDown
      }
      index = {
        3
      }
      /> <
      /div>
    );
  }
}

// Render it
ReactDOM.render( <
  Test / > ,
  document.body
);
.test-container {
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: row;
  background-color: cyan;
}

.cell-container {
  width: 100%;
  height: 100px;
  display: flex;
  flex-direction: row;
  background-color: grey;
  border: 1px solid black;
  overflow-y: hidden;
  overflow-x: hidden;
}
/*to push the element so we can see the outline*/
.cell-container:before {
  content:"";
  width:10px;
}

.cell-content {
  align-self: center;
  flex-shrink: 1;
  font-size: 12px;
  overflow-y: hidden;
  overflow-x: hidden;
  background-color: white;
}

.cell-vertical-grip {
  flex-shrink: 0;
  margin-left: auto;
  width: 3px;
  min-width: 3px;
  cursor: ew-resize;
  background-color: blue;
}
<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>

答案 1 :(得分:0)

一个简单的解决方案可能是对CSS进行一些修改,以使您的抓手元素放置在absolute上,并与父.cell-container的右边缘和高度对齐并设置大小:

.cell-vertical-grip {
  /* Add this */
  position:absolute;
  top:0;
  height:100%;
  right:0;
}

您还应该显式设置min-width中的.cell-container以匹配抓取器宽度,以便在容器完全折叠时仍可见:

.cell-container {
  /* Add this */
  min-width:3px;
  position:relative;
}

我已使用以下代码段中的这些更改更新了您的代码:

class Cell extends React.Component {
  handleMouseDown = event => {
    this.props.onMouseDown(this.props.index, event);
  };

  render() {
    let verticalGrip = ( <
      div onMouseDown = {
        this.handleMouseDown
      }
      className = "cell-vertical-grip" / >
    );

    return ( <
      div className = "cell-container"
      style = {
        {
          width: this.props.widths[this.props.index]
        }
      } >
      <
      div className = "cell-content"
      style = {
        {
          border: "10px solid transparent"
        }
      } >
      {
        "WIDTH " + this.props.widths[this.props.index]
      } <
      /div> {
        verticalGrip
      } <
      /div>
    );
  }
}

class Test extends React.Component {
  state = {
    widths: [100, 100, 100, 100],
    baseWidths: [100, 100, 100, 100],
    xBase: 0,
    resizeIndex: null
  };

  handleMouseDown = (index, event) => {
    console.log("MouseDown: index: " + index + ", pageX: " + event.pageX);

    this.setState({
      xBase: event.pageX,
      resizing: true,
      resizeIndex: index
    });
  };

  handleMouseMove = event => {
    if (this.state.resizing) {

      let delta = this.state.xBase - event.pageX;

      console.log("MouseMove " + delta);

      let widths = this.state.widths.slice();
      widths[this.state.resizeIndex] = this.state.baseWidths[this.state.resizeIndex] - delta;

      this.setState({
        widths: widths
      });
    }
  };

  handleMouseUp = event => {
    console.log("MouseUp");

    this.setState({
      resizing: false,
      resizeIndex: null
    });
  };

  render() {
    return ( <
      div className = "test-container"
      onMouseMove = {
        this.handleMouseMove
      }
      onMouseUp = {
        this.handleMouseUp
      } >
      <
      Cell widths = {
        this.state.widths
      }
      onMouseDown = {
        this.handleMouseDown
      }
      index = {
        0
      }
      /> <
      Cell widths = {
        this.state.widths
      }
      onMouseDown = {
        this.handleMouseDown
      }
      index = {
        1
      }
      /> <
      Cell widths = {
        this.state.widths
      }
      onMouseDown = {
        this.handleMouseDown
      }
      index = {
        2
      }
      /> <
      Cell widths = {
        this.state.widths
      }
      onMouseDown = {
        this.handleMouseDown
      }
      index = {
        3
      }
      /> <
      /div>
    );
  }
}

// Render it
ReactDOM.render( <
  Test / > ,
  document.body
);
.test-container {
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: row;
  background-color: cyan;
}

.cell-container {
  width: 100%;
  height: 100px;
  display: flex;
  flex-direction: row;
  background-color: grey;
  border: 1px solid black;
  overflow-y: hidden;
  overflow-x: hidden;

  /* Add this */
  min-width:3px;
  position:relative;
}

.cell-content {
  align-self: center;
  flex-shrink: 1;
  font-size: 12px;
  overflow-y: hidden;
  overflow-x: hidden;
  background-color: white;
}

.cell-vertical-grip {
  flex-shrink: 0;
  margin-left: auto;
  width: 3px;
  min-width: 3px;
  cursor: ew-resize;
  background-color: blue;

  /* Add this */
  position:absolute;
  top:0;
  height:100%;
  right:0;
}
<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>