1

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

例子:

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

<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在组件内部使用来更改位于transition-durationcss 文件中的值?

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

4

1 回答 1

3

您可以使用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)

样式是在组件外部定义的,然后使用一个高阶组件来包装它并注入样式。在大多数情况下都可以,但是由于我们需要从组件内部添加 css 规则,因此我们需要使用另一种方法。我们需要使用 jss 作为子元素而不是高阶组件。这将允许我们在方法的帮助下从组件中添加规则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手动设置属性,使用这种方法会很舒服,比如:<div className={classes.button}>. 因此,或者您必须手动设置转换类,如下所示:

<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 方法。

于 2016-07-15T17:25:39.277 回答