写在前面

今天参加了一整天reactjs的培训,看邮件说该课程价值100美元,该课程覆盖了react的大部分基础内容,确实很不错。听说外企中使用reactjs较多,国内使用vue较多,想在外企工作的同学有必要了解该框架。写该博文主要是梳理React的基础知识点,可以对ReactJS的基础知识有大体了解。


React基础环境搭建

  1. 安装React脚手架(安装一次就好)
npm install -g create-react-app
  1. 验证脚手架是否安装完毕/查询版本
create-react-app  -V
  1. 创建项目
create-react-app  项目名称   (js版本)

create-react-app 项目名称  --template typescript  (TS版本)
  1. 搭建好项目后,控制台会提示输入哪些命令,我习惯cd该目录,code .使用vscode打开

  2. 启动项目

npm start

在这里插入图片描述

至此基础环境搭建完成,开始react的正式学习


React组件

React 是一个使用组件构建用户界面的 JavaScript 库。组件是 React 应用程序的构建块,每个组件都是独立封装的,可以在不影响应用程序其他部分的情况下重复使用和组合。

  • Function 组件,以函数 的形式定义的组件称为 Function 组件,它们通常很简单,只有一个 props 参数并返回一个 virtual DOM 元素。
  • Class 组件,以 ES6 class 的形式定义的组件称为 Class 组件,它们可以有自己的状态 (state) 和生命周期方法。
  • Prop ,props 是父组件传递给子组件的参数。在 Function 组件中,props 是函数的参数。在 Class 组件中,props 是通过 this.props 访问的。

以下是一个使用props传递数据的简单的React子组件和父组件代码:

ChildComponent.js:

import React from 'react';

const ChildComponent = (props) => {
  return (
    <div>
      <p>Child Component</p>
      <p>{props.message}</p>
    </div>
  );
};

export default ChildComponent;

ParentComponent.js:

import React from 'react';
import ChildComponent from './ChildComponent';

class ParentComponent extends React.Component {
  render() {
    return (
      <div>
        <p>Parent Component</p>
        <ChildComponent message={'Hello from parent!'} />
      </div>
    );
  }
}

export default ParentComponent;

在app.js中使用这些组件:

import React from 'react';
import ParentComponent from './ParentComponent';

class App extends React.Component {
  render() {
    return (
      <div>
        <ParentComponent />
      </div>
    );
  }
}

export default App;

目录结构如下
在这里插入图片描述
运行结果:
在这里插入图片描述


React Onclick

如下为创建一个button,并且随着点击递增数字的计数器示例代码:

import React, { useState } from 'react';
import './index.css';

function MyButton() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount(count + 1);
  };

  return (
    <button className="my-button" onClick={handleClick}>
      {count}
    </button>
  );
}

export default MyButton;

其中,使用了React内置的useState Hook来存储按钮点击的次数,使用onClick属性绑定点击事件,每次点击都会调用handleClick函数,并且将count的值加1,从而实现计数器。

在App.js中引入:

import React from 'react';
import MyButton from './MyButton';

function App() {
  return (
    <div className="App">
      <MyButton />
    </div>
  );
}

export default App;

同时需要在index.css中定义按钮的样式,例如:

.my-button {
  width: 100px;
  height: 30px;
  font-size: 18px;
  background-color: lightblue;
  border: 1px solid lightyellow;
  color: white;
  cursor: pointer;
}

其中,.my-button是指定的class名称,在button标签中设置className属性即可应用该样式。

在这里插入图片描述

React useEffect

修改MyButton.js中的代码,来看一下useEffect的示例

import React, { useEffect, useState } from 'react';

const MyButton = () => {
    const [count, setCount] = useState(0);

    useEffect(() => {
      document.title = `You clicked ${count} times`;
    });
  
    return (
      <div>
        <p>You clicked {count} times</p>
        <button onClick={() => setCount(count + 1)}>
          Click me
        </button>
      </div>
    );
};

export default MyButton;

在这里插入图片描述
可以看到当点击后,浏览器的title也进行了更新,这里effect 不只执行一次。当组件第一次展示给用户以及之后的每次更新时它都会被执行。在 effect 中能触及当前的 props 和 state。
在这里插入图片描述


React Greeting

下面是一个使用React Greeting的示例代码,实现的是根据输入框输入的信息,获取内容并展示:

在这里插入图片描述

import React, { useState } from 'react';

function Greeting() {
  const [name, setName] = useState('');

  function handleChange(event) {
    setName(event.target.value);
  }

  return (
    <React.Fragment>
      <label>
        Enter your name:&nbsp;
        <input type="text" placeholder="Your name" value={name} onChange={handleChange} />
      </label>
      <h1>Hello, {name.length > 0 ? name : 'Stranger'}!</h1>
    </React.Fragment>
  );
}

export default Greeting;

这个示例代码中,我们在函数式组件Greeting中使用了useState hook,来管理输入框中的值。使用了React Fragment来避免多余的外层标签。然后,给input元素添加了placeholder属性,在没有输入时显示“Your name”,用于提示用户输入内容。通过onChange事件,输入框中的值改变时,调用handleChange函数更新state中对应的值。最后,在页面上展示一个h1标题,来展示用户输入的文本。如果用户没有输入任何内容,则页面上展示“Hello, Stranger!”。

最后引入到app.js中:

import React from 'react';
import Greeting from './Greeting';

function App() {
  return (
    <div className="container">
      <Greeting />
    </div>
  );
}

export default App;

这个示例中的App组件作为整个应用的入口组件,使用了Greeting组件,并且放置在了一个div.container中。

React Fragment的作用
React Fragment是一个组件,用于在不需要添加额外节点的情况下,将多个子元素分组。它可以用来组合一些子节点,而不会在DOM树中添加额外节点。它类似于Vue.js中的或Angular中的。
在过去,为了避免在DOM树中添加额外的DOM节点,开发人员会使用不必要的外部元素来包装多个元素。React Fragment可以使这个过程更加简单和干净。
使用React Fragment可以优化性能,因为它不会影响渲染结果,但可以优化渲染速度和内存使用。此外,React.Fragment可以被考虑成是对虚拟DOM树的一种提示,告诉React不要为它创建单独的节点。


React与BootStrap

Bootstrap是Twitter公司推出的一款开源的前端框架,它基于HTML、CSS、JavaScript开发,其中包含了丰富的CSS和JavaScript组件,用来快速构建响应式网站和Web应用程序。Bootstrap提供了一种简单的方法来快速设计页面结构、样式和交互效果,减少了开发成本,让开发者专注于网站和应用程序的功能实现。同时,Bootstrap还支持自定义构建下载,开发者可以根据自己的需求选择所需要的组件下载使用,极大地提高了开发效率。

下面是Button组件用到了bootstrap的案例:
首先,在index.html中引入Bootstrap的CSS和JS文件:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>My React App</title>
    <!-- 引入Bootstrap的CSS文件 -->
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.3.1/css/bootstrap.min.css">
  </head>
  <body>
    <!-- 这里是react应用的根节点 -->
    <div id="root"></div>
    <!-- 引入React的JS文件 -->
    <script src="./app.js"></script>
    <!-- 引入jQuery和Popper.js的CDN,以便引入Bootstrap的JS文件 -->
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.slim.min.js"></script>
    <script src="https://cdn.bootcss.com/popper.js/1.15.0/umd/popper.min.js"></script>
    <!-- 引入Bootstrap的JS文件 -->
    <script src="https://cdn.bootcss.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
  </body>
</html>

在这里插入图片描述

接下来,在MyButton.js中编写MyButton组件的代码:

import React from 'react';

const MyButton = ({text, style}) => {
  return (
    <MyButton type="MyButton" className={`btn ${style}`}>{text}</MyButton>
  );
};

export default MyButton;

MyButton组件有两个props:text和style。text表示按钮上要显示的文本,style表示按钮的样式类名。在这里我们使用了模板字符串和“${}”语法来拼接样式类名,以便动态修改按钮的样式。

最后,将MyButton组件集成到App.js中:

import React from 'react';
import MyButton from './MyButton';

const App = () => {
  return (
    <div className="container mt-3">
      <MyButton text="Default" style="btn-primary mr-3" />
      <MyButton text="Success" style="btn-success mr-3" />
      <MyButton text="Danger" style="btn-danger" />
    </div>
  );
};

export default App;

在App组件中,我们使用了三个MyButton组件,并传入不同的props,以生成三个具有不同样式的按钮。
在这里插入图片描述


React与API

使用Fetch方法

以下是调用API的数据并使用列表展示的示例代码

import React, { Component } from "react";

class FetchAPI extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: []
    };
  }

  componentDidMount() {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then(response => response.json())
      .then(data => {
        this.setState({
          data: data
        });
      });
  }

  render() {
    const { data } = this.state;
    const listItems = data.map(item => (
      <li key={item.id}>
        {item.name}, {item.email}
      </li>
    ));
    return <ul>{listItems}</ul>;
  }
}

export default FetchAPI;

此代码实现了以下功能:

  1. 导入React库和useState和useEffect Hook。
  2. 创建FetchAPI组件。
  3. 使用constructor和state来初始化组件的状态来创建一个名为data的状态,并将其初始值设置为空数组。
  4. 获取json数据,发出一个HTTP GET请求并将响应转换为JSON格式。此请求完成后,setData将更新data状态并将其设置为获取的JSON数据。
  5. 在组件的返回值中,呈现一个标题元素和一个项目元素的列表。使用map方法遍历data状态中的所有项目,并在列表中呈现每个项目的标题。{{item.title}}.

然后在app.js中引入该组件:

import React from "react";
import FetchAPI from "./FetchAPI";

function App() {
  return (
    <div className="App">
      <FetchAPI />
    </div>
  );
}

export default App;

在这里插入图片描述

使用Axois

Axios是一款基于Promise的HTTP客户端,可用于浏览器和Node.js中。Axios可以用于发送HTTP请求并处理响应。它支持请求和响应拦截器,可以帮助你简化代码,并使HTTP请求和响应更加灵活。Axios还提供了多种功能,例如取消请求,设置默认配置,拦截器等等。Axios被广泛应用于前端开发中,尤其在React等框架中使用广泛。

首先,需要在项目中安装axios:

npm install axios

安装后加载到package.json文件中
在这里插入图片描述

然后,在AxiosAPI组件中使用axios来调用接口并获取数据:

import React, { useState, useEffect } from 'react';
import axios from 'axios';

const AxiosAPI = () => {
  const [data, setData] = useState({});

  useEffect(() => {
    axios.get('https://jsonplaceholder.typicode.com/posts/1')
      .then(response => setData(response.data))
      .catch(error => console.log(error));
  }, []);

  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.body}</p>
    </div>
  );
}

export default AxiosAPI;

在上面的代码中,我们在组件中使用了useState和useEffect hooks来处理数据和获取接口数据确保实时更新。在useEffect hook中,我们使用axios调用了jsonplaceholder的API,并将响应数据保存在data中。最后,我们将数据渲染到组件中。

最后,将AxiosAPI组件集成到APP.js中:

import React from 'react';
import AxiosAPI from './AxiosAPI';

const App = () => {
  return (
    <div>
      <AxiosAPI />
    </div>
  );
}

export default App;

刷新服务,结果如下:
在这里插入图片描述
和接口中的数据进行对比
在这里插入图片描述


React路由和Context

前端路由是指在单页应用(SPA)中,通过操作URL来实现页面之间的跳转和管理。它可以保证用户在跳转页面时不刷新整个页面,而只是更新部分页面内容,从而达到快速响应的效果。
前端路由通常使用浏览器的history API或hash值来在URL中记录页面状态信息,从而实现在单页应用中的页面之间的切换。常见的前端路由库包括React Router、Vue Router和Angular Router等。
前端路由的优点包括提高网站的运行速度和用户体验,减轻服务器的压力,以及方便SEO等方面的优化。同时,前端路由也可以帮助开发人员更好地进行代码结构管理,提高代码复用性和可维护性。

首先确保安装了react-router-dom
npm install react-router-dom

下面是一个示例代码,展示了如何使用BrowserRouter、Route、Link、Routes组件以及UserContext来创建一个简单的ReactJS应用程序:

import React, { createContext, useState,useContext,useEffect } from 'react';
import { BrowserRouter, Route, Link, Routes } from 'react-router-dom';

// 创建一个UserContext的上下文,用于在组件之间共享用户信息
export const UserContext = createContext();

// 创建一个简单的用户列表(实际中应从后台服务获取)
const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 3, name: 'Charlie' },
];

// 用户页面组件,负责显示单个用户的详细信息
const UserPage = ({ userId }) => {
  const [user, setUser] = useState(null);

  // 在组件挂载时,从用户列表中查找对应的用户信息并设置到本地状态
  useEffect(() => {
    const user = users.find(u => u.id === userId);
    setUser(user);
  }, [userId]);

  // 判断是否已成功获取用户信息
  if (!user) {
    return <div>Loading...</div>;
  }

  // 显示用户信息
  return (
    <div>
      <h1>{user.name}</h1>
      <p>ID: {user.id}</p>
    </div>
  );
};

// 用户列表页面组件,负责显示所有用户的概要信息
const UsersPage = () => {
  return (
    <div>
      <h1>Users</h1>
      <ul>
        {users.map(user => (
          <li key={user.id}>
            <Link to={`/users/${user.id}`}>{user.name}</Link>
          </li>
        ))}
      </ul>
    </div>
  );
};

// 应用程序启动组件
const App = () => {
  const [user, setUser] = useState(null);

  // 用户登录函数,将用户信息存储到上下文中
  const login = ({ id, name }) => {
    setUser({ id, name });
  };

  // 用户登出函数,将用户信息从上下文中清除
  const logout = () => {
    setUser(null);
  };

  // 渲染应用程序,包括页面导航、用户信息和路由处理
  return (
    <BrowserRouter>
      <nav>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/users">Users</Link>
          </li>
        </ul>
      </nav>
      <UserContext.Provider value={{ user, login, logout }}>
        <div>
          {user ? (
            <p>
              Logged in as <b>{user.name}</b>. <button onClick={logout}>Logout</button>
            </p>
          ) : (
            <p>
              <Link to="/login">Login</Link>
            </p>
          )}
          <Routes>
            <Route path="/" element={<h1>Welcome to My App</h1>} />
            <Route path="/login" element={<LoginForm />} />
            <Route path="/users" element={<UsersPage />} />
            <Route path="/users/:userId" element={<UserPage />} />
          </Routes>
        </div>
      </UserContext.Provider>
    </BrowserRouter>
  );
};

// 登录表单组件,负责接收用户输入并处理登录逻辑
const LoginForm = () => {
  const { login } = useContext(UserContext);
  const [formData, setFormData] = useState({ name: '' });

  const handleChange = e => {
  // ...展开语法,用于展开对象,数组,不确定参数等
    setFormData({ ...formData, [e.target.name]: e.target.value });
  };

  const handleSubmit = e => {
    e.preventDefault();
    login({ id: 123, name: formData.name });
    setFormData({ name: '' });
  };

  return (
    <div>
      <h1>Login</h1>
      <form onSubmit={handleSubmit}>
        <label>
          Name:
          <input type="text" name="name" value={formData.name} onChange={handleChange} />
        </label>
        <button type="submit">Login</button>
      </form>
    </div>
  );
};

export default App;

在这个示例中,我们首先创建了一个UserContext上下文,用于在不同的组件之间共享用户信息。然后我们定义了两个页面组件,UsersPage和UserPage,分别用于显示用户列表和单个用户的详细信息。

在App组件中,我们也使用BrowserRouter、Route、Link和Routes组件来设置路由和页面导航。此外,我们还通过UserContext.Provider将用户信息注入整个应用程序。

最后,我们还提供了一个LoginForm组件,用于处理用户登录逻辑。在这个组件中,我们使用useContext钩子从UserContext中获取login函数,并通过useState钩子来管理登录表单中的用户输入。用户在提交表单时,我们调用login函数将用户信息存储到上下文中。然后页面会自动重新渲染,显示用户信息和导航菜单中的注销按钮。

在这里插入图片描述
在这里插入图片描述

Logo

前往低代码交流专区

更多推荐