添加和删​​除类以激活react中的关键帧

时间:2018-11-27 23:19:01

标签: javascript css reactjs

我目前正在做我的第一个反应项目。

我已将onClick事件放置到其中一个元素上。该元素恰好是一个按钮。我要实现的是在过渡过程中将图像从不透明度变为0,以确认用户已成功添加输入。通过下面的关键帧进行设置

#showTick {
    width: 30%;
    opacity: 0;
}

.activateKF {
    animation: showTick 0.7s;
}

@keyframes showTick {
    0% {opacity: 0;}
    25% {opacity: 0.5;}
    50% {opacity: 1;}
    75% {opacity: 0.5;}
    100% {opacity: 0;}
}

showtick样式是元素的默认样式。当用户单击按钮时,我想将.activateKF类添加到#showTick元素中。我正在使用以下代码进行此操作。

goalCreation=()=>{
    document.getElementById("showTick").classList.remove("activateKF"); 
    let goal = document.getElementById("enterGoal").value;
    if (goal.length < 1){
        return false;
    } else {
        document.getElementById("showTick").classList.add("activateKF");            
        this.props.submitGoal(goal);
    }
}

我试图在同一函数中删除该类,以便每当用户单击该类时,可以在单击事件中再次将关键帧添加到该元素-并且可以进行动画处理。但是,我发现它只能在第一次使用。

即使我删除了删除类的行,它仍然只能在第一次使用。我不知道为什么吗?

请有人帮忙,以便每当用户单击按钮时,关键帧每次都变为活动状态?

更新:我的代码中已经包含了这个实际的react组件

import React, { Component } from 'react';
import '../Styles/creategoal.css';
import specificGoal from '../Images/specificgoal.png';
import cost from '../Images/cost.png';
import tick from '../Images/greentick.jpg';
import '../Styles/creategoal.css';
import '../App.css';

export default class CreateGoal extends Component {
    constructor(props){
        super(props);
        this.state = {
            showCostDiv: false,
            showSpecificDiv: false
        }
    }

    goalCreation=()=>{
        let goal = document.getElementById("enterGoal").value;
        if (goal.length < 1){
            return false;
        } else {
            document.getElementById("showTick").classList.add("activateKF");            
            this.props.submitGoal(goal);
        }
    }

    closeHelp=(e)=>{
        let currentClicked = e.target.tagName;
        if (this.state.showCostDiv && currentClicked !== "SECTION"){
            this.setState({
                showCostDiv: false
            })
        if (this.state.showSpecificDiv && currentClicked !== "SECTION"){
            this.setState({
                showSpecificDiv: false
            })
        }
        }
    }

    openSpecificWindow=()=>{
        this.setState({
            showSpecificDiv: true
        })
    }

    closeSpecificWindow=()=>{
        this.setState({
            showSpecificDiv: false
        })
    }

    openCostWindow=()=>{
        this.setState({
            showCostDiv: true
        })
    }

    closeCostWindow=()=>{
        this.setState({
            showCostDiv: false
        })
    }

    render(){

        let specificDivStatus = "hideContent";
        let costDivStatus = "hideContent";

        if (this.state.showSpecificDiv){
            specificDivStatus = "showContent";
        }

        if (this.state.showCostDiv){
            costDivStatus = "showContent";
        }

        return (
        <div onClick={this.closeHelp} className="createGoal">

            <div id="banner" className="goalSetBanner">
                <h1>SET YOUR GOAL</h1>
            </div>
            <span className="goalTip">Consider the following when setting your goal:</span>

            <section id="BeSpecificHelp" className={specificDivStatus}>
                <p>Describe exactly what your goal is, and when its possible use numbers to make it measurable. This excercise will turn your idea or dream
                even closer to reality.</p>
                <br/>
                <p>Examples:</p>

                <p><span className="incorrect">Wrong:</span> Weight loss.<br/>
                <span className="correct">Right:</span> Losing 8Kg.</p>

                <p><span className="incorrect">Wrong:</span> Read more books.<br/>
                <span className="correct">Right:</span> Read a new book every 15 days.</p>

                <p><span className="incorrect">Wrong:</span> Buying a house.<br/>
                <span className="correct">Right:</span> Buying a house within two bedrooms in a given address.</p>

                <span id="closeWindowSpecific" onClick={this.closeSpecificWindow}>Close</span>              
            </section>

            <section id="considerCostHelp" className={costDivStatus}>
                <p>Do not focus only on the result you will get.</p>
                <p><strong>Your time and energy are limited resources</strong></p>

                <p>Reflect on what it will take you to achieve this goal.</p> 

                <p>Finish completing it if you are willing to pay the price.</p>

                <span id="closeWindowCost" onClick={this.closeCostWindow}>Close</span>              
            </section>

            <main className="setGoalInfo">
                <div id="beSpecificGoal" className="considerGoal">
                    <img src={specificGoal} alt="Specific Goal" />
                    <span className="goalHelp">Be as specific as possible</span>
                    <span id="beSpecificLink" onClick={this.openSpecificWindow} className="link-span">TAP FOR MORE INFO</span>
                </div>
                <div id="considerCost" className="considerGoal">
                    <img src={cost} alt="Cost of Goal" />
                    <span className="goalHelp">What will it cost you?</span>
                    <span id="considerCost" onClick={this.openCostWindow} className="link-span">TAP FOR MORE INFO</span>
                </div>
            </main>

            <div id="goalAdded">
                <img src={tick} id="showTick" alt="Goal Added" />
            </div>

            <div className="inputDiv">
                <input type="text" id="enterGoal" placeholder="What is your goal?"></input>
            </div>

            <button onClick={this.goalCreation} id="createGoal">CREATE MY GOAL</button>

        </div>
            )
    }
}

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

React的基本规则是您不直接操作DOM。 React将在渲染时构建一个虚拟DOM并仅替换它检测到的DOM片段已更改。如果您在React渲染周期之外操作DOM,则它可能无法按预期工作。

在react组件上使用id属性也不是一个好主意。首先,它降低了组件的可重用性(ID在整个页面中应该是唯一的),而react也将在DOM中呈现其自己的ID。

在React中,您可以使用ref语句,该语句是包含null(在卸载时)或项目被装入后的元素的函数,但是,此语句可能不是您所需要的在这里(当您从输入中读取值时,宁愿使用它。)

可能您只想使用React animation之类的东西,或者只想根据本地组件状态添加一个类。

通过查看当前的整体代码,您可以看到您还没有经常进行反应。您有大量的硬编码数据,并且有很多重复的概念。

实现当前目标的一种方法是实施类似以下的内容:

const { classNames } = window;
const { Component } = React;

class CheckableButton extends Component {
  constructor() {
    super();
    this.state = {
      submitted: false
    };
    this.handleSubmit = this.handleSubmit.bind( this );
  }
  componentDidUpdate() {
    const { submitted } = this.state;
    if (submitted) {
      // trigger submitted to be cleared
      this.resetTimer = setTimeout( () => this.setState( { submitted: false } ), 700 );
    }
  }
  componentWillUnmount() {
    // make sure the state doesn't get manipulated when the component got unmounted
    clearTimeout( this.resetTimer );
  }
  handleSubmit() {
    // set the submitted state to true
    this.setState( { submitted: true } );
  }
  render() {
    const { submitted } = this.state;
    const { title } = this.props;
    return (
      <button 
        type="button" 
        className={ classNames( 'checkable', { 'checked': submitted } ) } 
        onClick={ this.handleSubmit }>{ title }</button>
    );
  }
}

ReactDOM.render( 
  <CheckableButton title="Create goal" />, document.getElementById('container') );
button.checkable {
  padding-left: 5px;
  padding-top: 5px;
  padding-bottom: 5px;
  padding-right: 5px;
}
.checkable::before {
  display: inline-block;
  width: 20px;
  content: ' ';
  padding-right: 5px;
}
.checkable.checked::before {
  content: '✓';
  color: darkgreen;
  padding-right: 5px;
  font-weight: bold;
  opacity: 0;
  animation: showTick 0.7s;
}

@keyframes showTick {
  0% {opacity: 0;}
  25% {opacity: 0.5;}
  50% {opacity: 1;}
  75% {opacity: 0.5;}
  100% {opacity: 0;}
}
<script id="react" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.2/react.js"></script>
<script id="react-dom" src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/15.6.2/react-dom.js"></script>
<script id="classnames" src="https://cdnjs.cloudflare.com/ajax/libs/classnames/2.2.5/index.js"></script>
<div id="container"></div>

在组件中看到的逻辑主要基于反应生命周期事件。单击按钮后,状态将更改为已提交,这将依次触发componentDidUpdate,您可以在此检查已提交标志是否设置为true。完成后,您可以在setTimeout上创建回调以再次删除已提交的标志。

当然可以操纵handleSubmit函数来调用通过props传递的事件处理程序。

当您重新设计当前组件时,您可能应该考虑为“窗口”创建组件,以便它们也可以通过状态/道具进行操作,从而成为可重用的组件