2

我在一个组件中有一些代码,可以检测该组件在滚动时是否可见。该代码如下所示:

    constructor(props) {
      super(props);
      this.handleScrollAnimation = this.handleScrollAnimation.bind(this);
  }

  componentDidMount() {
    this.handleLoadAnimation();
    window.addEventListener('scroll', _.throttle(this.handleScrollAnimation.bind(this), 300));
  }

  componentWillUnmount() {
    window.removeEventListener('scroll', this.handleScrollAnimation.bind(this));
  }

  handleLoadAnimation() {
    const component = this.CalloutBoxes;
    if (this.isElementInViewport(component)) {
      component.classList.add('already-visible');
    }
  }

  handleScrollAnimation() {
    const component = this.CalloutBoxes;
    if (this.isElementInViewport(component)) {
      component.classList.add('animated');
    }
  }

  isElementInViewport(el) {
    const rect = el.getBoundingClientRect();

    return rect.bottom > 0 &&
      rect.right > 0 &&
      rect.left < (window.innerWidth || document.documentElement.clientWidth) /* or $(window).width() */ &&
      rect.top < (window.innerHeight || document.documentElement.clientHeight); /* or $(window).height() */
  }

当我导航到另一个页面时,我得到了错误Cannot read property 'getBoundingClientRect' of null。我不确定我需要做什么来阻止这种情况,也找不到任何可以让我知道我需要做什么的东西。

这是我的组件渲染功能:

    render() {
    const styles = {
      image: {
        backgroundImage: `url(${this.props.data.image})`
      }
    };

    return (
      <div
        ref={c => {
          this.CalloutBoxes = c;
        }}
        className="mini-nav-box"
        >
        <Link to={this.props.data.link}>
          <div style={styles.image} className="mini-nav-box-bg"/>
          <div className="mini-nav-box-content">
            <h3>{this.props.data.title}</h3>
            <p>{this.props.data.copy}</p>
          </div>
        </Link>
      </div>
    );
  }

这是我在页面上调用组件的地方:

{ calloutBoxes.map((box, index) => {
  return <CalloutBoxes key={index} data={box}/>;
})}

编辑:

我看到我必须从删除中删除 .bind(this) 并添加事件侦听器,因为它们每次都在创建一个新函数。所以现在我的删除事件监听器现在看起来像这样:

window.removeEventListener('scroll', this.scrollFn);

但是,我仍然有isElementInViewport在另一个页面上触发函数的问题,该页面上没有这些组件之一。

4

1 回答 1

1

所以我意识到我非常非常愚蠢。

您需要做的是将去抖动添加到构造函数并将其从添加事件侦听器中删除。

构造函数代码现在如下所示:

constructor(props) {
  super(props);
  this.handleScroll = _.debounce(this.handleScrollAnimation.bind(this), 300);
}

然后 componentDidMount 现在看起来像这样:

componentDidMount() {
  this.handleLoadAnimation();
  window.addEventListener('scroll', this.handleScroll);
}
于 2017-04-24T14:18:27.707 回答