个人文档
  • AI编程Cursor
  • GPT使用笔记
  • npm常用库合集
  • 同步用
  • 小Demo们
  • 工具网站教程集合
  • HTML、CSS 工具方法集合
    • HTML 全局属性
    • css常用功能
    • font-face 字体|子集相关
    • iframe父子页面传值
    • input输入优化
    • loading状态
    • nodejs使用谷歌邮箱发邮件
    • 为 Dom 自定义事件监听
    • 初始html的head标签配置
    • 拼音输入中文汉字的事件监听
    • 文字颜色效果
    • 文档片段范围 Range
    • 移动端开发-rem
    • 等宽字体推荐
    • 网站SEO优化注意点
    • 邮件html模板
  • JS 工具方法集合
    • Axios 简单使用
    • Axios 简单封装
    • Gitbook的安装和使用
    • Github 登录开发
    • HTML转为纯文本
    • JS 中强大的操作符
    • cookie 操作
    • js 动态加载js资源
    • js 常用功能语句
    • js取代trycatch的方法封装
    • js接口下载二进制
    • script 标签的异步属性
    • 判断当前是移动端还是pc端
    • 刷新token队列管理
    • 前端多线程 Web Worker
    • 加密-AES对称加密
    • 加密-node进行rsa加密解密
    • 地区省市区三级联动的地址数据 + 功能
    • 复制插件
    • 开发时环境变量
    • 得到随机图片
    • 数字格式整理集合
    • 数学计算插件
    • 时间格式整理
    • 获取ip地址
    • 获取url传参
    • 进制转换和位运算符
    • 页面隐藏|激活|关闭的监听
  • JS 知识点研究
    • Babel 历史和原理
    • Babel 配置和使用
    • Function 的 apply、call、bind
    • HTTP浏览器缓存粗解
    • Source map 文件还原为源码
    • TS常用技巧
    • js 的加载和模块化
    • js 的新数据类型 Symbol
    • js的代理对象 proxy 和 defineProperty
    • js的原型链 prototype
    • vite 打包体积优化
    • webpack 可视化打包文件大小插件
    • webpack 基础使用配置
    • webpack 版本5的报错
    • yeoman 开发脚手架的工具
    • 同步异步和微任务宏任务
    • 移动端调试---谷歌工具+eruda+vconsole
    • 转换-Blob URL
    • 转换-FileReader
    • 转换-Js文件类型和转换
    • 转换-前端开发的URL的编码和解码
    • 转换-字符串和Base 64的转换
  • Node 和 Npm 相关
    • Node 开发环境配置
    • express + jwt 校验
    • node 常用方法
    • node后台服务器-PM2
    • node基本使用
    • npm 中依赖的版本问题
    • npm 功能使用
    • npm指令说明和其他对比
    • nvm版本管理+自动切换node版本
  • React 学习
    • React Hook
    • React 项目基础开发
    • React.memo 和 React.PureComponent
    • React懒加载进阶
    • useContext Hook
    • useEffect Hook
    • useMemo 和 useCallback - Hook
    • useRef Hook
    • useState Hook
    • 同步修改变量功能封装 useVal for react
    • 轻便的传值组件
  • Rust 语言相关
    • Rust 基本
    • Rust 基础学习
    • Rust 调用 Object-C 的API
    • Tauri 基本使用
    • Tauri 是什么
  • VUE 学习
    • Vue3 使用
    • Vue3使用hook
    • Vue开发小技术点
    • vue路由切换时的动画效果
    • 花式引入组件和资源-打包时拆包减少js体积
  • Web3相关
    • Web3.0开发上-准备和概念理解
    • Web3.0开发下-功能代码示例
    • 以太坊区块链和Web3.0
    • 开发智能合约
  • python
    • pyenv版本管理工具
    • python初始化
    • python基本概念
    • venv虚拟环境
  • 个人其他
    • Steam Deck的基本设置和插件
  • 其他编程相关
    • Git教程和常用命令
    • Java开发-JDK和Maven的安装和卸载
    • Jenkins安装和基本使用
    • Linux系统指令
    • Mac 使用2K屏幕开启缩放
    • Mac 使用VS code打开项目
    • Mac 安装 Homebrew
    • Mac 的终端 shell 与 zsh
    • Mac 软件和插件
    • MacBook使用建议
    • Mac升降级到指定版本的系统
    • Mac安装Zsh
    • Mac安装软件各种提示
    • Mac系统脚本语言 AppleScript 的使用
    • Mac终端代理工具
    • Markdown(md)文档开发-Typora
    • Mysql 的安装和使用
    • Nginx 安装和基础使用
    • Nginx 稍微高深的配置
    • Slate - Api 的文档开发工具
    • Sublime配置
    • Ubuntu的 apt-get 使用
    • VScode配置
    • Windows 软件和插件
    • curl 工具使用
    • github 网站访问优化
    • host 文件
    • inquirer 终端中和用户交互
    • uTools的插件开发教程
    • vim 文本编辑功能
    • 使用 Github Pages 免费部署网站
    • 压缩指令 zip 和 unzip
    • 油猴的安装和开发(Tampermonkey)
    • 阿里云简略使用
  • 微信开发
    • 微信小程序开发
    • 微信开发必读
    • 微信开发提前购买域名
    • 微信手机打开的页面中授权登录
    • 微信扫码登录
    • 微信服务号登录+推送服务提醒
    • 自定义分享卡片-node.js实现
  • 数据结构与算法
    • KMP算法
    • Wildcard字符串分析算法
    • 二叉树
    • 字典树
    • 时间复杂度浅析
    • 算法神器——动态规划
Powered by GitBook
On this page

Was this helpful?

  1. React 学习

React 项目基础开发

title: React 项目基础开发 id: c8d0dfe2ef55c6148cd09399cda40fef tags: [] date: 2000/01/01 00:00:00 updated: 2024/05/07 14:45:19 isPublic: true --#|[分隔]|#--

React 项目基础开发

创建项目

使用大名鼎鼎的 cra (create-react-app)创建react项目

1. 首先使用 npm 全局安装

这一步其实可以省略,因为可以使用 npx,见下一步。

npm i -g create-react-app

2. 使用 create-react-app 创建项目

使用 create-react-app [项目名称] 的格式创建项目:

create-react-app react-demo

# 将在当前终端的文件夹创建一个名称为 react-demo 的文件夹
# 文件里面就是项目了

上一步说可以不全局安装 create-react-app,是因为现在的 node 除了 npm ,还提供了 npx 这个工具。

npx 允许用户使用一些需要先提前全局安装的工具时,比如 pm2、cnpm、yarn 等,可以不全局安装了,可以在这些指令的使用语句的前面,直接添加 npx。

这样的好处是,一些使用频率很低的工具,不用全局安装了,而是使用 npx 来「临时」使用。

比如没有全局安装 create-react-app 时,直接使用下面的指令:

npx create-react-app react-demo

npx 如果检测到系统没有这个指令,就会先自动先下载这个工具,然后再使用这个工具执行后面的命令,最终所有指令完成后,这个工具会自动移除(实际可能是会只存在缓存区)。

项目编译的配置

完成安装后,可以进行一些常用配置。

修改webpack配置的途径

新版的 create-react-app 是隐藏配置的,想修改 webpack 配置,最傻瓜式的方式是执行 cra 提供的下面的这条指令,弹出所有 webpack 配置来修改,但这么操作实在太不友好了,所有配置文件夹、配置文件都出现在项目里,很杂乱且不能再收回去:

# 这条指令就在 create-react-app 创建的项目的 package.json 的指令中
npm run eject

因为上面的操作很不友好,所以我们一般会采用其他的工具来merge式的修改配置,最常用的工具就是 react-app-rewired 了。

先在项目中安装工具:

npm i -D react-app-rewired

然后修改 package.json 中的指令:

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

接着在项目根目录(package.json同级) 创建文件 config-overrides.js,内容如下:

const path = require('path');

module.exports = (config, env) => {
  // env 顾名思义,就是环境变量配置
  // config 就是 webpack 配置文件,可以修改里面的项,最后会并入 webpack 的配置中
  // 从 config 可以读取到 entry、output、plugins、resolve……等等配置,可以进行修改

  // 查看 config.entry 配置
  console.log(config.entry)
  
  // 修改配置
  config.resolve = {
    ...(config.resolve ||  {}),
    alias: {
      ...(config.resolve.alias ||  {}),
      // 添加别名 alias
      app: path.join(__dirname, "src"),
    },
    // 针对 webpack >= 5 时需要单独导入node模块的配置
    // fallback: {
    //   ...(config.resolve.fallback || {}),
    //   crypto: require.resolve('crypto-browserify'),
    //   path: require.resolve('path-browserify'),
    //   http: require.resolve('stream-http'),
    //   https: require.resolve('https-browserify'),
    //   stream: require.resolve('stream-browserify'),
    // }
  }

  return config
}

.env文件进行配置修改

根目录下的 .env 文件同样可以做一些配置,比如:

# 本地启动服务时不自动使用浏览器打开页面
BROWSER=none

# 修改启本地服务时的端口号
PORT=3012

# 打包时不构建sourceMap文件
GENERATE_SOURCEMAP=false

3. 打包后的引入静态资源时使用相对路径

默认情况,打包后生成的静态项目,里面引入js\css\图片\字体时,使用的是绝对路径 /,这就导致我们无法双击index.html来预览项目(就算react路由模式使用的是hash模式也不行)。

所以可以给 package.json 文件添加一项:

{
  // ...其他配置
  "homepage": "./",
}

这样打包完成后,引入文件的方式就都是相对路径 ./ 的形式了。

项目开发的配置

项目开始开发后,需要进行项目调整,比如配置路由、添加sass支持等。

首先是上面说到的修改 webpack 配置的工具 react-app-rewired,这里不再赘述。

less 还是 scss

node-sass 经常出问题,现在官方也已经不推荐使用 node-sass ,明确 node-sass 以后只会进行对新版本node的兼容更新,不会再添加新功能。

官方现在的建议,是使用 dark-sass,而 dark-sass 只是这种用法的名字,具体的使用,就是安装下面两个插件:

npm i -D sass sass-loader

安装上面两个依赖后,可实现 node-sass 同样的效果(样式穿透的写法有不同,见其他文档)。

此外,也可以使用less,而且,如果使用antd样式框架,那最好使用less,因为antd使用的就是less,如果想自定义修改antd的全局样式变量,就必须使用less了。

全局状态管理 redux

用处不用说了,首先安装需要的依赖:

npm i -S redux react-redux redux-thunk

接着创建文件夹 src/store,里面创建四个文件:

  • defaultState.js:全局状态数据的默认值们。

  • reducers.js:数据的分发。

  • actions.js:管理数据的 action 动作们。

  • index.js::把上面的东西统一规整暴露出去的文件。

下面一次性把四个文件中的内容大致写一下:

// defaultState.js 文件中
const defaultState = {
  flagNum: 0,
};
export default defaultState;

// reducers.js 文件中
import { combineReducers } from "redux"; // 工具函数,用于组织多个reducer,并返回reducer集合
import defaultState from "./defaultState"; // 默认值
// 测试字段
function flagNum(data = defaultState.flagNum, action) {
  switch (action.type) {
    case "SET_FLAGNUM":
      return action.data;
    default:
      return data;
  }
}
// 导出所有reducer
export default combineReducers({
  flagNum,
});

// actions.js 文件中
export function init() {
  return async (dispatch, getState) => {
    const state = getState()
    const text = `页面初始化时 flagNum 的值:${state.flagNum}`
    console.log(text);
    // 是否 return 都可以
    return new Promise(resolve => {
      resolve();
    })
  };
}

// index.js 文件中
import { applyMiddleware, createStore } from "redux";
// 中间件,作用:如果不使用该中间件,当我们dispatch一个action时,需要给dispatch函数传入action对象;
// 但如果我们使用了这个中间件,那么就可以传入一个函数,这个函数接收两个参数:dispatch和getState。
// 这个dispatch可以在将来的异步请求完成后使用,对于异步action很有用
import thunk from "redux-thunk";
// 引入reducer
import reducers from "./reducers.js";
// 创建store实例
let store = createStore(reducers, applyMiddleware(thunk));
export default store;

下面把 redux 注入到全局,src/index.js 中:

import React from 'react';
import ReactDOM from "react-dom/client";
import Router from "./router";
// 引入redux
import { Provider } from "react-redux";
import store from "app/store";

const root = ReactDOM.createRoot(document.getElementById('root'));
// 修改写法,使用 Provider 包裹并注入 store
root.render(
  <Provider store={store}>
    <Router />
  </Provider>
)

最后是在某个组件中使用,这里以 react 推荐的函数式组件为例:

import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
// 引入要使用的动作
import { init } from "../../store/actions";

export default function Button() {
  // 初始化 dispatch
  const dispatch = useDispatch()
  useEffect(() => {
    // 用 dispatch 执行再 actions 中写好的方法
    // 可以放在函数中,使用异步 async/await 执行
    dispatch(init())
  }, [dispatch])

  // 获取全局变量
  const flagNum = useSelector(state => state.flagNum);
  const addFlag = () => {
    // 用 dispatch 修改某个变量
    dispatch({ type: "SET_FLAGNUM", data: flagNum + 1 })
  }
  return (
    <button onClick={addFlag}>点击加值:{flagNum}</button>
  );
}

项目中报错

BREAKING CHANGE: webpack < 5 的报错

webpack 5 官方解决方案。

最新版的 cra 项目中,使用node核心模块时,比如使用 path 时会发生类似以下报错:

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
        - add a fallback 'resolve.fallback: { "path": require.resolve("path-browserify") }'
        - install 'path-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
        resolve.fallback: { "path": false }

这是 webpack 新版本本身的特性,意思是webpack < 5版本时,自带node.js的核心模块,但大于等于5时,不会了,如果项目想使用类似 path、http、fs……这些模块时,需要自己安装对应的模块并进行webpack配置,才能使用了(还有一个办法,就是不使用webpack了,这种因噎废食的做法应该很少人采用)。

具体修正方法,见我这里另一个文档 webpack 版本5的报错。

PreviousReact HookNextReact.memo 和 React.PureComponent

Last updated 3 months ago

Was this helpful?