新版本 React 推荐使用函数式组件设计,状态相关处理推荐使用 Hooks,接下来我们通过 class component 和 function component 进行对比讲解。
React 的基础语法和概念是构建 React 应用程序的核心。以下是对 React 基础语法的详细说明,包括 props、state、条件渲染、事件处理和组件传值等。
1. Class Component
1.1. Props
props 是组件的属性,是从父组件传递到子组件的数据。props 是只读的,子组件只能读取而不能修改它们。
import React from 'react';
import ReactDOM from 'react-dom';
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
1.2. State
state 是组件内部的数据状态。state 是可变的,可以通过调用 this.setState 方法来更新状态,从而触发重新渲染。
import React from 'react';
import ReactDOM from 'react-dom';
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = { date: new Date() };
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(<Clock />, document.getElementById('root'));
1.3. 条件渲染
根据某个条件来决定渲染哪个组件或内容。可以使用 JavaScript 中的条件运算符,如 if、else 或三元运算符。
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
ReactDOM.render(
<Greeting isLoggedIn={false} />,
document.getElementById('root')
);
1.4. 事件处理
React 的事件处理类似于 DOM 事件处理,但有一些语法上的不同。事件命名采用小驼峰命名法,处理函数通过 {} 传递。
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = { isToggleOn: true };
// 绑定事件处理函数
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
1.5. 组件传值
父组件可以通过 props 向子组件传递数据和函数,子组件可以调用父组件传递的函数来传递数据回父组件。
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = { message: '' };
this.handleChildData = this.handleChildData.bind(this);
}
handleChildData(data) {
this.setState({ message: data });
}
render() {
return (
<div>
<Child onChildData={this.handleChildData} />
<p>Message from child: {this.state.message}</p>
</div>
);
}
}
class Child extends React.Component {
sendData = () => {
this.props.onChildData('Hello from child');
}
render() {
return (
<div>
<button onClick={this.sendData}>Send Data to Parent</button>
</div>
);
}
}
ReactDOM.render(
<Parent />,
document.getElementById('root')
);
1.6. 列表和 Key
在 React 中渲染列表时,需要为每个列表项提供一个唯一的 key 属性,以便 React 能够有效地更新和重新渲染列表。
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
return (
<ul>{listItems}</ul>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
1.7. 表单处理
React 表单元素的值通常由组件的 state 控制,这些表单元素称为“受控组件”。
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = { value: '' };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({ value: event.target.value });
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange}/>
</label>
<input type="submit" value="Submit"/>
</form>
);
}
}
ReactDOM.render(
<NameForm />,
document.getElementById('root')
);
2. Class Component
目前 React 应用主流编码方式是函数式组件,后续我们的课程也均是以函数式组件为主,同学们重点学习。
2.1. Props
函数式组件通过参数来接收 props。
import React from 'react';
import ReactDOM from 'react-dom';
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
2.2. State
函数式组件使用 useState Hook 来管理状态。
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';
function Clock() {
const [date, setDate] = useState(new Date());
useEffect(() => {
const timerID = setInterval(() => tick(), 1000);
return () => clearInterval(timerID);
}, []);
const tick = () => {
setDate(new Date());
};
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {date.toLocaleTimeString()}</h2>
</div>
);
}
ReactDOM.render(<Clock />, document.getElementById('root'));
2.3. 条件渲染
使用条件运算符或逻辑运算符来实现条件渲染。
import React from 'react';
import ReactDOM from 'react-dom';
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
return (
<div>
{isLoggedIn ? <h1>Welcome back!</h1> : <h1>Please sign up.</h1>}
</div>
);
}
ReactDOM.render(
<Greeting isLoggedIn={false} />,
document.getElementById('root')
);
2.4. 事件处理
函数式组件通过内联函数或自定义函数来处理事件。
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
function Toggle() {
const [isToggleOn, setIsToggleOn] = useState(true);
const handleClick = () => {
setIsToggleOn(!isToggleOn);
};
return (
<button onClick={handleClick}>
{isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
ReactDOM.render(<Toggle />, document.getElementById('root'));
2.5. 组件传值
父组件可以通过 props 向子组件传递数据和函数。
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
function Parent() {
const [message, setMessage] = useState('');
const handleChildData = (data) => {
setMessage(data);
};
return (
<div>
<Child onChildData={handleChildData}/>
<p>Message from child: {message}</p>
</div>
);
}
function Child(props) {
const sendData = () => {
props.onChildData('Hello from Child');
};
return (
<div>
<button onClick={sendData}>Send Data to Parent</button>
</div>
);
}
ReactDOM.render(<Parent />, document.getElementById('root'));
2.6. 列表和 Key
渲染列表时,需要为每个列表项提供一个唯一的 key 属性。
import React from 'react';
import ReactDOM from 'react-dom';
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
return (
<ul>{listItems}</ul>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
2.7. 表单处理
函数式组件使用 useState Hook 来处理表单数据。
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
function NameForm() {
const [value, setValue] = useState('');
const handleChange = (event) => {
setValue(event.target.value);
};
const handleSubmit = (event) => {
alert('A name was submitted: ' + value);
event.preventDefault();
};
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" value={value} onChange={handleChange}/>
</label>
<input type="submit" value="Submit" />
</form>
);
}
ReactDOM.render(<NameForm />, document.getElementById('root'));