React JS事件不会为最后渲染的元素触发

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)

基本上,这是我遇到的主要问题,我不知道为什么每个其他项目都被排序,删除和事件触发正确但最后一个?谢谢!

Sop*_*ert 6

这与我几个月前提交的React bug直接相关/引起:

#1355:touchmove不会触发已删除的元素

React利用事件冒泡并绑定文档根目录中的所有事件,这在大多数情况下都有效,但在这种特殊情况下会失败.与鼠标事件不同,触摸和拖动事件始终发送到接收touchstartdragstart事件的事件(而不是指针当前所在的元素).如果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)

使用这个配置,你只指定onDragStartrender.

(我会看看我是否可以解决这个问题 - 据我所知,除了我之外,你是第一个打击它的人,所以它不是我们的优先考虑.)


归档时间:

查看次数:

1540 次

最近记录:

10 年,7 月 前