【问题标题】:Variable transitions in React using ReactCSSTransitionGroup使用 ReactCSSTransitionGroup 在 React 中进行变量转换
【发布时间】:2016-07-15 17:10:25
【问题描述】:

ReactCSSTransitionGroup 使用 CSS 文件来定义和存储过渡。这很好,效果很好。但是如果一个组件需要一个可变的转换配置,例如一个变量transition-duration,它需要从 0ms 到 10000ms 的任何值?当 transition-duration 存储在 CSS 文件中时,如何从组件的 Javascript 类中更改它的值?

示例:

假设您想要制作一个幻灯片组件,并且您想要实现一个选项来更改 fading-duration(动画从一张幻灯片淡入另一张幻灯片所需的时间)。你这样调用组件:

<Slideshow fadeDuration={1000}>

这是组件将过渡添加到将要呈现的幻灯片元素的方式:

render: function() {
  return (
    <div>
      <ReactCSSTransitionGroup
        transitionName="example"
        transitionEnterTimeout={500}
        transitionLeaveTimeout={300}>
        {this.slide}
      </ReactCSSTransitionGroup>
    </div>
  );
}

这是 ReactCSSTransitionGroup 定义过渡所需的 css 文件:

.example-enter {
  opacity: 0.01;
}

.example-enter.example-enter-active {
  opacity: 1;
  transition: opacity 500ms ease-in;
}

.example-leave {
  opacity: 1;
}

.example-leave.example-leave-active {
  opacity: 0.01;
  transition: opacity 300ms ease-in;
}

现在如何在组件中使用props.fadeDuration 来更改位于css 文件中的transition-duration 的值?

到目前为止,我唯一想到的是,我必须删除 ReactCSSTransitionGroup 并使用 refs'Style Object' 'transition' property 手动创建过渡。这是要走的路吗?或者我该怎么做?

【问题讨论】:

    标签: javascript reactjs transition reactcsstransitiongroup


    【解决方案1】:

    您可以使用 jss 库从 javascript 操作 css。这是一个非常好的库,可以解决很多情况。看一看。

    更新

    我会告诉你如何使用它。在主要情况下,使用 jss-react 的组件看起来像:

    import React, { Component } from 'react'
    import useSheet from 'react-jss'
    
    // You can use jss directly too!
    import jss from 'jss'
    import vendorPrefixer from 'jss-vendor-prefixer'
    jss.use(vendorPrefixer())
    
    const styles = {
      button: {
        'background-color': 'yellow'
      },
      label: {
        'font-weight': 'bold'
      }
    }
    
    class Button extends Component {
      render() {
        const { classes } = this.props.sheet
    
        return (
          <div className={classes.button}>
            <span className={classes.label}>
              {this.props.children}
            </span>
          </div>
        )
      }
    }
    
    export default useSheet(Button, styles)
    

    样式是在组件外部定义的,然后使用higher-order component 包装它并注入样式。在大多数情况下都可以,但是由于我们需要从组件内部添加 css 规则,因此我们需要使用另一种方法。我们需要使用 jss 作为child element instead of higher order component。这将允许我们在 addRules() 方法的帮助下从组件中添加规则。

    import React, { Component } from 'react';
    import ReactCSSTransitionGroup from 'react-addons-css-transition-group'
    import useSheet from 'react-jss'
    import jss from 'jss'
    
    let styles = {};
    const sheet = jss.createStyleSheet(styles, {named: false})
    class Foo extends Component {
      constructor(props) {
        super(props);
        this.state ={
          isVisible: false
        }
      }
      toggle() {
        this.setState({
          isVisible: !this.state.isVisible
        })
      }
    
      render() {
        const duration = 500
        const { classes } = sheet
        sheet.addRules(
          {            
            '.example-enter': {
              opacity: 0.01
            },
            '.example-enter-active': {
              color: 'red',
              opacity: 1,
              transition: 'opacity ' + duration + 'ms ease-in'
            },
            '.example-leave': {
              opacity: 1
            },
            '.example-leave-active': {
              opacity: 0.01,
              transition: 'opacity '+ duration +'ms ease-in'
            }
          }
        );
        return (
          <div className={classes.red}>
            <Jss sheet={sheet} />
            <a onClick={this.toggle.bind(this)}>Click</a>
              <ReactCSSTransitionGroup
              transitionName="example"
              transitionEnterTimeout={10}
              transitionLeaveTimeout={600}>
              { this.state.isVisible ? <div>Visible</div> : null}
            </ReactCSSTransitionGroup>
          </div>
      );
      }
    }
    
    
    const map = new WeakMap()
    
    class Jss extends Component {
      componentWillMount() {
        const {sheet} = this.props
        const counter = map.get(sheet) || 0
        if (!counter) sheet.attach()
        map.set(sheet, counter + 1)
      }
    
      componentWillUnmount() {
        const {sheet} = this.props
        const counter = map.get(sheet) - 1
        if (counter) {
          map.set(sheet, counter)
        } else {
          sheet.detach()
          map.delete(sheet)
        }
      }
    
      render() {
        return null
      }
    }
    
    export default Foo 
    

    要记住的一件事。默认情况下,jss 会为类添加一些后缀,以摆脱全局选择器并将它们隔离。一个类看起来像:.example-enter-441163035。如果我们手动设置className 属性,使用这种方法会很舒服,比如:&lt;div className={classes.button}&gt;。所以,或者你必须手动设置转换类,像这样:

    <ReactCSSTransitionGroup
      transitionName={{
        enter: classes.example-enter,
        enterActive: classes.example-enter-active,
        leave: classes.example-leave,
        leaveActive: classes.example-leave-active.
      }}
      transitionEnterTimeout={10}
      transitionLeaveTimeout={600}>
    

    或者您必须在启动工作表时通过将named 选项设置为false 来使用全局选择器(就像我在示例中所做的那样):

    const sheet = jss.createStyleSheet(styles, {named: false})
    

    希望对您有所帮助!不过,看看这个库。这真的很酷,并促进了一种非常有趣的 CSS 方法。

    【讨论】:

    • 能否请你给我一个简短的例子,说明如何使用 jss 做到这一点?
    • 好的,请稍等。
    • 抱歉,我不得不离开,无法发布问题。我明天会回来举个例子。
    猜你喜欢
    • 2017-03-08
    • 1970-01-01
    • 2021-07-17
    • 2018-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-27
    • 2015-03-21
    相关资源
    最近更新 更多