react1

阅读 55

2022-07-14

React是一个用于构建用户界面的声明性,高效且灵活的JavaScript库。它允许您从称为“组件”的小而孤立的代码片段中组合复杂的UI。

React有几种不同的组件,但我们将从​​React.Component​​子类开始:

class ShoppingList extends React.Component {
render() {
return (
<div className="shopping-list">
<h1>Shopping List for {this.props.name}</h1>
<ul>
<li>Instagram</li>
<li>WhatsApp</li>
<li>Oculus</li>
</ul>
</div>
);
}
}

// Example usage: <ShoppingList name="Mark" />

我们很快就会得到有趣的类似XML的标签。我们使用组件告诉React我们想要在屏幕上看到什么。当我们的数据发生变化时,React将有效地更新和重新渲染我们的组件。

这里,ShoppingList是一个React组件类,或React组件类型。组件接受称为​​props​​​(“属性”的缩写)的参数,并返回要通过该​​render​​方法显示的视图层次结构。

该​​render​​方法返回您想要在屏幕上看到的内容的描述。React接受描述并显示结果。特别是,​​render​​​返回一个React元素,它是渲染内容的轻量级描述。大多数React开发人员使用称为“JSX”的特殊语法,这使得这些结构更容易编写。该​​<div />​​​语法在构建时被转化​​React.createElement('div')​​。上面的例子相当于:

return React.createElement('div', {className: 'shopping-list'},
React.createElement('h1', /* ... h1 children ... */),
React.createElement('ul', /* ... ul children ... */)
);

通过道具传递数据

为了让我们的脚湿透,让我们尝试将一些数据从我们的Board组件传递到Square组件。

在Board的​​renderSquare​​​方法中,更改代码以传递调用​​value​​Square 的道具:

class Board extends React.Component {
renderSquare(i) {
return <Square value={i} />;
}

​render​​​通过替换​​{/* TODO */}​​​为​​{this.props.value}​​:更改Square的方法来显示该值:

class Square extends React.Component {
render() {
return (
<button className="square">
{this.props.value}
</button>
);
}
}

class Square extends React.Component {
render() {
return (
<button className="square" onClick={() => alert('click')}>
{this.props.value}
</button>
);
}
}
请注意onClick={() => alert('click')},我们将函数作为onClickprop 传递。它只在点击后触发。忘记() =>和写入onClick={alert('click')}是一个常见的错误,每次组件重新渲染时都会触发警报。

下一步,我们希望Square组件“记住”它被点击,并用“X”标记填充它。为了“记住”事物,组件使用状态。

React组件可以通过​​this.state​​​在其构造函数中设置来具有状态。​​this.state​​​应被视为对其定义的React组件的私有。让我们存储Square的当前值​​this.state​​,并在单击Square时更改它。

首先,我们将在类中添加一个构造函数来初始化状态:

class Square extends React.Component {
constructor(props) {
super(props);
this.state = {
: null,
};
}

render() {
return (
<button className="square" onClick={() => alert('click')}>
{this.props.value}
</button>
);
}
}

在​​JavaScript类中​​​,您需要​​super​​​在定义子类的构造函数时始终调用。所有具有a的React组件类都​​constructor​​​应该通过​​super(props)​​调用启动它。

现在我们将更改Square的​​render​​方法,以便在单击时显示当前状态的值:

  • 更换​​this.props.value​​​用​​this.state.value​​​的内部​​<button>​​标签。
  • ​() => alert()​​​用​​() => this.setState({value: 'X'})​​。替换事件处理程序。
  • 将​​className​​​和​​onClick​​道具放在不同的线上以提高可读性。

在这些更改之后,​​<button>​​​Square ​​render​​方法返回的标记如下所示:

class Square extends React.Component {
constructor(props) {
super(props);
this.state = {
value: null,
};
}

render() {
return (
<button
className="square"
onClick={() => this.setState({value: 'X'})}
>
{this.state.value}
</button>
);
}
}

通过使用Square 方法中​​this.setState​​​的​​onClick​​​处理程序调用​​render​​​,我们告诉React在​​<button>​​​单击它时重新呈现该Square 。更新后,Square ​​this.state.value​​​将会是​​'X'​​​,所以我们将​​X​​​在游戏板上看到。如果你点击任何Square,​​X​​就会显示出来。

当您调用​​setState​​组件时,React也会自动更新其中的子组件。

class Board extends React.Component {
constructor(props) {
super(props);
this.state = {
: Array(9).fill(null),
};
}

renderSquare(i) {
return <Square value={i} />;
}

render() {
const status = 'Next player: X';

return (
<div>
<div className="status">{status}</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>
);
}
}

为了便于阅读,我们将返回的元素拆分为多行,并添加了括号,以便JavaScript不会在​​return​​我们的代码之后插入分号。

现在我们传递了从Board到Square的两个道具:​​value​​​和​​onClick​​​。该​​onClick​​道具是点击后Square可以调用一个函数。我们将对Square进行以下更改:

  • 更换​​this.state.value​​​用​​this.props.value​​​在Square的​​render​​方法
  • 更换​​this.setState()​​​用​​this.props.onClick()​​​在Square的​​render​​方法
  • 删除​​constructor​​Square,因为Square不再跟踪游戏的状态

完成这些更改后,Square组件如下所示:

class Square extends React.Component {
render() {
return (
<button
className="square"
onClick={() => this.props.onClick()}
>
{this.props.value}
</button>
);
}
}

单击Square时,将​​onClick​​调用Board提供的功能。以下是对如何实现这一目标的回顾:

  1. ​onClick​​​内置DOM​​<button>​​组件的prop 告诉React设置一个click事件监听器。
  2. 单击该按钮时,React将调用​​onClick​​​Square​​render()​​方法中定义的事件处理程序。
  3. 此事件处理程序调用​​this.props.onClick()​​​。Square的​​onClick​​支柱由董事会指定。
  4. 自从董事会转移​​onClick={() => this.handleClick(i)}​​​到Square后,Square​​this.handleClick(i)​​点击时调用。
  5. 我们尚未定义该​​handleClick()​​方法,因此我们的代码崩溃了。

注意

DOM ​​<button>​​​元素的​​onClick​​​属性对React具有特殊含义,因为它是一个内置组件。对于像Square这样的自定义组件,命名取决于您。我们可以用不同​​onClick​​​的​​handleClick​​​方式命名Square的prop或Board的方法。但是,在React中,使用​​on[Event]​​​道具名称来表示事件和​​handle[Event]​​处理事件的方法是一种惯例。

当我们尝试点击Square时,我们应该会收到错误,因为我们还没有定义​​handleClick​​​。我们现在将添加​​handleClick​​到Board类:

class Board extends React.Component {
constructor(props) {
super(props);
this.state = {
squares: Array(9).fill(null),
};
}

handleClick(i) {
const squares = this.state.squares.slice();
[i] = 'X';
this.setState({squares: squares});
}

renderSquare(i) {
return (
<Square
value={this.state.squares[i]}
onClick={() => this.handleClick(i)}
/>
);
}

render() {
const status = 'Next player: X';

return (
<div>
<div className="status">{status}</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>

精彩评论(0)

0 0 举报