代码之家  ›  专栏  ›  技术社区  ›  intrepid_em

如何在响应组件卸载时停止JavaScript事件?

  •  0
  • intrepid_em  · 技术社区  · 6 年前

    背景:
    我有一个用React构建的Web应用程序(目前为16.4.2版)。它只能在触摸屏上使用。它由很多按钮组成,可以做很多事情,而且由于都是触摸,所以我使用TouchStart/TouchEnd来处理这些操作。

    例子: 这是我如何使用事件的基本示例。你点击一个按钮,它就会设置 this.state.exampleRedirect true 从而使组件重新呈现,然后转到新页面(使用react router dom)。这一切都很好。

    <button
      type='button'
      onTouchStart={() => this.setState({ exampleRedirect: true })}
      className='o-button'>
      Open modal
    </button>
    

    问题:
    我最初用onclick来处理按钮,但是有问题,因为我的用户手指肥大,没有太多的技术背景,而且当他们触摸按钮时,他们会将手指拖到按钮上,按钮就不会触发点击。OntouchStart通过在任何触摸发生时触发(拖动、滑动、轻敲等)来解决此问题。

    问题在于OnTouchStart。用户触摸按钮,它会快速更改页面(使用路由器)并重新呈现新页面。这个应用程序速度很快,所以这几乎是即时的,这意味着当新页面加载时,用户的手指通常仍然在屏幕上,从而在他们触摸的任何东西上触发另一个触摸事件。这通常是另一个路由按钮,所以它只会在屏幕上触发,直到他们抬起手指。

    我正通过在每次页面加载时延迟启用按钮来解决这个问题。

    // example component
    import React, { Component } from 'react';
    
    class ExampleComponent extends Component {
      state = { buttonsDisabled: true }
    
      // after 300ms, the buttons are set to enabled (prevents touch events 
      // from firing when the page first loads
      componentWillMount() {
        timeoutId = setTimeout(() => {
          this.setState({ buttonsDisabled: false });
        }, 300);
      }
    
      render() {
        return (
          // button in render method
          <button
            disabled={this.state.buttonsDisabled}
            type='button'
            onTouchStart={() => this.setState({ exampleRedirect: true })}
            className='o-button'>
            Open modal
          </button>
        );
      }
    

    有更好的方法吗?或者是一种做我正在做的事情的方法,但是在全球范围内,这样我就不必在大约100个组件中添加这个jankity代码了?

    谢谢!

    1 回复  |  直到 6 年前
        1
  •  1
  •   Shubham Khatri    6 年前

    而不是使用 onTouchStart 当触摸点放在触摸表面上并使用超时时触发的事件,这有点像黑客攻击,您应该使用 onTouchEnd 因为当接触点从接触表面移除时,它会被点燃,从而确保不会发生上述情况。

    // example component
    import React, { Component } from 'react';
    
    class ExampleComponent extends Component {
      state = { buttonsDisabled: true }
    
      // after 300ms, the buttons are set to enabled (prevents touch events 
      // from firing when the page first loads
      componentWillMount() {
        timeoutId = setTimeout(() => {
          this.setState({ buttonsDisabled: false });
        }, 300);
      }
    
      render() {
        return (
          // button in render method
          <button
            disabled={this.state.buttonsDisabled}
            type='button'
            onTouchEnd={() => this.setState({ exampleRedirect: true })}
            className='o-button'>
            Open modal
          </button>
        );
      }