Javascript 混合循环和反应JSX

Javascript 混合循环和反应JSX,javascript,reactjs,Javascript,Reactjs,我对Javascript不熟悉,对此作出反应,并有一个类似的问题: 我正在学习tic-tac-toe教程,并试图理解JSX与循环和数组的混合 我有一个有效的方法: class Board extends React.Component { renderSquare(i) { return ( <Square value={this.props.squares[i]} onClick={() => this.props.onClick

我对Javascript不熟悉,对此作出反应,并有一个类似的问题:

我正在学习tic-tac-toe教程,并试图理解JSX与循环和数组的混合

我有一个有效的方法:

class Board extends React.Component {
  renderSquare(i) {
    return (
      <Square
       value={this.props.squares[i]}
       onClick={() => this.props.onClick(i)}
      />
    )
  }
  renderRow(row) {
    let ss = [];
    for(let i=0; i<3; i++)
    {
      ss.push(this.renderSquare(i+row));
    }
    return (
      <div className="board-row">
      {ss}
      </div>
    )
  }
  renderBoard() {
    let board = []
    for(let i=0; i<3; i++)
    {
      board.push(this.renderRow(i*3));
    }
    return board;

  }
  render() {
    return (
      <div>
        {this.renderBoard()}
      </div>
    )
  }
}
类板扩展React.Component{
renderSquare(一){
返回(
this.props.onClick(i)}
/>
)
}
渲染箭头(世界其他地区){
设ss=[];
对于(设i=0;i确定),请尝试以下方法:

renderBoard() {
  let board = []
  for (let i = 0; i < 3; i++) {
    let inner = []
    for (let j = 0; j < 3; j++) {
      inner.push(this.renderSquare(j + i));
    }
    let row = (
      <div className="board-row">
        {inner}
      </div>
    )
    board.push(row);
  }
  return board;
}
renderBoard(){
让board=[]
for(设i=0;i<3;i++){
让内部=[]
for(设j=0;j<3;j++){
内推(这个渲染正方形(j+i));
}
让行=(
{内部}
)
板。推(排);
}
返回板;
}

注意我必须做的事情,我必须创建一个变量来存储
,而不是推动函数调用,我只是将该
推入
。此外,内部循环使用另一个变量
j
,它替换
renderRow(行)的
输入

电路板组件的较短版本

  class Board extends React.Component {
    render() {
      let row = [];
      const squaresNumbers = Array.apply(null, Array(9)).map((x, i) => i);

      return (
        <div>
          {squaresNumbers.reduce((result, i) => {
            row.push(
              <Square key={i} value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />
            );
            if (row.length === 3) {
              result.push(<div className="board-row">{row}</div>);
              row = [];
            }
            return result;
          })}
        </div>
      );
    }
  }
类板扩展React.Component{
render(){
设row=[];
const squaresNumbers=Array.apply(null,数组(9)).map((x,i)=>i);
返回(
{squaresNumbers.reduce((结果,i)=>{
推(
this.props.onClick(i)}/>
);
if(row.length==3){
result.push({row});
行=[];
}
返回结果;
})}
);
}
}

你经常看到人们通过某种结构来动态创建元素数组。在你的例子中,因为你只有一个平面的正方形列表,而不是一个适当的层次结构,你可以通过临时创建一个来解决问题。然后你实际上不需要所有这些函数

class Board extends React.Component {
    render() {
        const indexes = [[0, 1, 2], [3, 4, 5], [6, 7, 8]];

        return (<div>
            {indexes.map(row =>
                <div class="board-row">
                    {row.map(index =>
                        <Square key={index}
                            value={this.props.squares[index]}
                            onClick={() => this.props.onClick(i)}
                            />
                    )}
                </div>
            )}
        </div>);
    }
}
.board行{
显示器:flex;
}
.广场{
宽度:40px;
高度:40px;
边框:1px纯色灰色;
}

考虑一下:你有一个从0到9的范围,不包括上边界。你想把它重塑成一个3乘3的矩阵。然后,你想把值映射到React组件实例中。让我们编写函数

class Board extends React.Component {
    render() {
        const indexes = [[0, 1, 2], [3, 4, 5], [6, 7, 8]];

        return (<div>
            {indexes.map(row =>
                <div class="board-row">
                    {row.map(index =>
                        <Square key={index}
                            value={this.props.squares[index]}
                            onClick={() => this.props.onClick(i)}
                            />
                    )}
                </div>
            )}
        </div>);
    }
}
首先,一个简单的
range
函数,它只接受一个参数,即上限,并输出从0到该边界的范围,不包括后者:

const range = j => [...Array(j).keys()];
所以

> range(9)
[ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]
你可以查一下为什么它会这样工作,但是现在让我们来考虑一下这个问题的“为什么”。 接下来,一个非常简单的
重塑
函数:

const reshape = (mx, my) => array => range(mx).map(x => range(my).map(y => array[mx * x + y]));
其工作原理如下:

> reshape(3, 3)([1, 2, 3, 4, 5, 6, 7, 8, 9])
[ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
最后,使其呈现:

class Board extends React.Component {
  constructor(props, ...args) {
    super(props, ...args);

    const {
      rows = 3,
      cols = 3,
    } = props;
    const board = reshape(rows, cols)(range(rows * cols));

    this.state = {
      rows,
      cols,
      board,
    };
  }

  render() {
    const { board } = this.state;

    return (
      <div>
        {board.map((row, i) => (
          <div key={i} className="board-row">
            {row.map(cell => (
              <Square
                key={cell}
                value={cell}
                onClick={() => this.props.onClick(cell)}
              />
            ))}
          </div>
        ))}
      </div>
    );
  }
}
类板扩展React.Component{
构造函数(道具,…参数){
超级(道具,…args);
常数{
行=3,
cols=3,
}=道具;
const board=重塑(行,列)(范围(行*列));
此.state={
排,
科尔斯,
董事会,
};
}
render(){
const{board}=this.state;
返回(
{board.map((行,i)=>(
{row.map(单元格=>(
this.props.onClick(cell)}
/>
))}
))}
);
}
}
那里发生了什么事

我们正在做一些函数编程。我们编写了一些不与业务逻辑耦合的小函数。我们使用了“范围”和“重塑”等词,并相应地编写函数,这样几乎每个程序员都不必阅读相应的源代码就能理解这些函数的功能

我们在
重塑
函数中做了一些修改。因为Javascript对变量函数声明不太友好,所以我们使用这个奇怪的
fn()
syntax。我认为需要时间来适应它,因为它的好处是很棒的:您开始编写可重用的小函数,这些函数可以由非常简单的块组成,以创建酷的业务逻辑

我们在这里做了一些假设:

  • range
    函数只接受一个参数
  • reformate
    函数只接受两个参数
  • reformate
    返回的lambda函数需要一个数组,并且语义规定它是平面的
  • 在实例化
    组件(执行其构造函数)后,我们从不更改板配置
其中任何一个都可以单独调整。您可能希望使用lodash的
\u0.range
,可能会使
重塑
功能在边缘情况下更安全一些,诸如此类。这取决于您进行优化


因此,虽然这个答案增加了很多思考的内容,但我确实希望您会发现它很有用。干杯!

不要忘记为数组中的每个元素添加
key
属性,如
this.props.onClick(I)}/>
在这个特定的例子中,我不会试图强迫它成为一些花哨的
for
循环。而且
for
循环在jsx中不起作用,大多数时候我发现它们很难阅读。我尽量避免它们。事实上,我在medi中整天创建react组件时,甚至没有使用过一次嗯大小的项目长达数月。我尽可能使用
map()
(99%的情况下都是如此)。这实际上相当干净。我喜欢它。但无论如何我还是会使用原始版本。它牺牲了一点“不要重复你自己”为了极大地提高可读性。它甚至可能更快。但是如果我决定为了使用循环而做不同的事情,那将是一种方法。