【React基础全篇】

文章目录

  • 一、关于 React
  • 二、脚手架
    • 2.1 create-react-app 脚手架的使用
    • 2.2 项目目录解析
    • 2.3 抽离配置文件
    • 2.4 webpack 二次封装
      • 2.4.1 集成 css 预处理器
      • 2.4.2 配置@解析别名
    • 2.5 setupProxy 代理
  • 三、JSX
    • 3.1 jsx 语法详解
    • 3.2 React.createElement
  • 四、组件定义
    • 4.1 类组件
    • 4.2 函数组件
    • 4.3 两组组件的区别
  • 五、Props
    • 5.1 Props 详解
    • 5.2 父子组件通信
      • 5.2.1 构建一个父子组件
      • 5.2.2 父组件给子组件传值
      • 5.2.3 父组件给子组件传值设置默认值
      • 5.2.4 使用 prop-types 属性验证
    • 5.3 props.children
    • 5.4 render props 特性
  • 六、State
    • 6.1 state 及其特点
    • 6.2 state 的定义和使用
      • 6.2.1 es6 的类 - 构造函数
      • 6.2.2 es7 的类 - 属性初始化器
    • 6.3 如何正确的修改 state
    • 6.4 this.setState()方法及其特点
      • 6.4.1 传递函数
      • 6.4.2 传递对象
  • 七、生命周期
    • 7.1 三个阶段
      • 7.1.1 装载阶段
      • 7.1.2 更新阶段
      • 7.1.3 卸载阶段
      • 7.1.4 Error boundaries
    • 7.2 两个时期
    • 7.3 入门理解 React Fiber 架构
  • 八、事件绑定
    • 8.1 ES5 语法绑定事件
      • 8.1.1 无参数的绑定
        • 8.1.1.1 方法一
        • 8.1.1.1 方法二
      • 8.1.2 有参数的绑定
    • 8.2 ES6 语法绑定事件
      • 8.2.1 无参数绑定
        • 8.2.1.1 方法一
        • 8.2.1.2 方法二
      • 8.2.2 有参数绑定
        • 8.2.2.1 方法一
        • 8.2.2.2 方法二
    • 8.3 合成事件的特点
      • 8.3.1 事件机制
      • 8.3.2 对合成事件的理解
      • 8.3.3 事件机制的流程
        • 1、事件注册
        • 2、事件存储
        • 3、事件执行
      • 8.3.4 合成事件、原生事件之间的冒泡执行关系
  • 九、条件渲染
    • 9.1 &&
    • 9.2 三元运算符
    • 9.3 动态 className
    • 9.4 动态 style
  • 十、列表渲染
  • 十一、表单绑定
    • 11.1 各种表单的绑定与取值
    • 11.2 受控表单以及受控组件
  • 十二、状态提升
    • 12.1 父子组件通信
    • 12.2 状态提升解读
  • 十三、组合 vs 继承
    • 13.1 理解组件化
    • 13.2 使用组合而非继承实现 React 组件化
    • 13.3 封装 Modal 弹窗
    • 13.4 ReactDOM.createPortal()
  • 十四、上下文 Context
    • 14.1 理解上下文、作用及其特点
    • 14.2 使用 React.createContext()
      • 14.2.1 逐层传递数据
      • 14.2.2 使用 Context 传值
      • 14.2.3 传递多个值
      • 14.2.4 displayName
    • 14.3 常见应用场景解读
  • 十五、高阶组件
    • 15.1 理解高阶组件、作用及其特点
    • 15.2 高阶组件语法详解
      • 15.2.1 组件嵌套
      • 15.2.2 高阶组件
    • 15.3 常见应用场景解读
  • 十六、ref
    • 16.1 ref 访问 DOM
    • 16.2 详解 ref 转发
    • 16.3 使用 ref 注意事项
  • 十七、hooks
    • 17.1 为什么使用 hooks
    • 17.2 常见的 hooks
      • 17.2.1 useState
      • 17.2.2 useEffect
      • 17.2.3 useRef
      • 17.2.4 useReducer
      • 17.2.5 useContext
      • 17.2.6 useMemo
      • 17.2.7 useCallback
      • 17.2.8 useImperativeHandle
      • 17.2.9 useLayoutEffect
      • 17.2.10 useDebugValue
      • 17.2.11 useId
      • 17.2.12 useDeferredValue
      • 17.2.13 useTransition
      • 17.2.14 useSyncExternalStore
      • 17.2.15 useInsertionEffect
    • 17.3 自定义 hooks
  • 十八、Redux
    • 18.1 理解 Flux 架构

一、关于 React

英文官网:https://reactjs.org/

中文官网:https://zh-hans.reactjs.org/

React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站。做出来以后,发现这套东西很好用,就在 2013 年 5 月开源了。

react 在发展过程中,一直跟随原生 js 的脚步,特别是从 v16.0 版本开始(用到了 class 来创建组件)

2015 年推出了使用 react 来编写移动端的 app ---- react-native

重要版本发版时间

序号 版本号 发版时间 重要更新
1 16 2017 年 9 月 26 引入 es6 的类组件
2 16.3 2018 年 4 月 3 日 生命周期更新
3 16.4 2018 年 5 月 23 日 生命周期更新
4 16.8 2019 年 2 月 6 日 引入 react hooks
5 17.0 2020 年 10 月 20 日 过渡版本
6 18.0 2022 年 3 月 29 日 写法改变,严格模式发生改变

二、脚手架

英文官网:https://create-react-app.dev/

中文官网:https://create-react-app.bootcss.com/

补充:react 的脚手架并不是只有 create-react-app,还有dva-cli,umi

2.1 create-react-app 脚手架的使用

Create React App 让你仅通过一行命令,即可构建现代化的 Web 应用。

本文档之后称之为 cra

创建项目的方式:

需要保证电脑安装 node 版本在 14 以上,系统在 win7 以上

# 方式1:使用npx
$ npx create-react-app react-basic
# 方式2:使用npm
$ npm init react-app react-basic
# 方式3:使用yarn
$ yarn create react-app react-basic
yarn的使用
yarn的安装:npm i yarn tyarn -g
安装依赖:
  npm i xxx -g  ->  yarn add xxx -global
  npm i xxx -S  ->  yarn add xxx
  npm i xxx -D  ->  yarn add xxx -dev
  npm i         ->  yarn

如果需要使用 ts 开发项目,创建项目时可以通过--template typescript指定模版

$ npx create-react-app myapp --template typescript

如果出现如下内容,即代表项目创建成功

Success! Created react-basic at /Users/wudaxun/Desktop/workspace/code/bk2207A/code/react-course/react-basic
Inside that directory, you can run several commands:

  npm start
    Starts the development server.

  npm run build
    Bundles the app into static files for production.

  npm test
    Starts the test runner.

  npm run eject
    Removes this tool and copies build dependencies, configuration files
    and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

  cd react-basic
  npm start

Happy hacking!

2.2 项目目录解析

项目创建完毕生成目录结构如下:

react-basic
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
└── src
    ├── App.css
    ├── App.js
    ├── App.test.js
    ├── index.css
    ├── index.js
    ├── logo.svg
    ├── reportWebVitals.js // 做性能测试
    └── setupTests.js // 测试

src/reportWebVitals.js

const reportWebVitals = (onPerfEntry) => {
  if (onPerfEntry && onPerfEntry instanceof Function) {
    import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
      getCLS(onPerfEntry); // 衡量视觉稳定性。为了提供一个好的用户体验,CLS应该小于0.1
      getFID(onPerfEntry); // 衡量可交互性。为了提供一个好的用户体验,FID应该在100毫秒内。
      getFCP(onPerfEntry); // 首次内容绘制
      getLCP(onPerfEntry); // 衡量加载性能。为了提供一个好的用户体验,LCP应该在2.5秒内
      getTTFB(onPerfEntry); // 到第一个字节的时间
    });
  }
};
export default reportWebVitals;

react 官方文档已经给了我们性能提升的方案:https://zh-hans.reactjs.org/docs/optimizing-performance.html

打开package.json,发现可运行命令如下:

 "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },

start指令用于启动开发者服务器

build指令用于打包项目

test指令用于测试

eject指令用于抽离配置文件

cra脚手架基于webpack,默认webpack的配置在 node_modules 下的 react-scripts 内部,但是一般情况下,传输代码时,不会上传 node_modules,那么在必要情况下就必须得抽离配置文件。

2.3 抽离配置文件

通过npm run eject或者cnpm run eject 或者yarn eject指令抽离配置文件

抽离配置文件过程中注意事项

  • 1.确保项目的 git 仓库是最新的
  • 2.如果不需要对于 webpack 进行配置,那么不需要抽离配置文件
  • create-react-app v2 默认支持 ts 以及 sass 以及 css 的模块化,如果使用 sass 作为 css 预处理器,那么不需要抽离配置文件
Copying files into /Users/wudaxun/Desktop/workspace/code/bk2207A/code/react-course/react-basic
  Adding /config/env.js to the project
  Adding /config/getHttpsConfig.js to the project
  Adding /config/modules.js to the project
  Adding /config/paths.js to the project
  Adding /config/webpack.config.js to the project
  Adding /config/webpackDevServer.config.js to the project
  Adding /config/jest/babelTransform.js to the project
  Adding /config/jest/cssTransform.js to the project
  Adding /config/jest/fileTransform.js to the project
  Adding /scripts/build.js to the project
  Adding /scripts/start.js to the project
  Adding /scripts/test.js to the project
  Adding /config/webpack/persistentCache/createEnvironmentHash.js to the project

Updating the dependencies
  Removing react-scripts from dependencies
  Adding @babel/core to dependencies
  Adding @pmmmwh/react-refresh-webpack-plugin to dependencies
  Adding @svgr/webpack to dependencies
  Adding babel-jest to dependencies
  Adding babel-loader to dependencies
  Adding babel-plugin-named-asset-import to dependencies
  Adding babel-preset-react-app to dependencies
  Adding bfj to dependencies
  Adding browserslist to dependencies
  Adding camelcase to dependencies
  Adding case-sensitive-paths-webpack-plugin to dependencies
  Adding css-loader to dependencies
  Adding css-minimizer-webpack-plugin to dependencies
  Adding dotenv to dependencies
  Adding dotenv-expand to dependencies
  Adding eslint to dependencies
  Adding eslint-config-react-app to dependencies
  Adding eslint-webpack-plugin to dependencies
  Adding file-loader to dependencies
  Adding fs-extra to dependencies
  Adding html-webpack-plugin to dependencies
  Adding identity-obj-proxy to dependencies
  Adding jest to dependencies
  Adding jest-resolve to dependencies
  Adding jest-watch-typeahead to dependencies
  Adding mini-css-extract-plugin to dependencies
  Adding postcss to dependencies
  Adding postcss-flexbugs-fixes to dependencies
  Adding postcss-loader to dependencies
  Adding postcss-normalize to dependencies
  Adding postcss-preset-env to dependencies
  Adding prompts to dependencies
  Adding react-app-polyfill to dependencies
  Adding react-dev-utils to dependencies
  Adding react-refresh to dependencies
  Adding resolve to dependencies
  Adding resolve-url-loader to dependencies
  Adding sass-loader to dependencies
  Adding semver to dependencies
  Adding source-map-loader to dependencies
  Adding style-loader to dependencies
  Adding tailwindcss to dependencies
  Adding terser-webpack-plugin to dependencies
  Adding webpack to dependencies
  Adding webpack-dev-server to dependencies
  Adding webpack-manifest-plugin to dependencies
  Adding workbox-webpack-plugin to dependencies

Updating the scripts
  Replacing "react-scripts start" with "node scripts/start.js"
  Replacing "react-scripts build" with "node scripts/build.js"
  Replacing "react-scripts test" with "node scripts/test.js"

Configuring package.json
  Adding Jest configuration
  Adding Babel preset

Running npm install...

up to date in 4s

203 packages are looking for funding
  run `npm fund` for details
Ejected successfully!
$ npm start
$ npm build

2.4 webpack 二次封装

2.4.1 集成 css 预处理器

  • 集成 less 预处理器
$ cnpm i less less-loader -D
  • 集成 sass 预处理器
$ cnpm i node-sass -D
  • 集成 stylus 预处理器
$ cnpm i stylus stylus-loader -D

具体配置如下:

React-basic/config/webpack.config.js

// style files regexes 可以搜索此关键字快速定位
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;
const stylusRegex = /\.stylus/;
const stylusModuleRegex = /\.module\.stylus/;

// "postcss" loader applies autoprefixer to our CSS.可以搜索此关键字快速定位
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader turns CSS into JS modules that inject