React - 使用循环创建嵌套组件
React - Create nested components with loops
我对 React 有一点疑问。我无法使用 for 循环创建嵌套组件。我想要做的是创建一个 table 的 9 个单元格,然后创建 3 行,每行 3 个单元格,然后将 3 行安装在一起并创建一个 9x9.
板
假设我想得到这样的东西,但是使用循环
class Board extends React.Component {
renderSquare(i) {
return <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />;
}
render(){
return(
<div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}
我搜索了其他人的问题几个小时,我认为我的代码几乎是正确的,但它没有呈现我想要的。我只得到一个白页。
这是我的代码:
class Board extends React.Component {
renderSquare(i) {
return <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />;
}
createCells(i){
if(i%3){return;}
var index = this.fillN(Array(i)); //index=[0,1,2,3,4,5,6,7,8]
var cells = [];
index.forEach(function(i){
cells.push(() => {
return(
<div>
{this.renderSquare(i)}
</div>
);
});
});
return cells;
}
createRows(cells){
var index = this.fillMod3(Array(3)); //index=[0,3,6]
var rows = []
index.forEach(function(i){
rows.push(() => {
return(
<div>
{cells[i]}
{cells[i+1]}
{cells[i+2]}
</div>
);
});
});
return rows;
}
render(){
var cells = this.createCells(9);
var rows = this.createRows(cells);
var board = [];
var index = this.fillN(Array(1));
index.forEach(function(row){
board.push(() => {
return(
<div>{row}</div>
);
});
})
return(
<div>
{board[0]}
</div>
);
}
我总是在屏幕上看到这样的内容:
<Board>
<div> /*empty*/ </div>
</Board>
我想澄清一下,我确定与该组件(板)交互的其余代码没有问题。
我是 React 的新手,如果有人能帮助我,我将不胜感激。
抱歉我的英语不好
编辑1:
按照 marklew 示例,我应该可以做这样的事情
render(){
var index1 = this.fillN(Array(3)); //index1=[0,1,2]
var index2 = this.fillN(Array(3)); //index2=[0,1,2]
return(
<div>
{index1.map((e1,i1) => {
return(
<div key={i1} className="board-row">
{index2.map((e2, i2) => {
return(
<p key={i2+10}>
{this.renderSquare(i2)}
</p>
)
})}
</div>
)
})}
</div>
);
}
但它不符合我的要求。我只获得一个包含 9 个单元格的列,并且这些单元格是相同的对象。我不明白为什么。 (我知道它们是相同的对象,因为我在创建它们时分配了一个句柄函数 onClick:
<Board
onClick={(i) => this.handleClick(i)} //handleClick just draws a X in the cell
/>
我同时在 3 个单元格中得到 X 淹死
编辑2:
我找到了解决方案:
render(){
var index1 = this.fillMod3(Array(3));
return(
<div>
{index1.map((e,i) => {
return(
<div key={i} className="board-row">
{this.renderSquare(e)}
{this.renderSquare(e+1)}
{this.renderSquare(e+2)}
</div>
)
})}
</div>
);
}
}
但这不是我想要的。即使是实习生 renderSquare(i) 函数,我也想要另一个循环。
要在 JSX 中呈现元素列表,您可以这样做:
render() {
return <div>
{
[1,2,3].map ( (n) => {
return this.renderSquare(n)
})
}
</div>;
}
只需将组件数组包装到 JSX 中的 {}
即可。
澄清一下,这与以下逻辑相同:
return <div>
{
[
<h1 key="1">Hello 1</h1>,
<h1 key="2">Hello 2</h1>,
<h1 key="3">Hello 3</h1>
]
}
</div>;
请注意,每次渲染组件数组时,都必须提供一个 key
道具,如 here 所指。
此外,如果您只想在渲染函数中打印行值,您应该替换:
index.forEach(function(row){
board.push(() => {
return(
<div>{row}</div>
);
});
})
与:
index.forEach( (row, index) => {
board.push(<div key={index}>{row}</div>)
})
或者,将 forEach
和 push
替换为 map
:
board = index.map( (row, index) => <div key={index}>{row}</div> )
编辑 我使用您的代码作为基础创建了一个带有 9x9 板的 fiddle:https://jsfiddle.net/mrlew/cLbyyL27/(您可以单击单元格以 select它)
您正在将函数推送到 board
数组。如果你想渲染它们,你必须像
这样调用这些函数
{board[0]()}
我准备了一个例子来解决你的问题:http://jsbin.com/hofohiy/edit?js,output
我看到你也在做 JS React 教程!这是我所做的,但我正在努力解决这个问题,因为必须有一种好的方法来提供这些单独的密钥中的每一个。
我 运行 遇到了与你 运行 相同的问题,其中 X 被绘制成 3 个正方形,发生这种情况的原因是因为当你渲染正方形时,一些 "i's" 被复制了。例如,有多个 "i" 为 2 的正方形(至少在我的问题中是这样)。
所以每个Square都有一个索引吧? [0,1,2,3,4,5,6,7,8].
首先,我们需要找到它们之间的关联方式,以便我们可以将它们呈现为行!因此,在您的示例中,您有 index1 和 index2,我假设它们指的是棋盘中正方形的 x 和 y 坐标。重写上面的数组我们得出:[{0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {2,1}, {0, 2}, {1,2}, {2,2}] 使用 {x,y} 格式。我们如何使用这些值(我们将从您的 index1 和 index2 中获取这些值,以获取我们以 [0,1,2,3,4,5,6,7,8] 开头的原始值数组?
我做的是 3 * x + y(或者在一个循环中,3 * i + j)。这样每个方块都有一个与之相关联的唯一 "i" 值。
设置循环后,我使用 SO post 正确地 return 我从一个单独的函数创建的元素(为了保持我的代码更清晰,这是一次糟糕的尝试) .
这就是我最终得到的结果,但我需要确保正确设置密钥,这实际上是我偶然发现的 post:
createSquares() {
let rows = [];
for(var i = 0; i < 3; i++){
let squares = [];
for(var j = 0; j < 3; j++){
squares.push(this.renderSquare(3*i+j));
}
rows.push(<div className="board-row">{squares}</div>);
}
return rows;
}
然后我在 Board 中的渲染函数如下所示:
render() {
return (
<div>
{this.createSquares()}
</div>
);
}
这是我在阅读此处和 React JSX 中的循环后能想到的最佳答案
:
render() {
return (
<div>
{
[...Array(3)].map((_, i) => (
<div key={i} className="board-row">
{
[...Array(3)].map((_, j) => this.renderSquare(3 * i + j))
}
</div>
))
}
</div>
);
}
P.S。我也在新 React Tutorial 中进行挑战。 =p
我也在研究 React 教程。感谢您的回复。我找到了这个解决方案:
render() {
const rows = [];
for(let i = 0; i<9; i=i+3) {
const oneRow = [];
for(let j = i; j < i+3; j++) {
oneRow.push(this.renderSquare(j, j))
}
rows.push(<div className="board-row" key={i + 'someId'}>{oneRow}</div>)
}
return (
<div>
{rows}
</div>
);
}
我将 renderSquare 更改为为 Square 组件设置一个键作为第二个参数。
renderSquare(i, key) {
return (
<Square
value={this.props.squares[i]}
onClick={() => this.props.onClick(i)}
key={key}
/>
);
}
Live demo on codepen
render()
函数中的嵌套循环
(评论中的解释:)
class Board extends React.Component {
renderSquare(i) {
return (
<Square
value={this.props.squares[i]}
key={i}
onClick={() => this.props.onClick(i)}
/>
);
}
render() {
var self = this;
return (
<div>
// you can use: [...Array(3)] instead of [1,2,3]
{[1, 2, 3].map(function(row, rowIdx) { // create rows
return (
<div className="board-row" key={rowIdx}>
{
// you can use: [...Array(3)] instead of [1,2,3]
[1, 2, 3].map((col, colIdx) => { // create columns
return self.renderSquare((3 * rowIdx) + colIdx); // calculate square index
})
}
</div>
);
})}
</div>
);
}
}
这应该可以解决您面临的问题。
这甚至为实习生 renderSquare(i) 函数添加了另一个循环。
它可以满足您的需求,即为井字游戏显示 3 列和 3 个单元格。
render() {
let count = 0;
const index = [1, 2, 3];
return (
<div>
{index.map((v, i) => {
return (
<div key={i} className="board-row">
{index.map((v2, i2) => {
return this.renderSquare(count++);
})}
</div>
);
})}
</div>
);
}
第一个方案:
import React from 'react';
import Square from './Square';
export default
class Board extends React.Component {
render() {
const board2 = [];
for (let i = 0; i < 3; i++) {
const s = [];
for (let k = 0; k < 3; k++) {
s[k] = <Square
key ={3*i+k}
value ={this.props.squares[3*i+k]}
onClick ={()=>this.props.onClick(3*i+k)}
/>;
}
board2[i] = <div className="board-row" key={i}>{s}</div>;
}
///////////////////////////////////////
return (
<div>{board2}</div>
);
}
}
第二种方案:
import React from 'react';
import Square from './Square';
export default
class Board extends React.Component {
render() {
let board =Array(3).fill(null);
let square =Array(3).fill(null);
const x = board.map((b,bIndex)=>{
return<div className="board-row" key={bIndex}>
{
square.map((s, sIndex)=>{
return <Square
key ={3*bIndex+sIndex}
value ={this.props.squares[3*bIndex+sIndex]}
onClick ={()=>this.props.onClick(3*bIndex+sIndex)}
/>;
})
}
</div>;
});
///////////////////////////////////////
return (
<div>{x}</div>
);
}
}
正方形:
import React from 'react';
export default
function Square(props) {
console.log('square render')
return (
<button className="square" onClick={props.onClick}>
{props.value}
</button>
);
}
我假设您正在查看 React Tutorial 示例。正如说明明确指出的那样,我们的想法是创建两个循环,而不仅仅是一个。
本例中的第一个循环创建了 3 行。第二个嵌套循环创建了 3 个必要的列,通过 renderSquare 函数为每个位置返回一个 Square。您可能会注意到,我使用了两个循环的索引来正确地将相应的索引分配给正方形。
return (
<div>
{[0,1,2].map(i => {
return (
<div className="board-row">
{[0,1,2].map(j => {
return this.renderSquare(3*i + j)
})}
</div>
);
})}
</div>
);
class Board extends React.Component {
renderSquare(i) {
return (<Square key={i} value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />);
}
render() {
let board = [];
for(let x = 0; x<3; x++){
let lis =[];
for(let y = 0; y<3; y++){
lis.push(this.renderSquare(3*x + y));
}
board.push(<div key={x}>{lis}</div>)
}
return (
<div>
{board}
</div>
);
}
}
我的解决方案是:
class Board extends React.Component {
//range is a Sequence generator function
//Array.from(arrayLike[, mapFn [, thisArg]]).
//arrayLike - An array-like or iterable object to convert to an array
//mapFn - Map function to call on every element of the array
//thisArg - Value to use as this when executing mapFn
//range(0, 4, 1); => [0, 1, 2, 3, 4]
range = (start, stop, step) => Array.from(
{ length: (stop - start)/step +1 },
(_, i) => start + (i * step)
);
renderSquare(i) {
return <Square
key={i}
value={this.props.squares[i]}
onClickChange={() => this.props.onClickChange(i)}
/>;
}
render() {
let row = 3;
let col = 3;
return (
<div>
{
//This generates an Array of [0, 3, 6] if row = 3 and col = 3
// n is the element and i is the index of the element, i starts at 0
this.range(0, row * col - 1, col).map( (n, i) => {
return (
<div key={i} className="board-row">
{
this.range(n, (i + 1) * col - 1, 1).map( (n, i) => {
return this.renderSquare(n)
})
}
</div>
)
})
}
</div>
);
}
此代码段使用 map 的方式类似于我们定义嵌套循环的方式。
const buildBoard = [0, 1, 2].map((row) => {
return (
<div className='board-row' key={row}>
{[0, 1, 2].map((col) => {
return this.renderSquare(row * 3 + col);
})}
</div>
);
});
return <div id='Board Container'>{buildBoard}</div>;
更改了教程中 Board 的代码以反映为
class Board extends React.Component {
constructor(props) {
super(props);
this.rows = Array(3).fill(null);
}
renderSquare(i) {
return (<Square
key={i}
value={this.props.squares[i]}
onClick={() => this.props.onClick(i)}
/>);
}
renderRow(row) {
return (
<div key={row} className="board-row">
{this.rows.map((x, col) => this.renderSquare(3*row+col))}
</div>
);
}
render() {
return (
<div>
{this.rows.map((x, rowIndex) => this.renderRow(rowIndex))}
</div>
);
}
}
这是我的解决方案。可能会有帮助。
renderSquare(i) {
return (
<Square
key={i}
value={this.props.squares[i]}
onClick={() => this.props.onClick(i)}
/>
);
}
render() {
let rows = [];
for (let i = 0; i <= 2; i++) {
let children = []
for (let j = i * 3; j <= i * 3 + 2; j++) {
children.push(this.renderSquare(j))
}
rows.push(
<div key={i} className="board-row">
{children}
</div>
)
}
return (
<div>
{rows}
</div>
);
}
上面提供数组的答案,破坏了循环的目的;这不是很漂亮,但话又说回来,React with JSX 也不是:
class Board extends React.Component {
render() {
let board=[];
for(let row=0;row<9;row+=3) {
let cols=[];
for(let col=0;col<3;col++) {
let i=col+row;
cols.push(<Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)}/>)
}
board.push(
<div className="board-row">
{cols}
</div>
);
}
return (
<div>
{board}
</div>
);
}
}
嗯,我觉得现在更简单了,因为我刚刚做了
export default function Board(props){
return(
<div id = "board">
{createBoard(3, 3)}
</div>
)
}
function Square(props){
return(
<div className = "boardSquare" style = {{
gridColumn: props.x,
gridRow: props.y}}>
</div>
)
}
function createBoard(x, y){
// x and y being the max "cells" my board will have
let grid = [];
for(let i = 0; i < x; i++){
for(let u = 0; u < y; u++){
grid.push(<Square x = {i + 1} y = {u + 1} key = {`x${i+1}y${u+1}`}/>);
}
}
return grid;
}
它完全符合我的要求,所以是的,只需返回一个数组就解决了我的问题,我希望我的回答对某人有用。
只是为了笑笑,这里有一个最近的工作示例作为函数组件
import React from "react";
import Square from "./Square";
import "./Board.css";
export default function Board(props) {
function renderSquare(i) {
return (
<Square
key={i}
value={props.squares[i]}
onClick={() => props.onClick(i)}
/>
);
}
return (
<div className="board-wrapper">
{
[...Array(3).keys()].map( row => (
<div key={row} className="board-row">
{
[...Array(3).keys()].map( col => renderSquare((row * 3) + col))
}
</div>
)
)
}
</div>
)
}
我对 React 有一点疑问。我无法使用 for 循环创建嵌套组件。我想要做的是创建一个 table 的 9 个单元格,然后创建 3 行,每行 3 个单元格,然后将 3 行安装在一起并创建一个 9x9.
板假设我想得到这样的东西,但是使用循环
class Board extends React.Component {
renderSquare(i) {
return <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />;
}
render(){
return(
<div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}
我搜索了其他人的问题几个小时,我认为我的代码几乎是正确的,但它没有呈现我想要的。我只得到一个白页。
这是我的代码:
class Board extends React.Component {
renderSquare(i) {
return <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />;
}
createCells(i){
if(i%3){return;}
var index = this.fillN(Array(i)); //index=[0,1,2,3,4,5,6,7,8]
var cells = [];
index.forEach(function(i){
cells.push(() => {
return(
<div>
{this.renderSquare(i)}
</div>
);
});
});
return cells;
}
createRows(cells){
var index = this.fillMod3(Array(3)); //index=[0,3,6]
var rows = []
index.forEach(function(i){
rows.push(() => {
return(
<div>
{cells[i]}
{cells[i+1]}
{cells[i+2]}
</div>
);
});
});
return rows;
}
render(){
var cells = this.createCells(9);
var rows = this.createRows(cells);
var board = [];
var index = this.fillN(Array(1));
index.forEach(function(row){
board.push(() => {
return(
<div>{row}</div>
);
});
})
return(
<div>
{board[0]}
</div>
);
}
我总是在屏幕上看到这样的内容:
<Board>
<div> /*empty*/ </div>
</Board>
我想澄清一下,我确定与该组件(板)交互的其余代码没有问题。
我是 React 的新手,如果有人能帮助我,我将不胜感激。 抱歉我的英语不好
编辑1: 按照 marklew 示例,我应该可以做这样的事情
render(){
var index1 = this.fillN(Array(3)); //index1=[0,1,2]
var index2 = this.fillN(Array(3)); //index2=[0,1,2]
return(
<div>
{index1.map((e1,i1) => {
return(
<div key={i1} className="board-row">
{index2.map((e2, i2) => {
return(
<p key={i2+10}>
{this.renderSquare(i2)}
</p>
)
})}
</div>
)
})}
</div>
);
}
但它不符合我的要求。我只获得一个包含 9 个单元格的列,并且这些单元格是相同的对象。我不明白为什么。 (我知道它们是相同的对象,因为我在创建它们时分配了一个句柄函数 onClick:
<Board
onClick={(i) => this.handleClick(i)} //handleClick just draws a X in the cell
/>
我同时在 3 个单元格中得到 X 淹死
编辑2: 我找到了解决方案:
render(){
var index1 = this.fillMod3(Array(3));
return(
<div>
{index1.map((e,i) => {
return(
<div key={i} className="board-row">
{this.renderSquare(e)}
{this.renderSquare(e+1)}
{this.renderSquare(e+2)}
</div>
)
})}
</div>
);
}
}
但这不是我想要的。即使是实习生 renderSquare(i) 函数,我也想要另一个循环。
要在 JSX 中呈现元素列表,您可以这样做:
render() {
return <div>
{
[1,2,3].map ( (n) => {
return this.renderSquare(n)
})
}
</div>;
}
只需将组件数组包装到 JSX 中的 {}
即可。
澄清一下,这与以下逻辑相同:
return <div>
{
[
<h1 key="1">Hello 1</h1>,
<h1 key="2">Hello 2</h1>,
<h1 key="3">Hello 3</h1>
]
}
</div>;
请注意,每次渲染组件数组时,都必须提供一个 key
道具,如 here 所指。
此外,如果您只想在渲染函数中打印行值,您应该替换:
index.forEach(function(row){
board.push(() => {
return(
<div>{row}</div>
);
});
})
与:
index.forEach( (row, index) => {
board.push(<div key={index}>{row}</div>)
})
或者,将 forEach
和 push
替换为 map
:
board = index.map( (row, index) => <div key={index}>{row}</div> )
编辑 我使用您的代码作为基础创建了一个带有 9x9 板的 fiddle:https://jsfiddle.net/mrlew/cLbyyL27/(您可以单击单元格以 select它)
您正在将函数推送到 board
数组。如果你想渲染它们,你必须像
{board[0]()}
我准备了一个例子来解决你的问题:http://jsbin.com/hofohiy/edit?js,output
我看到你也在做 JS React 教程!这是我所做的,但我正在努力解决这个问题,因为必须有一种好的方法来提供这些单独的密钥中的每一个。
我 运行 遇到了与你 运行 相同的问题,其中 X 被绘制成 3 个正方形,发生这种情况的原因是因为当你渲染正方形时,一些 "i's" 被复制了。例如,有多个 "i" 为 2 的正方形(至少在我的问题中是这样)。
所以每个Square都有一个索引吧? [0,1,2,3,4,5,6,7,8].
首先,我们需要找到它们之间的关联方式,以便我们可以将它们呈现为行!因此,在您的示例中,您有 index1 和 index2,我假设它们指的是棋盘中正方形的 x 和 y 坐标。重写上面的数组我们得出:[{0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {2,1}, {0, 2}, {1,2}, {2,2}] 使用 {x,y} 格式。我们如何使用这些值(我们将从您的 index1 和 index2 中获取这些值,以获取我们以 [0,1,2,3,4,5,6,7,8] 开头的原始值数组?
我做的是 3 * x + y(或者在一个循环中,3 * i + j)。这样每个方块都有一个与之相关联的唯一 "i" 值。
设置循环后,我使用
这就是我最终得到的结果,但我需要确保正确设置密钥,这实际上是我偶然发现的 post:
createSquares() {
let rows = [];
for(var i = 0; i < 3; i++){
let squares = [];
for(var j = 0; j < 3; j++){
squares.push(this.renderSquare(3*i+j));
}
rows.push(<div className="board-row">{squares}</div>);
}
return rows;
}
然后我在 Board 中的渲染函数如下所示:
render() {
return (
<div>
{this.createSquares()}
</div>
);
}
这是我在阅读此处和 React JSX 中的循环后能想到的最佳答案 :
render() {
return (
<div>
{
[...Array(3)].map((_, i) => (
<div key={i} className="board-row">
{
[...Array(3)].map((_, j) => this.renderSquare(3 * i + j))
}
</div>
))
}
</div>
);
}
P.S。我也在新 React Tutorial 中进行挑战。 =p
我也在研究 React 教程。感谢您的回复。我找到了这个解决方案:
render() {
const rows = [];
for(let i = 0; i<9; i=i+3) {
const oneRow = [];
for(let j = i; j < i+3; j++) {
oneRow.push(this.renderSquare(j, j))
}
rows.push(<div className="board-row" key={i + 'someId'}>{oneRow}</div>)
}
return (
<div>
{rows}
</div>
);
}
我将 renderSquare 更改为为 Square 组件设置一个键作为第二个参数。
renderSquare(i, key) {
return (
<Square
value={this.props.squares[i]}
onClick={() => this.props.onClick(i)}
key={key}
/>
);
}
Live demo on codepen
render()
函数中的嵌套循环
(评论中的解释:)
class Board extends React.Component {
renderSquare(i) {
return (
<Square
value={this.props.squares[i]}
key={i}
onClick={() => this.props.onClick(i)}
/>
);
}
render() {
var self = this;
return (
<div>
// you can use: [...Array(3)] instead of [1,2,3]
{[1, 2, 3].map(function(row, rowIdx) { // create rows
return (
<div className="board-row" key={rowIdx}>
{
// you can use: [...Array(3)] instead of [1,2,3]
[1, 2, 3].map((col, colIdx) => { // create columns
return self.renderSquare((3 * rowIdx) + colIdx); // calculate square index
})
}
</div>
);
})}
</div>
);
}
}
这应该可以解决您面临的问题。
这甚至为实习生 renderSquare(i) 函数添加了另一个循环。 它可以满足您的需求,即为井字游戏显示 3 列和 3 个单元格。
render() {
let count = 0;
const index = [1, 2, 3];
return (
<div>
{index.map((v, i) => {
return (
<div key={i} className="board-row">
{index.map((v2, i2) => {
return this.renderSquare(count++);
})}
</div>
);
})}
</div>
);
}
第一个方案:
import React from 'react';
import Square from './Square';
export default
class Board extends React.Component {
render() {
const board2 = [];
for (let i = 0; i < 3; i++) {
const s = [];
for (let k = 0; k < 3; k++) {
s[k] = <Square
key ={3*i+k}
value ={this.props.squares[3*i+k]}
onClick ={()=>this.props.onClick(3*i+k)}
/>;
}
board2[i] = <div className="board-row" key={i}>{s}</div>;
}
///////////////////////////////////////
return (
<div>{board2}</div>
);
}
}
第二种方案:
import React from 'react';
import Square from './Square';
export default
class Board extends React.Component {
render() {
let board =Array(3).fill(null);
let square =Array(3).fill(null);
const x = board.map((b,bIndex)=>{
return<div className="board-row" key={bIndex}>
{
square.map((s, sIndex)=>{
return <Square
key ={3*bIndex+sIndex}
value ={this.props.squares[3*bIndex+sIndex]}
onClick ={()=>this.props.onClick(3*bIndex+sIndex)}
/>;
})
}
</div>;
});
///////////////////////////////////////
return (
<div>{x}</div>
);
}
}
正方形:
import React from 'react';
export default
function Square(props) {
console.log('square render')
return (
<button className="square" onClick={props.onClick}>
{props.value}
</button>
);
}
我假设您正在查看 React Tutorial 示例。正如说明明确指出的那样,我们的想法是创建两个循环,而不仅仅是一个。
本例中的第一个循环创建了 3 行。第二个嵌套循环创建了 3 个必要的列,通过 renderSquare 函数为每个位置返回一个 Square。您可能会注意到,我使用了两个循环的索引来正确地将相应的索引分配给正方形。
return (
<div>
{[0,1,2].map(i => {
return (
<div className="board-row">
{[0,1,2].map(j => {
return this.renderSquare(3*i + j)
})}
</div>
);
})}
</div>
);
class Board extends React.Component {
renderSquare(i) {
return (<Square key={i} value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />);
}
render() {
let board = [];
for(let x = 0; x<3; x++){
let lis =[];
for(let y = 0; y<3; y++){
lis.push(this.renderSquare(3*x + y));
}
board.push(<div key={x}>{lis}</div>)
}
return (
<div>
{board}
</div>
);
}
}
我的解决方案是:
class Board extends React.Component {
//range is a Sequence generator function
//Array.from(arrayLike[, mapFn [, thisArg]]).
//arrayLike - An array-like or iterable object to convert to an array
//mapFn - Map function to call on every element of the array
//thisArg - Value to use as this when executing mapFn
//range(0, 4, 1); => [0, 1, 2, 3, 4]
range = (start, stop, step) => Array.from(
{ length: (stop - start)/step +1 },
(_, i) => start + (i * step)
);
renderSquare(i) {
return <Square
key={i}
value={this.props.squares[i]}
onClickChange={() => this.props.onClickChange(i)}
/>;
}
render() {
let row = 3;
let col = 3;
return (
<div>
{
//This generates an Array of [0, 3, 6] if row = 3 and col = 3
// n is the element and i is the index of the element, i starts at 0
this.range(0, row * col - 1, col).map( (n, i) => {
return (
<div key={i} className="board-row">
{
this.range(n, (i + 1) * col - 1, 1).map( (n, i) => {
return this.renderSquare(n)
})
}
</div>
)
})
}
</div>
);
}
此代码段使用 map 的方式类似于我们定义嵌套循环的方式。
const buildBoard = [0, 1, 2].map((row) => {
return (
<div className='board-row' key={row}>
{[0, 1, 2].map((col) => {
return this.renderSquare(row * 3 + col);
})}
</div>
);
});
return <div id='Board Container'>{buildBoard}</div>;
更改了教程中 Board 的代码以反映为
class Board extends React.Component {
constructor(props) {
super(props);
this.rows = Array(3).fill(null);
}
renderSquare(i) {
return (<Square
key={i}
value={this.props.squares[i]}
onClick={() => this.props.onClick(i)}
/>);
}
renderRow(row) {
return (
<div key={row} className="board-row">
{this.rows.map((x, col) => this.renderSquare(3*row+col))}
</div>
);
}
render() {
return (
<div>
{this.rows.map((x, rowIndex) => this.renderRow(rowIndex))}
</div>
);
}
}
这是我的解决方案。可能会有帮助。
renderSquare(i) {
return (
<Square
key={i}
value={this.props.squares[i]}
onClick={() => this.props.onClick(i)}
/>
);
}
render() {
let rows = [];
for (let i = 0; i <= 2; i++) {
let children = []
for (let j = i * 3; j <= i * 3 + 2; j++) {
children.push(this.renderSquare(j))
}
rows.push(
<div key={i} className="board-row">
{children}
</div>
)
}
return (
<div>
{rows}
</div>
);
}
上面提供数组的答案,破坏了循环的目的;这不是很漂亮,但话又说回来,React with JSX 也不是:
class Board extends React.Component {
render() {
let board=[];
for(let row=0;row<9;row+=3) {
let cols=[];
for(let col=0;col<3;col++) {
let i=col+row;
cols.push(<Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)}/>)
}
board.push(
<div className="board-row">
{cols}
</div>
);
}
return (
<div>
{board}
</div>
);
}
}
嗯,我觉得现在更简单了,因为我刚刚做了
export default function Board(props){
return(
<div id = "board">
{createBoard(3, 3)}
</div>
)
}
function Square(props){
return(
<div className = "boardSquare" style = {{
gridColumn: props.x,
gridRow: props.y}}>
</div>
)
}
function createBoard(x, y){
// x and y being the max "cells" my board will have
let grid = [];
for(let i = 0; i < x; i++){
for(let u = 0; u < y; u++){
grid.push(<Square x = {i + 1} y = {u + 1} key = {`x${i+1}y${u+1}`}/>);
}
}
return grid;
}
它完全符合我的要求,所以是的,只需返回一个数组就解决了我的问题,我希望我的回答对某人有用。
只是为了笑笑,这里有一个最近的工作示例作为函数组件
import React from "react";
import Square from "./Square";
import "./Board.css";
export default function Board(props) {
function renderSquare(i) {
return (
<Square
key={i}
value={props.squares[i]}
onClick={() => props.onClick(i)}
/>
);
}
return (
<div className="board-wrapper">
{
[...Array(3).keys()].map( row => (
<div key={row} className="board-row">
{
[...Array(3).keys()].map( col => renderSquare((row * 3) + col))
}
</div>
)
)
}
</div>
)
}