避免重新渲染滚动并提高React Web应用程序中的性能

时间:2015-06-16 08:53:32

标签: javascript performance reactjs

我有React的性能问题,基本上我有两个紧凑的菜单,当页面滚动到距离顶部x距离时。我在滚动时看到Web应用程序的另一个组件正在做很少的动作,原因是它们正在重新渲染。

要知道当用户进行滚动时到顶部的距离我在componentDidMount()上有一个eventlistener,我认为这导致了问题,但我不确定,因为你知道反应稳定版本是相当新的我也是这项技术的新手:

以下是一些代码,正好是顶部栏,它是嵌套组件,当用户从顶部开出超过100px时触发紧凑菜单栏:

export default class AppTopBar extends Component {
    constructor (props){
        super(props);
        this._bind("_handleOnScrollDocument");
        this.state = {
            StatusBar: false
        }
    }

    componentDidMount() {
        if (process.env.BROWSER) {
            document.addEventListener("scroll", (e) => this._handleOnScrollDocument(e), true);
        }
    }

    _handleOnScrollDocument(e) {
        if (e.target.body.scrollTop > 100) {            
            this.setState({ StatusBar: true }); 
        } else {
            this.setState({ StatusBar: false });
        }
    }

    render() {
        return (
            <div className="aui-core-apptopbar">
                <StatusBar companies={this.props.companies} compactMenuItems={this.props.compactMenuItems} StatusBar={this.state.showCompactStatusBar}/>
                <StatusBar companies={this.props.companies} userOptions={this.props.userOptions} compactMenuItems={this.props.compactMenuItems}/>
                <MainNavBarView menuItems={this.props.menuItems}/>
            </div>
        );
    }
}

我一直在研究和阅读有关组件生命周期和其他性能的信息:PURERENDERMIXIN

您是否了解更好的方法来获取轻量级Web应用程序并避免在滚动时重新呈现?

3 个答案:

答案 0 :(得分:7)

假设您为班级创建了一个局部变量flag。然后:

_handleOnScrollDocument(e) {
  let newFlag = (e.target.body.scrollTop > 100);
  if (flag !== newFlag) {
    this.setState({showCompactStatusBar: newFlag});
    flag = newFlag;
  }
};

仅当您从一个方向或另一个方向传递scrollTop阈值(100)时,这将导致状态更改(和重新渲染)。否则我们根本不需要设置状态,从而避免调用render

答案 1 :(得分:2)

&#34;内置&#34;解决方案是使用shouldComponentUpdate方法,它允许您比较当前return locals()&amp; 传入 props&amp;组件的state组件props然后如果您选择,请将state方法短路:

render

答案 2 :(得分:0)

我的网页内有overflow: auto CSS规则的组件上有滚动事件。我将滚动事件监听器附加到该组件,因为它被引导on this blog post。但是,将最后一个滚动位置设置为状态会严重破坏性能。

所以我在类构造函数中定义了最后一个位置并在那里更改了它,并避免了在每个滚动上重新渲染。

constructor(props){
  super(props)
  this.state = { scrollDirection: 'up' }
  this.lastY = 0
}

如果方向改变,我只会改变状态。

handleListScroll(event){
  const Y = event.currentTarget.scrollTop
  const lastY = this.lastY
  if (Y > lastY) {
    scrollDirection = 'down'
    if (this.state.scrollDirection === 'up') {
      this.setState({
        scrollDirection,
      })
    }
  }
  if (Y < lastY) {
    scrollDirection = 'up'
    if (this.state.scrollDirection === 'down') {
      this.setState({
        scrollDirection
      })
    }
  }
  this.lastY = Y
}