This project was bootstrapped with Create React App.
In the project directory, you can run:
安装项目依赖
Runs the app in the development mode.
Open http://localhost:3000 to view it in your browser.
The page will reload when you make changes.
You may also see any lint errors in the console.
Launches the test runner in the interactive watch mode.
See the section about running tests for more information.
Builds the app for production to the build
folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
See the section about deployment for more information.
Note: this is a one-way operation. Once you eject
, you can't go back!
If you aren't satisfied with the build tool and configuration choices, you can eject
at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject
will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
You don't have to ever use eject
. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
# 创建my-app项目
npx create-react-app my-app
# 进入到项
cd my-app
# 启动项目
npm start
-src
-apis 项目接口函数
-assets 项目资源文件,比如,图片等
-components 通用组件
-pages 页面组件
-router 路由配置
-store 集中状态管理
-utils 工具,比如,token、axios 的封装等
-App.js 根组件
-index.css 全局样式
-index.js 项目入口
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.css'
import App from "./App"
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App/>
</React.StrictMode>
)
const App = () => {
return <div>this is app</div>
}
export default App
项目背景:在业务开发过程中文件夹的嵌套层级可能会比较深,通过传统的路径选择会比较麻烦也容易出错,设置路径别名可以简化这个过程
- 安装
craco
工具包 - 增加
craco.config.js
配置文件 - 修改
scripts 命令
- 测试是否生效
npm i @craco/craco -D
const path = require('path')
module.exports = {
// webpack 配置
webpack: {
// 配置别名
alias: {
// 约定:使用 @ 表示 src 文件所在路径
'@': path.resolve(__dirname, 'src')
}
}
}
{
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test",
"eject": "react-scripts eject"
}
}
实现步骤
- 在项目根目录创建
jsconfig.json
配置文件 - 在配置文件中添加以下配置
代码实现
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
}
}
}
说明:VSCode与WebStorm会自动读取jsconfig.json
中的配置,让ide知道@就是src目录
1、安装解析 sass 的包:npm i sass -D
2、创建全局样式文件:src/index.scss
3、测试scss是否能正常工作:
body {
margin: 0;
div {
color: blue;
}
}
npm install antd --save
import { Button } from 'antd';
const App = () => {
return <div><Button>click me</Button></div>
}
export default App
npm i react-router-dom
pages/Layout/index.js
const Layout = () => {
return <div>this is layout</div>
}
export default Layout
pages/Login/index.js
const Login = () => {
return <div>this is login</div>
}
export default Login
router/index.js
import {createBrowserRouter} from 'react-router-dom'
import Login from '../pages/Login'
import Layout from '../pages/Layout'
const router = createBrowserRouter([
{
path: '/',
element: <Layout/>,
},
{
path: '/login',
element: <Login/>,
},
])
export default router
index.js
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.scss'
import router from './router'
import {RouterProvider} from 'react-router-dom'
ReactDOM.createRoot(document.getElementById('root')).render(
<RouterProvider router={router}/>
)
实现步骤
- 安装 axios 到项目
- 创建 utils/request.js 文件
- 创建 axios 实例,配置
baseURL,请求拦截器,响应拦截器
- 在 utils/index.js 中,统一导出request
npm i axios
import axios from 'axios'
// 配置请求实例
const request = axios.create({
baseURL: 'http://example.com',
timeout: 5000
})
// 添加请求拦截器
request.interceptors.request.use((config)=> {
return config
}, (error)=> {
return Promise.reject(error)
})
// 添加响应拦截器
request.interceptors.response.use((response)=> {
console.log(response)
return response.data
}, (error)=> {
console.log(error)
return Promise.reject(error)
})
export { request }
import { request } from './request'
export { request }
npm i react-redux @reduxjs/toolkit
import {createSlice} from '@reduxjs/toolkit'
const userStore = createSlice({
name: "user",
// 数据状态
initialState: {
token: '',
userInfo: {}
},
// 同步修改方法
reducers: {
setToken(state, action) {
state.token = action.payload
},
setUserInfo(state, action) {
state.userInfo = action.payload
},
clearUserInfo(state) {
state.token = ''
state.userInfo = {}
}
}
})
// 解构出actionCreator
const {setToken, setUserInfo, clearUserInfo} = userStore.actions
// 获取reducer函数
const userReducer = userStore.reducer
export default userReducer
// 组合redux子模块 + 导出store实例
import { configureStore } from '@reduxjs/toolkit'
import userReducer from './modules/user'
export default configureStore({
reducer: {
user: userReducer
}
})
@/index.js
import React from 'react'
import ReactDOM from 'react-dom/client'
import '@/index.scss'
import router from '@/router'
import {RouterProvider} from 'react-router-dom'
import {Provider} from "react-redux";
import store from "@/store";
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<Provider store={store}>
<RouterProvider router={router}/>
</Provider>
)
pages/Login/index.js
import './index.scss'
import {Card, Form, Input, Button} from 'antd'
const Login = () => {
// form绑定了onFinish事件,当表单提交时自动触发,并将表单数据作为参数传入
const onFinish = (values) => {
console.log('Received values of form: ', values)
}
return (
<div className="login">
<Card className="login-container">
<Form onFinish={onFinish} validateTrigger={['onBlur']}>
<Form.Item
name="mobile"
// 多条校验规则,按顺序执行串行校验
rules={[
{required: true, message: '请输入手机号'},
{
pattern: /^1[3-9]\d{9}$/,
message: '手机号码格式不对'
}
]}
>
<Input size="large" placeholder="请输入手机号"/>
</Form.Item>
<Form.Item
name="code"
rules={[
{required: true, message: '请输入验证码'},
]}
>
<Input size="large" placeholder="请输入验证码" maxLength={6}/>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" size="large" block>
登录
</Button>
</Form.Item>
</Form>
</Card>
</div>
)
}
export default Login
pages/Login/index.scss
.login {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
.login-logo {
width: 200px;
height: 60px;
display: block;
margin: 0 auto 20px;
}
.login-container {
width: 440px;
height: 360px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 0 50px rgb(0 0 0 / 10%);
}
.login-checkbox-label {
color: #1890ff;
}
}
参考文献: https://segmentfault.com/a/1190000044085567#item-1 https://segmentfault.com/a/1190000041847944 https://blog.csdn.net/sinat_36728518/article/details/106971471
整合以下工具: eslint prettier git hooks husky lint-staged commitlint stylelint