我目前正在做我的第一个反应项目。
我已将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>
)
}
}
非常感谢您的帮助。
答案 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传递的事件处理程序。
当您重新设计当前组件时,您可能应该考虑为“窗口”创建组件,以便它们也可以通过状态/道具进行操作,从而成为可重用的组件