React.js 循环图片幻灯片的性能问题

Posted

技术标签:

【中文标题】React.js 循环图片幻灯片的性能问题【英文标题】:Performance concern with a React.js looping picture slideshow 【发布时间】:2016-09-12 18:26:35 【问题描述】:

我们希望显示看起来像 gif 的图片的循环幻灯片。当前结果在此 url 可见:https://figuredevices.com。

我们目前的方法是使用不透明度来显示或隐藏幻灯片:

class SlideShow extends React.Component 

  constructor(props, context) 
    super(props);
    this.state = 
      currentSlide: 0
    ;
    this.interval = null;

  

  componentDidMount() 
    this.interval = setInterval(this.transitionToNextSlide.bind(this), 200);
  

  componentWillUnmount()
    if(this.interval)
      clearInterval(this.interval);
    
  

  transitionToNextSlide() 

    let nextSlide = this.state.currentSlide + 1;

    if (nextSlide == this.props.slides.length) 
        nextSlide = 0;
    
    this.setState(currentSlide: nextSlide);
  


  render () 

    let slides = this.props.pictures.map((picture, idx) => 
      let slideContainerStyle = 
        opacity: this.state.currentSlide == idx ? 1 : 0
      ;
      return(
        <div style=slideContainerStyle key=idx>
          <Slide picture=picture/>
        </div>
      );
    )

    let containerStyle = 
      width:'100%'
    ;

    return (
      <div style=containerStyle>
          slides
      </div>
    );

  

;

图片以 5 x 5 的形式加载到 this.props.picture。图片的数量没有限制,随着这个数量的增长,我担心性能。有两点我觉得不对劲:

render 方法中的 map 操作是每 200 毫秒遍历一次整个数组,只是为了改变两个 css 属性。 DOM 的大小增长了很多,但大多数节点都被隐藏了

你会建议一个更好的方法,也许使用 animation 或 react-motion ?

【问题讨论】:

为什么不只使用一个 &lt;Slide&gt; 并每 200 毫秒更新一次 picture 属性? 如果你想保持不透明度过渡..你只需要两张幻灯片。使用next 道具来定位动画&lt;Slide next=isNext /&gt;,正如@Aaron 所说,只需相应地更改道具。 我没有看到任何不透明度褪色,但是是的:如果你想要一个过渡,你可以使用 ReactCSSTransitionGroup 并将 &lt;Slide&gt; 替换为当前图片。 确实我认为 ReactCSSTransitionGroup 更适合我不想要的过渡效果。我曾尝试使用单张幻灯片进行设置,但幻灯片之间的过渡并不顺畅,因为我失去了不透明度过渡,这使得@azium 命题非常聪明:-)。让我试一试。 ReactCSSTransitionGroup 基本上做了 azium 为您描述的事情:当元素被交换时(通过查看key),它将创建第二个元素淡入,同时淡出前一个元素,然后当过渡完成时,它将删除旧元素,因此您只剩下新元素。它应该非常高效。 【参考方案1】:

您应该将所有图片保存为一个数组,并且每 200 毫秒递增一次数组索引。然后,不是每次都显示所有图片,而是让它在您当前的索引处显示图片。这好多了,因为您只返回一张照片而不是一堆不可见的照片:)

注意:我无法对此进行测试,因此我不确定所有内容在语法上是否完全正确,但这是一般的想法。每 200 毫秒,递增 slideIndex。然后,总是返回一个只包含你想看的一张图片的 div。

class SlideShow extends React.Component 

  constructor(props, context) 
    super(props);
    this.state = 
      slideIndex;
    ;
    this.interval = null;

  

  componentDidMount() 
    this.interval = setInterval(this.transitionToNextSlide.bind(this), 200);
  

  componentWillUnmount()
    if(this.interval)
      clearInterval(this.interval);
    
  

  transitionToNextSlide() 
    this.setState(this.state.slideIndex: (this.state.slideIndex + 1) % this.props.slides.length)


  render () 
    let containerStyle = 
      width:'100%'
    ;

    return (
      <div style=containerStyle>
          <Slide picture=this.props.pictures[this.state.currentSlide]/>
      </div>
    );   
    
;

【讨论】:

以上是关于React.js 循环图片幻灯片的性能问题的主要内容,如果未能解决你的问题,请参考以下文章

使用adaptiveHeight时React.js动画幻灯片高度

分析React.js性能

React.js 性能分析

使用 React.js 为自定义轮播设置动画

Preact:React.js替代品?

Jquery Mobile 和 Phonegap 的卡顿性能问题