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方法中,更改代码以传递调用valueSquare 的道具:
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方法 - 删除
constructorSquare,因为Square不再跟踪游戏的状态
完成这些更改后,Square组件如下所示:
class Square extends React.Component {
render() {
return (
<button
className="square"
onClick={() => this.props.onClick()}
>
{this.props.value}
</button>
);
}
}单击Square时,将onClick调用Board提供的功能。以下是对如何实现这一目标的回顾:
-
onClick内置DOM<button>组件的prop 告诉React设置一个click事件监听器。 - 单击该按钮时,React将调用
onClickSquarerender()方法中定义的事件处理程序。 - 此事件处理程序调用
this.props.onClick()。Square的onClick支柱由董事会指定。 - 自从董事会转移
onClick={() => this.handleClick(i)}到Square后,Squarethis.handleClick(i)点击时调用。 - 我们尚未定义该
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>










