通过转换更改组件道具

时间:2017-02-13 20:50:08

标签: javascript reactjs css-transitions

我想要实现的是通过过渡动画改变不透明度,以获得改变可见元素的平滑效果。

我构建的组件是Slider。虽然下一张幻灯片的幻灯片不透明度正在变为1,但当前幻灯片的更改为0。

我的第一个幻灯片组件版本

 export class Slide extends React.PureComponent {
   render() {
    let { img, backgroundColor, active, ...props } = this.props;
    const Wrapper = styled.div`
      background-image: url(${img});
      background-color: ${backgroundColor};
      background-size: cover;
      background-position: 50% 50%;
      opacity: ${active ? 1 : 0};
      transition: opacity 1s;
    `;
    return (
      <Wrapper/>
    )
  }
}

我的第一个想法是将当前幻灯片索引存储在状态中。所以我的Slides容器知道哪个幻灯片是最新的,并将其活动属性更改为true。但这会影响重新渲染此幻灯片并且转换不可见。第一个问题:为什么?

我最终玩了反应dom,我手动改变当前元素的不透明度。

export default class Slider extends Component {
  __slidesCount;
  __current;
  __refs = [];

  constructor(props) {
    super(props);
    this.__current = 0;
    this.__slidesCount = this.props.children.length
  }

  componentWillMount() {
    // Save number of slides
  }

  nextSlide = () => {
    let next = this.__current < this.__slidesCount - 1 ? this.__current + 1 : 0,
      nextSlide = this.__refs[next],
      currentSlide = this.__refs[this.__current];

    ReactDOM.findDOMNode(nextSlide).style['opacity'] = 1;
    ReactDOM.findDOMNode(currentSlide).style['opacity'] = 0;
    this.__current = next;
    setTimeout(this.nextSlide, 3000)
  };

  componentDidMount() {
    // set timeout to run it after component mounting is finished
    setTimeout(() => {
      ReactDOM.findDOMNode(this.__refs[0]).style['opacity'] = 1;
    }, 0);
    // call function changing slide to next
    setTimeout(this.nextSlide, 3000)
  }

  render() {
    let { children, ...props } = this.props;
    let slides = children.map((slide, index) => {
      return React.cloneElement(slide, { ref: ref => this.__refs.push(ref) })
    });
    return (
      <SlidesWrapper {...props}>
        {slides}
      </SlidesWrapper>
    )
  }
}

您对此解决方案有何看法?有什么方法可以更容易吗? 当然,我不想使用jQuery并最大限度地减少外部css的使用。

1 个答案:

答案 0 :(得分:1)

编辑:原来OP正在使用Styled Components,并且每次调用render()时都会创建一个新组件,因为const Wrapper...位于其中render()方法。

这导致Wrapper组件每次更新Slide组件时重新安装,因此不会发生任何CSS转换,因为它是组件的新实例,因此是新的HTML元素。

这里有一个概念证明,即使active状态作为道具传递,并且没有外部CSS来控制UI状态,CSS转换仍然有效:CodePen。我使用了相同的更改不透明度的示例,并在活动幻灯片之间切换以显示其有效。

如果您的状态发生变化时Slide重新呈现,则必须有其他可能重新呈现整个序列的内容。也许您的组件正在被删除并重新添加,或其他内容。您需要自己调试,或提供更多代码,以便我们为您提供帮助。

或者,如评论中所述,如果您需要,可以使用ReactCSSTransitionGroup