我在React.js中做了这个小游戏:

演示:https://door-game.netlify.com/
App.js文件:https://github.com/Blazej6/Door-game/blob/master/src/App.js

我想在中心按钮中渲染与所选框架匹配的图片。 3个Vue呈现vue,3个反应-反应等。

我如何做到这一点的逻辑?

是否做了一些实验性的方法,例如将颜色类 anchor 放置在应用程序和圈子组件内部,但似乎根本没有读取当前状态(至少不是从当前 Angular 读取),还尝试在链接中实际使用React Router和Encolse圈子组件,但是无论出于何种原因,这确实使CSS搞砸了

真的没有人可以完成任务吗?

最佳答案

对于像这样的简单应用程序,还不需要集成redux / mobx。我推荐的是React中非常常见的东西,即lift your state up

我们可以通过三个步骤完成此操作:

  • 简化CircleoneCircletwoCirclethree组件。他们只需要知道当前 Angular 是多少就可以渲染
  • ClawCircle应该被告知要渲染什么图像(否则为空白)
  • App需要保留所有这些信息的状态(因此,我们已将状态从CircleX提升到其父级App)。

  • 步骤1

    让我们假设通过prop currentAngle向我们提供信息,而不是将currentAngle保持在该状态。当单击一个圆圈时,我们只会告诉创建该圆圈的人,因为他们将向我们传递一个名为onClick的 Prop 。

    由于我们现在不需要跟踪状态,因此我们可以使组件变为无状态,只需将其变成功能组件即可。

    例如,CircleOne可能看起来更像这样:
    const CircleOne = ({ currentAngle, onClick }) => (
      <div
        className="App-logo small-logo"
        alt="logo"
        style={{ transform: `rotateZ(${currentAngle}deg)` }}
        onClick={onClick}
      >
        <div className="little-circle one react">
        {/* ... rest of your divs */}
      </div>
    );
    

    第2步

    接下来,让我们更改ClawCircle,为它提供一个可选的imageClass Prop ,它可以是claw-reactclaw-vue等,也可以只是一个空字符串(也要相应更新css来渲染图像!)。因此,render方法可能会更改为:
    render() {
      const circleStyle = { transform: `rotateZ(${this.props.currentAngle}deg)` };
      return (
        <div
          className={`App-logo claw-circle ${this.props.imageClass}`}
          alt="logo"
          style={circleStyle}
          onClick={this.rotateCircle.bind(this)}
        />
      );
    }
    

    顺便说一下,bind调用可以在构造函数中完成,而不是在render方法中进行,这样,我们不必在每次重新渲染组件时都重新绑定(bind)。
    constructor(props) {
      super(props);
      // constructor code
      this.rotateCircle = this.rotateCircle.bind(this);
    }
    
    // later: onClick={this.rotateCircle}
    

    第三步

    这是更复杂的步骤,因为我们现在必须将繁重的工作委托(delegate)给App而不是各个Circle

    因此,App需要知道每个单独的圆的 Angular ,并处理单击每个圆时发生的情况。此外,当 Angular 改变时,我们要检查三个 Angular 是否相等。如果它们相等,则需要告诉ClawCircle要渲染什么图像。

    总而言之,它可能看起来像这样:

    编辑:在运行该代码之前,我应该尝试运行此代码。这是完整版(经过测试!)只需确保CSS中具有claw-react claw-vueclaw-angular规则
    import React, { Component } from 'react';
    import './App.css';
    import { CSSTransitionGroup } from 'react-transition-group';
    
    class HalfCircle extends Component {
      render() {
        return (
              <div className="App-logo half-circle" alt="logo">
              </div>
        );
      }
    }
    
    const Circleone = ({ currentAngle, onClick }) => (
      <div
        className="App-logo small-logo"
        alt="logo"
        style={{ transform: `rotateZ(${currentAngle}deg` }}
        onClick={onClick}
      >
        <div className="little-circle one react"></div>
        <div className="little-circle two angular"></div>
        <div className="little-circle three vue"></div>
      </div>
    );
    
    
    const Circletwo = ({ currentAngle, onClick }) => (
      <div
        className="App-logo big-logo"
        alt="logo"
        style={{ transform: `rotateZ(${currentAngle}deg` }}
        onClick={onClick}
      >
        <div className="little-circle un react"></div>
        <div className="little-circle dos angular"></div>
        <div className="little-circle tres vue"></div>
      </div>
    );
    
    
    const Circlethree = ({ currentAngle, onClick }) => (
      <div
        className="App-logo biggest-logo"
        alt="logo"
        style={{ transform: `rotateZ(${currentAngle}deg` }}
        onClick={onClick}
      >
        <div className="little-circle ein react"></div>
        <div className="little-circle zwei angular"></div>
        <div className="little-circle drei vue"></div>
      </div>
    );
    
    class ClawCircle extends Component {
      constructor(props){
        super(props)
        this.state = {
          currentAngle: 45,
          anglePerClick: 360,
        }
      }
      rotateCircle() {
        const { currentAngle, anglePerClick } = this.state;
        this.setState({
          currentAngle: currentAngle + anglePerClick
        })
      }
      render() {
        const circleStyle = {
          transform: `rotateZ(${this.state.currentAngle}deg)`
        }
    
        return (
          <div
            className={`App-logo claw-circle ${this.props.imageName}`}
            alt="logo"
            style={circleStyle}
            onClick={this.rotateCircle.bind(this)}
          />
        );
      }
    }
    
    const getNameForAngle = (one, two, three) => {
      if (one === two && one === three) {
        switch(one) {
          case 120:
            return 'claw-react';
          case 240:
            return 'claw-vue';
          case 360:
            return 'claw-angular';
          default:
            return '';
        }
      }
    
      return '';
    };
    
    class App extends Component {
    
      constructor(props) {
        super(props);
    
        this.state = {
          oneAngle: 120,
          twoAngle: 120,
          threeAngle: 120,
        };
    
        this.handleOneClick = this.handleOneClick.bind(this);
        this.handleTwoClick = this.handleTwoClick.bind(this);
        this.handleThreeClick = this.handleThreeClick.bind(this);
      }
    
      handleClick(circle) {
        const nextAngle = this.state[circle] + 120;
        this.setState ({
          [circle]: nextAngle
        });
      }
    
      handleOneClick() {
        this.handleClick('oneAngle');
      }
    
      handleTwoClick() {
        this.handleClick('twoAngle');
      }
    
      handleThreeClick() {
        this.handleClick('threeAngle');
      }
    
      render() {
        const { oneAngle, twoAngle, threeAngle } = this.state;
    
        const imageName = getNameForAngle(oneAngle, twoAngle, threeAngle);
    
        return (
          <div className="App">
            <header className="App-header">
              <Circleone
                currentAngle={oneAngle}
                onClick={this.handleOneClick}
              />
              <Circletwo
                currentAngle={twoAngle}
                onClick={this.handleTwoClick}
              />
              <Circlethree
                currentAngle={threeAngle}
                onClick={this.handleThreeClick}
              />
              <ClawCircle imageName={imageName} />
              <HalfCircle/>
            </header>
          </div>
        );
      }
    }
    
    export default App;
    

    09-25 15:30