创建方式
(1)next.js(推荐)服务端渲染
npx 运行这些命令,而不需要全局安装模块
npx create-next-app@latest //@13.4.12
(2)脚手架(react18版本已不再推荐,推荐nest.js)
//首先通过npm全局安装create-react-app
npm install -g create-react-app
//然后使用create-react-app命令来创建项目
create-react-app <项目名>
//创建my-app项目
create-react-app my-app
cd my-app
npm run start 或 yarn start
NPM开始
启动开发服务器。
NPM运行构建
将应用捆绑到生产环境的静态文件中。
NPM测试
启动测试运行程序。
NPM运行弹出
删除此工具并复制构建依赖项、配置文件
并将脚本放入app目录。如果你这么做,你就回不去了!
$ yarn eject 暴露webpack配置项
(3)vite
npm create vite@latest
✔ Project name: vite-project(自定义项目名)
? Select a framework: › - Use arrow-keys. Return to submit.
vanilla // 无前端框架
vue // 基于 Vue
> react // 基于 React
preact // 基于 Preact(一款精简版的类 React 框架)
lit // 基于 lit(一款 Web Components 框架)
svelte // 基于 Svelte
cd vite-project
npm install
npm run dev
props规则校验
配置状态管理
redux原始写法
redux
store目录创建store容器
redux工程化处理
- 把reducer/状态管理按照模块化划分,把所有模块的reducer合并为一个即可
- 每一次派发,都把所有模块的reducer,以次执行,派发时传递的行为对象(行为标识)是统一 的,所以要保证各个模块之间派发的行为标识唯一性,==派发行为标识管理action-types.js文件
- 创建action/对象,按模块管理我们需要派发的行为对象,把所有模块的action合并为一个即可
redux使用
react-redux
入门 React Redux | React Redux 中文文档 (react-redux.js.org)
npm install react-redux
# Or
yarn add react-redux
"redux": "^4.2.0",
//中间件
"redux-logger": "^3.0.6", "redux-promise": "^0.6.0", "redux-thunk": "^2.4.2",
配置redux架子
---结构
react-ToolKit (RTK)
开始使用 |Redux 工具包 (redux-toolkit.js.org)
npm i react-redux @reduxjs/toolkit
zustand
zustand (React) | ZUSTAND (awesomedevin.github.io)
npm install zustand # or yarn add zustand
mobx
安装: `npm install mobx --save`。
React 绑定库: `npm install mobx-react --save`
npm install mobx mobx-react //支持函数组件和类组件
npm install mobx mobx-react-lite //仅支持函数组件
配置router
src/router
---index.js 路由入口
---router.js路由表
import React, { Suspense, useState, useEffect } from 'react'
import {
Routes,
Route,
useNavigate,
useLocation,
useParams,
useSearchParams,
} from 'react-router-dom'
import routes from './routes'
import { Mask, DotLoading, Toast } from 'antd-mobile'
import store from '../store'
import action from '../store/action'
/* 统一路由配置 */
const isCheckLogin = (path) => {
let {
base: { info },
} = store.getState(),
checkList = ['/personal', '/store', '/update']
return !info && checkList.includes(path)
}
const Element = function Element(props) {
let { component: Component, meta, path } = props
let isShow = !isCheckLogin(path)
let [_, setRandom] = useState(0)
// 登录态校验
useEffect(() => {
if (isShow) return
;(async () => {
let infoAction = await action.base.queryUserInfoAsync()
let info = infoAction.info
if (!info) {
// 如果获取后还是不存在:没有登录
Toast.show({
icon: 'fail',
content: '请先登录',
})
// 跳转到登录页
navigate(
{
pathname: '/login',
search: `?to=${path}`,
},
{ replace: true }
)
return
}
// 如果获取到了信息,说明是登录的,我们派发任务把信息存储到容器中
store.dispatch(infoAction)
setRandom(+new Date())
})()
})
// 修改页面的TITLE
let { title = '知乎日报-WebApp' } = meta || {}
document.title = title
// 获取路由信息,基于属性传递给组件
const navigate = useNavigate(),
location = useLocation(),
params = useParams(),
[usp] = useSearchParams()
return (
<>
{isShow ? (
<Component
navigate={navigate}
location={location}
params={params}
usp={usp}
/>
) : (
<Mask visible={true}>
<div style={{ color: '#00b578' }}>
<DotLoading color="currentColor" />
<span>正在加载</span>
</div>
</Mask>
)}
</>
)
}
export default function RouterView() {
return (
<Suspense
fallback={
<Mask visible={true}>
<div style={{ color: '#00b578' }}>
<DotLoading color="currentColor" />
<span>正在加载</span>
</div>
</Mask>
}
>
<Routes>
{routes.map((item) => {
let { name, path } = item
return (
<Route key={name} path={path} element={<Element {...item} />} />
)
})}
</Routes>
</Suspense>
)
}
//做路由懒加载,lazy方法
import { lazy } from 'react'
import Home from '../views/Home'
import { withKeepAlive } from 'keepalive-react-component'
const routes = [
{
path: '/',
name: 'home',
component: withKeepAlive(Home, { cacheId: 'home', scroll: true }),
meta: {
title: '知乎日报-WebApp',
},
},
{
path: '/detail/:id',
name: 'detail',
component: lazy(() => import('../views/Detail')),
meta: {
title: '新闻详情-知乎日报',
},
},
{
path: '/personal',
name: 'personal',
component: lazy(() => import('../views/Personal')),
meta: {
title: '个人中心-知乎日报',
},
},
{
path: '/store',
name: 'store',
component: lazy(() => import('../views/Store')),
meta: {
title: '我的收藏-知乎日报',
},
},
{
path: '/update',
name: 'update',
component: lazy(() => import('../views/Update')),
meta: {
title: '修改个人信息-知乎日报',
},
},
{
path: '/login',
name: 'login',
component: lazy(() => import('../views/Login')),
meta: {
title: '登录/注册-知乎日报',
},
},
{
path: '*',
name: '404',
component: lazy(() => import('../views/Page404')),
meta: {
title: '404页面-知乎日报',
},
},
]
export default routes
使用
import React from "react";
import { HashRouter } from 'react-router-dom';
//写好的路由
import RouterView from "./router";
import { KeepAliveProvider } from 'keepalive-react-component';
const App = function App() {
return <HashRouter>
<KeepAliveProvider>
<RouterView />
</KeepAliveProvider>
</HashRouter>;
};
export default App;
配置Ant Design
[Ant Design](Ant Design (antgroup.com))
import React from 'react';
import ReactDOM from 'react-dom/client';
import Task from './views/Task';
/* 使用ANTD组件库 */
import { ConfigProvider } from 'antd';
//汉化
import zhCN from 'antd/locale/zh_CN';
//全局样式
import './index.less';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<ConfigProvider locale={zhCN}>
<Task />
</ConfigProvider>
);
使用 在需要的地方按需引入即可
//例如
import {
Button,
DatePicker,
Form,
Input,
Modal,
Popconfirm,
Table,
Tag,
message,
} from 'antd'
配置Ant Design Mobile
快速上手 - Ant Design Mobile (antgroup.com)
在 Vite 项目中配置 @
-
基于 Vite 创建 React + TypeScript 的项目,具体创建项目的步骤,请参考 Vite 官方文档。 在 Vite 项目中配置
@路径提示-
安装 node 的类型声明:
npm i -D @types/node
-
2.配置 vite.config.ts 文件
// 1. 以 ES6 模块化的方式,从 Node 的 path 模块中,导入 join 函数
import { join } from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
// 2. 在 resolve.alias 对象下,配置 @ 的指向路径
resolve: {
alias: {
'@': join(__dirname, './src/')
}
}
})
3.配置 tsconfig.json 文件,在 compilerOptions 节点下,新增 "baseUrl": "." 和 "paths": { "@/*": [ "src/*" ] } 两项
{
"compilerOptions": {
/* 新增以下两个配置项,分别是 baseUrl 和 paths */
"baseUrl": ".",
"paths": {
"@/*": [
"src/*"
]
},
"target": "ES2020",
"useDefineForClassFields": true,
"lib": [
"ES2020",
"DOM",
"DOM.Iterable"
],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": [
"src"
],
"references": [
{
"path": "./tsconfig.node.json"
}
]
}
组件缓存# keepalive-react-component
-基于react开发出来的react缓存组件,类似于类似vue的keepalive包裹vue-router的效果功能
zhangrenyang/keepalive-react-component: keepalive-react-component是一个react缓存组件 (github.com)
npm install keepalive-react-component --save
# or
yarn add keepalive-react-component
做跨域
setupProxy.js文件
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function (app) {
app.use(
createProxyMiddleware("/api", {
target: "http://127.0.0.1:7100",
changeOrigin: true,
ws: true,
pathRewrite: { "^/api": "" }
})
);
};