【问题标题】:Toggling a CSS class when a React.js component gets updated当 React.js 组件更新时切换 CSS 类
【发布时间】:2016-12-05 15:26:31
【问题描述】:

我制作了一个简单的 React.js 有状态组件,显示一个每秒更新一次数字的计数器。我想为此计数器实现滚动效果,每次计数器增加时,新数字都会从顶部向下滚动。 请查看我的pen on Codepen 以了解该项目的外观。我的问题特别涉及您将在柜台右侧看到的数字。您会注意到有两个数字一个在一个之上,接下来要显示的数字(绑定到组件状态)位于当前可见数字的上方。这两个数字都使用 CSS 转换属性定位,现在我想做的是每次新数字增加时在 Y 轴上转换这些数字。这是组件的代码:

var ReactCounter = React.createClass({
newFirstDigit: 0,
currentFirstDigit: 0,
currentSecondDigit: 0,  
scrollFirstDigit: false,

// Set initial state with counter not running
getInitialState: function() {
    return {
        running: false,
        newSecondDigit: 0,
        scrollSecondDigit: false,
    }
},

// Called as soon as Counter is added to the DOM
componentDidMount: function() {
    this.interval = setInterval(this.timeCounter, 1000);
},

// Called as soon as Counter is removed from the DOM
componentWillUnmount: function() {
    clearInterval(this.interval);
},

// Called as soon as Counter is updated
componentDidUpdate: function() {
    if (this.currentSecondDigit != this.state.newSecondDigit) {
        // add scroll class
        this.setState ({
            scrollSecondDigit: true,
        })
        this.currentSecondDigit = this.state.newSecondDigit;
    }

    if (this.currentSecondDigit == this.state.newSecondDigit) {
        // remove scroll class
        this.setState ({
            scrollSecondDigit: false,
        })
    }

    if (this.currentFirstDigit !== this.newFirstDigit) {
        // add scroll class
        this.scrollFirstDigit = true;
        this.currentFirstDigit = this.newFirstDigit;
    }

    if (this.currentFirstDigit === this.newFirstDigit) {
        // remove scroll class
        this.scrollFirstDigit = false;
    }

    if (this.state.newSecondDigit == 10) {
        this.newFirstDigit++;
    }

    if (this.state.newSecondDigit == 10) {
        this.setState({
            newSecondDigit: 0,
        });
        this.currentSecondDigit = 0;
    }

    // Stop and reset counter when it gets to 60
    if (this.newFirstDigit == 6) {
        if (this.state.newSecondDigit == 0) {
            this.setState({ 
                running: false,
                newSecondDigit: 0
            });
            this.newFirstDigit = 0;
            this.currentFirstDigit = 0;
            this.currentSecondDigit = 0;
        }
    }
},

timeCounter: function() {
    if (this.state.running) {
        this.setState({
            newSecondDigit: this.state.newSecondDigit + 1,  
        });
    }
},

startCounter: function() {
    this.setState({ 
      running: true,
      previousTime: Date.now(),
    });
},

stopCounter: function() {
    this.setState({ 
        running: false
    });
},

resetCounter: function() {
    this.setState({
      newSecondDigit: 0,
      previousTime: Date.now(),
    });
    this.newFirstDigit = 0;
    this.currenFirstDigit = 0;
    this.currentSecondDigit = 0;
},

render: function() {
    var scrollFirstDigit = this.scrollFirstDigit === true ? 'scroll' : '';
    var scrollSecondDigit = this.state.scrollSecondDigit === true ? 'scroll' : '';

    return (
        <div className="counter-container">
            <div className="numbers-container">
                <div className="number-container one">
                    <div className={"number current " + scrollFirstDigit}>
                        {this.newFirstDigit}
                    </div>
                    <div className={"number previous " + scrollFirstDigit}>
                        {this.currentFirstDigit}
                    </div>
                </div>
                <div className="number-container two">
                    <div className={"number current " + scrollSecondDigit}>
                        {this.state.newSecondDigit}
                    </div>
                    <div className={"number previous " + scrollSecondDigit}>
                        {this.currentSecondDigit}
                    </div>
                </div>
            </div>
            <div className="buttons-container">
                {this.state.running ? <button className="btn stop" onClick={this.stopCounter}>Stop</button> : <button className="btn start" onClick={this.startCounter}>Start</button> }
                <button className="btn reset" onClick={this.resetCounter}>Reset</button>
            </div>
        </div>
    ); 
}

})

ReactDOM.render( <ReactCounter />, document.getElementById('app-container') );

您会看到我正在尝试在 componentDidUpdate 方法中添加和删除 CSS 类。我也在 componentWillUpdate 方法中尝试过,但是两种解决方案都不能正常工作。您认为实现所需滚动效果的最佳方式是什么?

【问题讨论】:

  • 你看过类名节点模块吗?它允许您根据指定的条件切换类。

标签: javascript animation reactjs translation counter


【解决方案1】:

根据我的理解,您希望根据您创建的 scrollFirstDigitscrollSecondDigit 变量更改 CSS 类(将 scroll 类添加到类列表中)。在 React 中,我经常使用 classnames 模块来做这样的事情。例如,您可能对以下内容感兴趣:

var classnames = require('classnames');
...
<div className={classnames({ 'number current': true, 'scroll': this.state.scrollFirstDigit === true})}>;

因此,您可以通过更改状态对象来简单地切换所需的 CSS 类(因为它会触发重新渲染并导致重新评估类)。 您可以在模块github 页面查看更多示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-05
    • 2021-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多