繁体   English   中英

Reactjs 在 setState 后失去了 touchmove

[英]Reactjs lost touchmove after setState

我有一个关于 Reactjs 的触摸事件的问题。
当触摸移动时,我将调用 setState 来呈现新的 div。
但是如果我继续处理那些新的 div,那么 touchmove 事件就不会再触发了。
就像下面的gif
在此处输入图片说明

如果我搬出那些 div 那么它就起作用了。
在此处输入图片说明

这是我的示例代码:

var Container = React.createClass({
    getInitialState: function () {
        return {
            index: 0,
            rows: this.getRowsByIndex(0)
        };
    },

    getRowsByIndex: function(index) {
        var rows = [];

        for (var i = index; i < index + 10; i++) {
            rows.push(i);
        }

        return rows;
    },

    handleTouchStart: function() {
        console.log('start')
    },

    handleTouchMove: function() {
        console.log('move')
        this.setState({
            index: this.state.index + 1,
            rows: this.getRowsByIndex(this.state.index + 1)
        });
    },

    handleTouchEnd: function() {
        console.log('end')
    },

    handleTouchCancel: function() {
        console.log('cancel')
    },

    render: function () {
        return (
            <div style={{ width: 250, height: 300, border: '1px solid' }}
                onTouchStart={this.handleTouchStart}
                onTouchMove={this.handleTouchMove}
                onTouchEnd={this.handleTouchEnd}
                onTouchCancel={this.handleTouchCancel}>
                <div>
                    {this.state.rows.map(function(item, index) {
                        return <div key={item} style={{ width: 100, backgroundColor: '#eee' }}>{item}</div>;
                    })}
                </div>
            </div>
        );
    }
});

现在我只知道如果我将 pointerEvents: none 添加到 div,那么它就可以工作。 有没有人有同样的问题?

tl;博士

<div key={item}更改为<div key={index}

演示: https : //stackblitz.com/edit/react-5yqumb


有点长的解释

你需要改变这部分

{this.state.rows.map(function(item, index) {
    return (
        <div key={item} style={{ width: 100, backgroundColor: '#eee' }}> 
            {item}
        </div>
    );
})}

到(看看key={index} ):

{this.state.rows.map(function(item, index) {
    return (
        <div key={index} style={{ width: 100, backgroundColor: '#eee' }}> 
            {item}
        </div>
    );
})}

如果你改变了这个

<div key={index} style={{ width: 100, backgroundColor: '#eee' }}> 
    {item}
</div>

到另一个 React 组件,如:

class Box extends Component {
  componentDidMount() {
    console.log('mounted <Box />', this.props.children);
  }

  componentWillUnmount() {
    console.log('unmounted <Box />', this.props.children);
  }

  render() {
    return <div style={{ width: 100, backgroundColor: '#eee' }}>{this.props.children}</div>;
  }
}

您可以很容易地观察到,在每次状态更新时,您都会挂载和卸载<Box />组件。 看看这些console.logs

mounted <Box /> 0
mounted <Box /> 1
mounted <Box /> 2
mounted <Box /> 3
mounted <Box /> 4
mounted <Box /> 5
mounted <Box /> 6
mounted <Box /> 7
mounted <Box /> 8
mounted <Box /> 9
start
unmounted <Box /> 0
mounted <Box /> 10
unmounted <Box /> 1
mounted <Box /> 11
unmounted <Box /> 2
mounted <Box /> 12
unmounted <Box /> 3
mounted <Box /> 13
unmounted <Box /> 4
mounted <Box /> 14
unmounted <Box /> 5
mounted <Box /> 15
unmounted <Box /> 6
mounted <Box /> 16
unmounted <Box /> 7
mounted <Box /> 17
unmounted <Box /> 8
mounted <Box /> 18

删除和添加 dom 节点是问题的根源。 在您的情况下,您希望在 DOM 中具有相同数量的<div />并仅更新其内容,因此在该特定上下文中使用索引是安全的。 您可以在官方文档 - Lists and Keys - React 中阅读有关密钥的更多信息。

当您将<div key={item}更改为<div key={index}console.logs如下所示:

mounted <Box /> 0
mounted <Box /> 1
mounted <Box /> 2
mounted <Box /> 3
mounted <Box /> 4
mounted <Box /> 5
mounted <Box /> 6
mounted <Box /> 7
mounted <Box /> 8
mounted <Box /> 9
start
end

您可以随时尝试在 DOM 中设置断点以查看 DOM 节点是否被删除。

key={index} 键={索引}

key={item} 键={item}

据我所知,这是因为touchmovetouchend应该从同一个活动触摸 [1] 分派;

也就是说,一旦你移除了(在这种情况下由于 React 重新渲染)启动touchstart的元素,它不会进一步调度touchmovetouchend事件。

这就是为什么pointer-events: none似乎使它起作用,因为您只是绕过了可以删除的元素。

[1] https://www.w3.org/TR/touch-events/#event-touchmove

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM