推荐使React组件/ div可拖动的方法 [英] Recommended way of making React component/div draggable

查看:2211
本文介绍了推荐使React组件/ div可拖动的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想制作一个可拖动的(也就是说,可以通过鼠标重新定位)React组件,它似乎必然涉及全局状态和分散的事件处理程序。我可以用脏的方式,在我的JS文件中使用全局变量,甚至可以将它包装在一个漂亮的闭包界面中,但我想知道是否有一种方法可以更好地与React相结合。

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.

另外,既然我之前从未在原始JavaScript中做过这个,我想看看专家是如何做到的,以确保我已经处理了所有角落案件,特别是它们与React有关。

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.

谢谢。

推荐答案

我应该将此转变为博客文章,但这是非常可靠的例子。

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.

这里有小提琴: 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.

父母应该拥有可拖动的当前位置。在这种情况下,draggable仍将拥有我在拖动状态,但只要发生mousemove事件,就会调用 this.props.onChange(x,y)

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.

父母只需拥有非移动位置,因此可拖动将拥有它的拖动位置但是onmouseup它将调用 this.props.onChange(x,y)并将最终决定推迟到父级。如果父母不喜欢draggable结束的地方,它就不会更新它的状态,并且拖拽会在拖动之前快速恢复到它的初始位置。

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.

@ssorallen指出,因为draggable更像是一个属性,而不是一个东西,它可能更适合作为mixin。我对mixin的经验是有限的,所以我还没有看到他们在复杂的情况下如何帮助或妨碍他们。这可能是最好的选择。

@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.

这篇关于推荐使React组件/ div可拖动的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆