React基础与实践笔记 | 青训营笔记

94 阅读4分钟

React 基础与实践课程笔记

一、React简介

React 是一个用于构建用户界面的 JavaScript 库,是用js构建快速响应和大型web应用的首选方法之一,在Facebook和instagram上表现优异。React 的核心特性是组件化开发和虚拟 DOM,这使得开发人员能够轻松地创建复杂且高性能的应用程序。

二、React 基础

1. JSX

JSX 是 JavaScript 的一种扩展语法,它可以让我们在 JavaScript 代码中书写类似于 HTML 的标签结构。React 使用 JSX 来描述组件的结构和样式。

const element = <h1>Hello, world!</h1>;

2. 元素渲染

React 元素是构建应用程序的最小单位。要将 React 元素渲染到页面上,我们需要使用 ReactDOM.render() 方法。

import React from 'react';
import ReactDOM from 'react-dom';

const element = <h1>Hello, world!</h1>;
ReactDOM.render(element, document.getElementById('root'));

3. 组件与 Props

React 组件允许我们将 UI 划分为独立的、可重用的部分。组件可以是函数或者类。

// 函数组件
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

// 类组件
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

Props 是组件的输入。我们可以通过给组件传递属性(props)来设置组件的外观和行为。注意:组件内部不应该修改 props。

function App() {
  return <Welcome name="Sara" />;
}

ReactDOM.render(<App />, document.getElementById('root'));

4. State 与生命周期

State 是组件内部的状态,用于存储和管理组件的数据。State 只能在类组件中使用,但是 React 16.8 引入了 Hook,使得函数组件也可以使用 state。我们可以通过 setState() 方法来更新组件的 state。

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>{this.state.date.toLocaleTimeString()}</div>;
  }
}

ReactDOM.render(<Clock />, document.getElementById('root'));

我们先创建了一个时钟组件,会在页面上每隔一秒钟更新当前时间。

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = { date: new Date() };
  }

这里定义了一个 Clock 类,继承自 React.Component。在构造函数中,初始化了组件的 state,其中 date 属性被设置为当前日期时间的实例。

  componentDidMount() {
    this.timerID = setInterval(() => this.tick(), 1000);
  }

在组件挂载到 DOM 树上后,会调用 componentDidMount() 方法。这里使用 JavaScript 的 setInterval() 方法来设置一个定时器,每隔一秒钟就调用一次 tick() 方法更新组件的 state。

 componentWillUnmount() {
    clearInterval(this.timerID);
  }

当组件要从 DOM 树中被移除时,会调用 componentWillUnmount() 方法,这里清除了之前设置的定时器。

  tick() {
    this.setState({ date: new Date() });
  }

这里定义了 tick() 方法,它会在定时器触发时被调用,用于更新组件的 state 中的 date 属性,从而重新渲染组件。

render() {
    return <div>{this.state.date.toLocaleTimeString()}</div>;
  }
}

最后,在组件的 render() 方法中,返回一个 div 元素,显示当前时间的字符串,使用了 toLocaleTimeString() 方法将时间转换为本地时间字符串。

最后通过 ReactDOM.render() 方法将 Clock 组件渲染到页面上,通过 document.getElementById('root') 获取到的 DOM 元素。

5. 事件处理

React 中的事件处理方式类似于 DOM 元素的事件处理,但是有一些语法和概念上的差异。例如,React 事件使用驼峰命名,而不是小写。此外,通过 JSX 传递的事件处理函数是一个函数引用,而不是一个字符串。

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isToggleOn: true };

    // 为了在回调中使用 `this`,这个绑定是必不可少的
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState((prevState) => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

ReactDOM.render(<Toggle />, document.getElementById('root'));

三、React 实践

1. 列表与 Keys

在 React 中,我们可以使用数组的 map() 方法来遍历列表并生成新的元素。当我们创建一个元素数组时,需要为每个元素分配一个唯一的 key 属性。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'));

2. 表单

React 中的表单元素与 HTML 表单元素有所不同。在 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'));

3. 状态提升

当多个组件需要共享一些数据时,我们可以将共享状态提升到它们的最近公共祖先。这使得我们能够在组件树中同步数据。

function BoilingVerdict(props) {
  if (props.celsius >= 100) {
    return <p>The water would boil.</p>;
  }
  return <p>The water would not boil.</p>;
}

class Calculator extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = { temperature: '' };
  }

  handleChange(e) {
    this.setState({ temperature: e.target.value });
  }

  render() {
    const temperature = this.state.temperature;
    return (
      <fieldset>
        <legend>Enter temperature in Celsius:</legend>
        <input value={temperature} onChange={this.handleChange} />
        <BoilingVerdict celsius={parseFloat(temperature)} />
      </fieldset>
    );
  }
}

ReactDOM.render(<Calculator />, document.getElementById('root'));

其中 Calculator 组件作为父组件,BoilingVerdict 组件作为子组件。

在这个例子中,Calculator 组件通过 props 将当前温度值传递给 BoilingVerdict 组件,BoilingVerdict 组件根据接收到的温度值来判断水是否会沸腾,并返回相应的提示信息。

4. React-Router

在单页应用中,我们需要使用路由来实现页面之间的切换。React-Router 是一个用于实现路由功能的 React 插件。

首先,需要安装 React-Router:

npm install react-router-dom

然后在项目中使用:

import { BrowserRouter as Router, Route, Link } from 'react-router-dom';

function Home() {
  return <h2>Home</h2>;
}

function About() {
  return <h2>About</h2>;
}

function App() {
  return (
    <Router>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/about">About</Link>
            </li>
          </ul>
        </nav>

        <Route path="/" exact component={Home} />
        <Route path="/about" component={About} />
      </div>
    </Router>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));