我有一个React组件,用户可以更改其可见性和位置。
通过添加和删除CSS类的可见性,通过函数的位置,设置Drag&之后的新位置。落在顶部和左侧。
这样可行,但我的问题是当组件被重新渲染为可见性时,React不会更新样式(因此不会将位置重写为初始值)。
manifest.xml
首次呈现卡片时,样式看起来像<application
android:name="android.support.multidex.MultiDexApplication" //this line >
</application>
。
当卡片移动时,样式看起来像class MoveableCard extends React.Component {
...
render() {
...
return <div className={(this.props.isVisible ? '' : 'hide')}
draggable="true" onDragStart={dragStart}
style={{top:'initial', left:'initial'}}>
...
</div>
}
}
function dragStart(event) {
var style = window.getComputedStyle(event.target, null)
event.dataTransfer.setData("text/plain", JSON.stringify({
id:event.target.getAttribute('data-reactid'),
x:(parseInt(style.getPropertyValue("left"),10) - event.clientX),
y:(parseInt(style.getPropertyValue("top"),10) - event.clientY)
}))
}
function dragOver(event) {
event.preventDefault()
return false
}
function drop(event) {
let data = JSON.parse(event.dataTransfer.getData("text/plain"))
let el = document.querySelectorAll("[data-reactid='" + data.id + "']")[0]
el.style.left = (event.clientX + parseInt(data.x, 10)) + 'px'
el.style.top = (event.clientY + parseInt(data.y, 10)) + 'px'
event.preventDefault()
return false
}
document.body.addEventListener('dragover',dragOver,false)
document.body.addEventListener('drop',drop,false)
。
当卡片关闭时,类style="top: initial; left: initial;"
会被添加,但样式仍为style="top: 162px; left: 320px;"
,无论我如何创建样式对象。
那么,我如何强制React更新样式呢? 或者还有另一种方法可以实现这一目标吗?
答案 0 :(得分:0)
答案的简短版本:
使用内部状态和组件生命周期
长版:
首先,我建议将事件处理程序放在组件中而不是全局方法中:
class MoveableCard extends React.Component {
dragStart(event) {}
dragOver(event) {}
drop(event) {}
}
其次,在组件的构造函数中,将组件的this-context绑定到那些处理程序。 (那么,或者你在渲染方法中使用箭头函数)
constructor() {
this.dragStart = this.dragStart.bind(this);
this.dragOver = this.dragOver.bind(this);
this.drop = this.drop.bind(this);
}
为了让组件更新&#39;或重新渲染,我建议在这种情况下改变其内部状态。因此,您首先在componentWillMount中的初始状态中添加初始值。
componentWillMount() {
this.state = { top: 0, left: 0 };
}
在事件处理程序中,您现在可以使用this.setState更新innerState的top和left(以及您需要绑定它的内容)。
drop() {
// Assuming you filled in this.left and this.top in the dragOver method
this.setState({ top: this.top, left: this.left });
}
通过使用setState,将使用内部状态的新值触发重新渲染。现在,您可以在渲染方法中使用this.state.top
和this.state.left
:
render() {
return (
<div className={(this.props.isVisible ? '' : 'hide')}
draggable="true"
onDragStart={this.dragStart}
style={{top: this.state.top, left: this.state.left}}>
</div>
);
}
答案 1 :(得分:0)
好的,得到了一个基于Andrew,dejakob和Chris答案的解决方案,谢谢大家:)
我最初想过,我无法将函数移动到Component中,因为具有最终位置的Drop事件是由元素发出的,我放弃了我的卡,而不是卡本身。
但是有一个dragend
事件,由卡发出并包含位置。
现在我只需要使用它来设置状态中的位置(并通过父级中的unsetPosition
将其删除。)
class MoveableCard extends React.Component {
constructor(props) {
super(props)
this.state = {
styles: {top:'initial', left:'initial'}
}
this.drop = this.drop.bind(this);
}
dragStart(e) {
let style = window.getComputedStyle(e.target, null)
this.setState({l: parseInt(style.getPropertyValue("left")) - e.clientX, y: parseInt(style.getPropertyValue("top")) - e.clientY})
}
drop(e) {
this.setState({left: this.state.l + e.clientX, top: this.state.y + e.clientY})
e.preventDefault()
return false
}
unsetPosition() {
this.setState({styles: {top:'initial', left:'initial'}})
}
render() {
return <div className={(this.props.isVisible ? '' : 'hide')}
draggable="true"
onDragStart={this.dragStart}
onDragEnd={this.drop}
style={this.state.styles}>
...
</div>
}
}