React-使用三元将CSS类应用于功能组件

时间:2018-09-19 19:53:52

标签: css reactjs classname ternary react-props

我对React还是比较陌生的,他正在开发John Conway-Life of Life应用程序。我为板子本身构建了Gameboard.js功能组件(是App.js的子组件),并为板子中的单个正方形构建了Square.js功能组件(并且是{ GameboardApp的孙代。)

App中,我有一个名为alive的函数,当用户单击它时,我想更改单个正方形的颜色。 App还具有一个“活动”属性,其状态最初设置为false,而alive会在调用时将该属性更改为true。

这里是App.js

import React, { Component } from 'react';
import './App.css';
import GameBoard from './GameBoard.js';
import Controls from './Controls.js';

    class App extends Component {
      constructor(props){
        super(props);

        this.state = {
          boardHeight: 50,
          boardWidth: 30,
          iterations: 10,
          reset: false,
          alive: false
        };
      }

      selectBoardSize = (width, height) => {
        this.setState({
          boardHeight: height,
          boardWidth: width
        });
      }

      onReset = () => {

      }

      alive = () => {
        this.setState({ alive: !this.state.alive });
        console.log('Alive function has been called');

      }



      render() {
        return (
          <div className="container">
            <h1>Conway's Game of Life</h1>

          <GameBoard
            height={this.state.boardHeight}
            width={this.state.boardWidth}
            alive={this.alive}
          />

            <Controls
              selectBoardSize={this.selectBoardSize}
              iterations={this.state.iterations}
              onReset={this.onReset}
            />

          </div>
        );
      }
    }

    export default App;

Gameboard看起来像这样,并将props.alive传递给Square

import React, { Component } from 'react';
import Square from './Square.js';

const GameBoard = (props) => {
    return (
      <div>
        <table className="game-board">
          <tbody>
            {Array(props.height).fill(1).map((el, i) => {
              return (
                <tr key={i}>
                  {Array(props.width).fill(1).map((el, j) => {
                    return (
                      <Square key={j} alive={props.alive}/>
                    );
                  })}
                </tr>
              );
            })}
          </tbody>
         </table>
      </div>
    );
}

export default GameBoard;

在我的CSS中,有一个名为active的类,如果单击该正方形,它将更改单个正方形的颜色。我该如何做才能在Square中单击td元素,从而改变颜色(即CSS类变为活动状态)?

我已经尝试过了:

import React, { Component } from 'react';

const Square = (props) => {

  return(
    <td className={props.alive ? "active" : "inactive"} onClick={() => props.alive()}></td>
  );
}

export default Square;

CSS看起来像这样:

.Square {
  background-color: #013243; //#24252a;
  height: 12px;
  width: 12px;
  border: .1px solid rgba(236, 236, 236, .5);
  overflow: none;

  &:hover {
    background-color: #48dbfb; //#00e640; //#2ecc71; //#39FF14;
  }
}

.inactive {
  background-color: #013243; //#24252a;
}

.active {
  background-color:  #48dbfb;
}

我该如何做,.Square CSS类始终应用于每个正方形,但是如果激活,则单个正方形的颜色会更改?换句话说,我是否可以将Square的td设置为始终使用.Square CSS类设置样式,然后根据Square是否为alive中的各个元素进行适当的着色在App的状态下为真?

是否存在三元方法来始终设置一个特定的CSS类,然后再设置2个其他类中的1个。会始终显示Square CSS类,并根据逻辑/状态来呈现活动或不活动状态?

3 个答案:

答案 0 :(得分:2)

评论的想法正确。

您可以使用template literal并在其中嵌入三元条件:

return (
    <td
      className={`Square ${props.alive ? "active" : "inactive"}`}
      onClick={() => props.alive()}
    ></td>
);

快速刷新模板文字:使用反引号将字符串包装起来,然后可以通过将其包装在${}模式中来在其中插入JavaScript表达式。另外,模板文字可以跨越多行,因此不再需要笨拙的字符串连接!

const myName = "Abraham Lincoln";
const myString = `Some text.
  This text is on the next line but still in the literal.
  Newlines are just fine.
  Hello, my name is ${myName}.`;

编辑:我现在看到的更大的问题是,您没有将每个单元的状态存储在任何地方。您仅在App中存储了一个布尔值,称为alive。您真正需要的是布尔值的 array ,每个布尔值代表单个{{ 1}}。

遵循"the data flows down"的React原则,“有效”状态的数组应位于SquareApp中。在您的情况下,您可以尝试将其保留在GameBoard中,这样AppGameBoard可以保留为纯功能组件。

Square内,您可以在构造函数中创建一个新的二维数组App,并使用board值的子数组来填充它:

0

// App.js constructor(props){ super(props); this.state = { boardHeight: 50, boardWidth: 30, board: [], iterations: 10, reset: false, }; this.state.board = new Array(this.state.boardHeight).fill(new Array(this.state.boardWidth).fill(0)); } 数组中,每个索引代表一行。因此,board的简化示例表示为:

[[0, 0, 1], [0, 1, 0], [1, 1, 1]]

0 0 1 0 1 0 1 1 1 应该仅基于传递给它的GameBoard道具来呈现单元格网格,并将每个board的活动值和回调函数作为道具传递:

Square

从那里您应该能够看到该应用程序的工作方式。 const GameBoard = (props) => { return ( <div> <table className="game-board"> <tbody> {this.props.board.map((row, y) => { return <tr key={y}> {row.map((ea, x) => { return ( <Square key={x} x={x} y={y} isAlive={ea} aliveCallback={this.props.alive} /> ); })} </tr>; })} </tbody> </table> </div> ); } 存储游戏状态并呈现功能组件App。在GameBoard中,每个GameBoard都会根据其活动值进行渲染,并在单击时触发一个Square。 {p}应当根据其aliveCallbackaliveCallback属性在board内部的App数组中设置适当值的状态。

答案 1 :(得分:0)

您可以喜欢

return(
    <td className={`Square ${props.alive ? "active" : "inactive"}`} 
       onClick={() => props.alive()}>
    </td>
  );

请参阅此code

答案 2 :(得分:0)

标题问题不是“无法正常工作”的真正原因

注意:此声明

  

className = {props.alive吗? “ active”:“ inactive”}

是正确的,不需要使用模板文字。

您可以通过多种方式编写/使用它:

className={'Square '+ (props.alive ? 'active' : 'inactive')}

说实话,由于“正方形”具有相同的背景色,因此无需使用“无效”。

className={'Square '+ (props.alive ? 'active' : null)}

事实上不需要三元运算符

className={'square '+ (props.alive && 'active')}

当然,您可以在返回之前用普通js'计算/准备'值

const Square = (props) => {
  let classes = ['Square','bb']
  if( props.alive ) classes.push('active')
  classes = classes.join(' ')
  return (
    <h1 className={classes}>Hello</h1>
  )};

只需阅读docs或Google,即可了解“在js中反应CSS”。