react按钮拖拽_推荐使React组件/ div可拖动的方法

本文探讨如何在React中创建一个可拖动的组件。通过使用全局状态和事件处理器,作者提供了一个完整的示例,包括组件的初始位置、拖动状态和鼠标事件处理。示例代码展示了一个Draggable组件的实现,详细解释了组件内部的工作原理,以及在不同场景下状态所有权的考虑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

I want to make a draggable (that is, repositionable by mouse) React component, which seems to necessarily involve global state and scattered event handlers. I can do it the dirty way, with a global variable in my JS file, and could probably even wrap it in a nice closure interface, but I want to know if there's a way that meshes with React better.

Also, since I've never done this in raw JavaScript before, I'd like to see how an expert does it, to make sure I've got all the corner cases handled, especially as they relate to React.

Thanks.

解决方案

I should probably turn this into a blog post, but here's pretty solid example.

The comments should explain things pretty well, but let me know if you have questions.

And here's the fiddle to play with: http://jsfiddle.net/Af9Jt/2/

var Draggable = React.createClass({

getDefaultProps: function () {

return {

// allow the initial position to be passed in as a prop

initialPos: {x: 0, y: 0}

}

},

getInitialState: function () {

return {

pos: this.props.initialPos,

dragging: false,

rel: null // position relative to the cursor

}

},

// we could get away with not having this (and just having the listeners on

// our div), but then the experience would be possibly be janky. If there's

// anything w/ a higher z-index that gets in the way, then you're toast,

// etc.

componentDidUpdate: function (props, state) {

if (this.state.dragging && !state.dragging) {

document.addEventListener('mousemove', this.onMouseMove)

document.addEventListener('mouseup', this.onMouseUp)

} else if (!this.state.dragging && state.dragging) {

document.removeEventListener('mousemove', this.onMouseMove)

document.removeEventListener('mouseup', this.onMouseUp)

}

},

// calculate relative position to the mouse and set dragging=true

onMouseDown: function (e) {

// only left mouse button

if (e.button !== 0) return

var pos = $(this.getDOMNode()).offset()

this.setState({

dragging: true,

rel: {

x: e.pageX - pos.left,

y: e.pageY - pos.top

}

})

e.stopPropagation()

e.preventDefault()

},

onMouseUp: function (e) {

this.setState({dragging: false})

e.stopPropagation()

e.preventDefault()

},

onMouseMove: function (e) {

if (!this.state.dragging) return

this.setState({

pos: {

x: e.pageX - this.state.rel.x,

y: e.pageY - this.state.rel.y

}

})

e.stopPropagation()

e.preventDefault()

},

render: function () {

// transferPropsTo will merge style & other props passed into our

// component to also be on the child DIV.

return this.transferPropsTo(React.DOM.div({

onMouseDown: this.onMouseDown,

style: {

left: this.state.pos.x + 'px',

top: this.state.pos.y + 'px'

}

}, this.props.children))

}

})

Thoughts on state ownership, etc.

"Who should own what state" is an important question to answer, right from the start. In the case of a "draggable" component, I could see a few different scenarios.

Scenario 1

the parent should own the current position of the draggable. In this case, the draggable would still own the "am I dragging" state, but would call this.props.onChange(x, y) whenever a mousemove event occurs.

Scenario 2

the parent only needs to own the "non-moving position", and so the draggable would own it's "dragging position" but onmouseup it would call this.props.onChange(x, y) and defer the final decision to the parent. If the parent doesn't like where the draggable ended up, it would just not update it's state, and the draggable would "snap back" to it's initial position before dragging.

Mixin or component?

@ssorallen pointed out that, because "draggable" is more an attribute than a thing in itself, it might serve better as a mixin. My experience with mixins is limited, so I haven't seen how they might help or get in the way in complicated situations. This might well be the best option.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值