jhe*_*igs 4 javascript drag-and-drop reactjs
我创建了一个拖放界面,最终将其转换为表单生成器.我创建了一个表单构建器http://jsfiddle.net/szASZ/1/的小提琴.当您将其中一个顶部项目拖动到其下方的灰色拖放区域时,一切似乎都能正常工作.
但是,我得到的问题是当你刷新页面/小提琴并尝试对放置区域内的项目进行排序时.如果您抓住第一个放置区域顶部的"无线电输入"并将其移动到该放置区域内部或外部,则一切正常.
现在,尝试在其放置区域中拖动最后一项"复选框输入",所有内容也应该正常工作.最后,刷新页面/小提琴并移动相同的,最后一个"Checkbox Input"到另一个放置区.占位符将显示,然后永远不会消失.我发现的是"onDragEnd"事件在拖放循环的这个实例中从不被调用,但它每隔一段时间调用一次.此事件通常会中继到表单构建器的顶层,在该表单构建器中,它将获取正在拖动的项目并将其设置在新的数据数组中.
为了让事情变得更有趣,如果我将一个空对象添加到包含已删除项目的数组(http://jsfiddle.net/szASZ/-第30,34行),一切都按预期工作,所以看起来似乎"drop zone"项数组中的最后一项不能正确触发"onDragEnd"事件.
componentWillMount: function () {
var newInput = [
{ "classes": "soft-half push-half--bottom brand-bg--gray-dark brand-color--white", "title": "Text Input" },
{ "classes": "soft-half push-half--bottom brand-bg--gray-dark brand-color--white", "title": "Checkbox Input" },
{ "classes": "soft-half push-half--bottom brand-bg--gray-dark brand-color--white", "title": "Radio Input" }
];
var newZones = [
[
{ "classes": "soft-half push-half--bottom brand-bg--gray-dark brand-color--white", "title": "Radio Input" },
{ "classes": "soft-half push-half--bottom brand-bg--gray-dark brand-color--white", "title": "Text Input" },
{ "classes": "soft-half push-half--bottom brand-bg--gray-dark brand-color--white", "title": "Checkbox Input" }
,{}
],
[
{ "classes": "soft-half push-half--bottom brand-bg--gray-dark brand-color--white", "title": "Text Input" },
{ "classes": "soft-half push-half--bottom brand-bg--gray-dark brand-color--white", "title": "Checkbox Input" }
,{}
]
];
this.setState({ inputs: newInput });
this.setState({ zones: newZones });
}
Run Code Online (Sandbox Code Playgroud)
基本上,这是我遇到的主要问题,我不知道为什么每个其他项目都被排序,删除和事件触发正确但最后一个?谢谢!
这与我几个月前提交的React bug直接相关/引起:
React利用事件冒泡并绑定文档根目录中的所有事件,这在大多数情况下都有效,但在这种特殊情况下会失败.与鼠标事件不同,触摸和拖动事件始终发送到接收touchstart
或dragstart
事件的事件(而不是指针当前所在的元素).如果dragstart
从DOM中删除了接收事件的元素(就像在这种特殊情况下它从它开始的列表中消失一样)那么那个(分离的)元素仍将接收dragend
事件,但它不会冒泡到文档根目录,所以React永远不会看到该事件.
您只能在拖动最后一个元素时看到这个,因为您正在使用key
道具不正确.因为您当前使用索引作为键,当您有一个列表ABCD并开始拖动B(导致列表成为ACD)时,React会将第二个元素(以前为B)变为具有文本"C",从而改变第三个元素元素(以前为C)具有文本"D",并删除第四个元素(以前为D).如果您使用唯一的每个项目ID作为键而不是索引,React将始终删除您正在拖动的元素,这将更容易推理.(由于该错误,您会看到此行为始终发生,而不是仅在拖动最后一个元素时发生.)
作为一种变通方法,您可以在dragstart处理程序中手动绑定dragend
/ dragenter
/ dragleave
处理程序并清理它们dragend
.这将为这些事件完全回避React的事件系统:
// DRAGGING
dragStart: function (e) {
this.getDOMNode().addEventListener('dragend', this.dragEnd, false);
this.getDOMNode().addEventListener('dragenter', this.dragEnter, false);
this.getDOMNode().addEventListener('dragleave', this.dragLeave, false);
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', e.target.innerHTML);
this.props.dragStart(this.props.item, { sorting: true });
},
dragEnd: function (e) {
this.getDOMNode().removeEventListener('dragend', this.dragEnd, false);
this.getDOMNode().removeEventListener('dragenter', this.dragEnter, false);
this.getDOMNode().removeEventListener('dragleave', this.dragLeave, false);
var opts = e.dataTransfer.dropEffect === 'none' ? { success: false } : { success: true };
this.props.dragEnd(opts);
},
Run Code Online (Sandbox Code Playgroud)
使用这个配置,你只指定onDragStart
在render
.
(我会看看我是否可以解决这个问题 - 据我所知,除了我之外,你是第一个打击它的人,所以它不是我们的优先考虑.)
归档时间: |
|
查看次数: |
1540 次 |
最近记录: |