我正在编写一个组件,如果单击其右边框并拖动它,则允许更改它的子元素的宽度。
但是我遇到了一些问题。首先,拖动div元素很尴尬,因为如果鼠标在拖动时进入右边的另一个元素,拖动状态就会丢失并出现错误。
另外,当点在右边框的5个像素内时,我当前显示调整大小光标,在可调整大小的div内部工作正常。但是,如果您从右侧接近边框(鼠标位于其他div内),即使您在5个像素内,也无法选择它。
另一个问题是,当我拖动鼠标并调整div的大小时,鼠标会选择拖动它的文本。
最后,因为元素每次更改时都必须重新渲染,所以我注意到性能并不总是很平滑。
有关如何缓解这些问题的建议吗?
Resizable = React.createClass({
propTypes: {
id : React.PropTypes.string,
class : React.PropTypes.string,
width : React.PropTypes.number,
onResize : React.PropTypes.func,
onAction : React.PropTypes.func,
},
getInitialState: function() {
return {
showResizeCursor : false,
canResize : false,
};
},
getDefaultProps: function() {
return {
};
},
_handleMouseMove: function(event) {
var node = React.findDOMNode(this);
var offsets = node.getBoundingClientRect();
var divLeft = offsets.left;
var divRight = offsets.right;
var mouseX = event.clientX;
var maxWidth = this.props.maxWidth || this.props.width;
var minWidth = this.props.minWidth || this.props.width;
var newWidth = mouseX - divLeft + 200;
var isWithinBounds = newWidth <= maxWidth && newWidth >= minWidth;
if (this.state.canResize && isWithinBounds) {
this.props.onResize(newWidth);
}
var difference = Math.abs(divRight - mouseX);
if (difference < 4) {
return this.setState({ showResizeCursor: true });
}
if (this.state.showResizeCursor) {
this.setState({ showResizeCursor: false });
}
},
_handleMouseUp: function() {
this.setState({ canResize: false });
},
_handleMouseDown: function() {
if (this.state.showResizeCursor) {
this.setState({ canResize: true });
}
},
render: function() {
var style = {
width : this.state.width,
};
if (this.state.showResizeCursor) { style.cursor = 'col-resize'; }
return (
<div id={this.props.id}
style ={style}
className ={this.props.class}
onMouseDown ={this._handleMouseDown}
onMouseUp ={this._handleMouseUp}
onMouseMove ={this._handleMouseMove}
onMouseLeave={this._handleMouseUp}
>
{this.props.children}
</div>
);
}
});
使用示例:
render: function() {
...
return (
<Wrapper>
<Resizable
id = {'list-view'}
width = {this.state.listViewWidth}
maxWidth = {this.state.listViewMaxWidth}
minWidth = {this.state.listViewMinWidth}
onResize = {this._handleListViewResize}
>
{first_column_that_should_be_resizable}
</Resizable>
{second_column_not_resizeable}
答案 0 :(得分:6)
这里有许多不同的问题......
首先,拖动div元素很尴尬,因为如果鼠标在拖动时进入右边的另一个元素,拖动状态就会丢失并且会出错。
当您开始编写第一个拖放行为时,这是一个非常常见的问题。你不应该在同一个元素上监听mousedown,mousemove和mouseup事件,你应该只监听mousedown事件,并且在那个处理程序中开始监听另外两个但是在文档的主体上。这样,您就拥有了一个全局处理程序,鼠标不会遇到其他元素的问题。
另外,当点在右边框的5个像素内时,我当前显示调整大小光标,在可调整大小的div内部工作正常。但是,如果您从右侧接近边框(鼠标在其他div内),即使您在5像素范围内,也无法选择它。
我建议你只使用CSS。它是什么:)
另一个问题是,当我拖动鼠标并调整div的大小时,鼠标会选择拖动它的文本。
是的,只是CSS。执行mousedown处理程序后,为元素添加一个特殊的CSS类,并在CSS中添加类似的内容。
.disable-select {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
最后,因为每次更改宽度时元素必须重新渲染,我注意到性能并不总是平滑。
我不认为React是你最好的选择。我只想使用jQuery和componentDidMount
等生命周期方法添加此行为。这样,您可以使用普通的jQuery(在每次鼠标移动时)调整div的大小,然后将最终状态(即最终大小)应用于mouseup处理程序上的组件。