一、开发前言
1. 规范
2. 创建项目
node -v => 18.0.0
npm -v => 8.6.0
create-react-app star-airbnb
3. 项目基本配置
配置jsconfig.json
{"compilerOptions": {"target": "es5","module": "esnext","baseUrl": "./","moduleResolution": "node","paths": {"@/*": ["src/*"]},"jsx": "preserve","lib": ["esnext","dom","dom.iterable","scripthost"]}
}
通过craco配置
react脚手架隐藏webpack
解决一 : npm run eject
导出webpack配置,要去找到对应的配置,如果修改错误,项目可能跑不起来
解决二 : 通过craco => create-react-app config
配置后,会与原来的webpack配置混合
npm install @craco/craco@alpha -D => "react-scripts": "5.0.1"
新建 craco.config.js文件
/* package.json */
"scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test",
+ "start": "craco start",
+ "build": "craco build",
+ "test": "craco test",
}
别名
const path = require('path');const resolve = (pathName) => path.resolve(__dirname, pathName);module.exports = {// webpackwebpack: {alias: {'@': resolve('src'),'assets': resolve('src/assets'),'components': resolve('src/components'),'view': resolve('src/view'),'store': resolve('src/store'),'utils': resolve('src/utils'),'router': resolve('src/router'),'services': resolve('src/services'),'baseUi': resolve('src/base-ui')}}
};
less文件
可查看 Ant Design 这里所用是4点多的版本
npm i craco-less@2.1.0-alpha.0
const path = require('path');
const resolve = (pathName) => path.resolve(__dirname, pathName);const CracoLessPlugin = require('craco-less');module.exports = {// lessplugins: [{plugin: CracoLessPlugin,options: {lessLoaderOptions: {lessOptions: {// modifyVars: { '@primary-color': '#1DA57A' },javascriptEnabled: true}}}}],// webpackwebpack: {alias: {'@': resolve('src'),assets: resolve('src/assets'),components: resolve('src/components'),view: resolve('src/view'),store: resolve('src/store'),utils: resolve('src/utils'),router: resolve('src/router'),services: resolve('src/services'),baseUi: resolve('src/base-ui')}}
};
css样式重置
对默认CSS样式进行重置
normalize.css
npm install normalize.css
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import 'normalize.css';const root = ReactDOM.createRoot(document.getElementById('root'));root.render(<React.StrictMode><App /></React.StrictMode>
);
reset.css
@mainColor: #484848;blockquote, body, button, dd, dl, dt, fieldset, form, h1, h2, h3, h4, h5, h6, hr, input, legend, li, ol, p, pre, td, textarea, th, ul {// color: @mainColor;padding: 0;margin: 0;
}a {color: @mainColor;text-decoration: none;
}img {vertical-align: top;
}body {font-size: 14px;font-family: Circular, "PingFang-SC", "Hiragino Sans GB", "微软雅黑", "Microsoft YaHei", "Heiti SC" ;-webkit-font-smoothing: antialiased;
}
目录结构划分
4. 主题配置
项目使用styled-components,可用于配置主题
配置
theme/index.js
export const theme = {color: {$primaryColor: '#FF385C',$secondaryColor: '#00848A',$textColor: '#484848',$textColorSecondary: '#222222'},fontSize: {$small: '12px',$normal: '14px',$large: '16px'},mixin: {$boxShadow: `transition: box-shadow 0.2s ease;&:hover {box-shadow: 0 2px 4px rgba(0,0,0,0.18);}`}
};export default theme;
index.js
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom/client';
import { HashRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
// 1. 引入 Provider
import { ThemeProvider } from 'styled-components';import App from './App';
import store from './store';
import 'normalize.css';
import 'assets/css/index.less';
import { theme } from './theme';const root = ReactDOM.createRoot(document.getElementById('root'));root.render(<Provider store={store}>{/* 2. 使用主题 */}<ThemeProvider theme={theme}><HashRouter><Suspense fallback={<div>Loading...</div>}><App /></Suspense></HashRouter></ThemeProvider></Provider>
);
组件使用
import styled from 'styled-components';export const LeftWrapper = styled.div.attrs((props) => ({// 1. 使用主题, 通过 props.theme 获取主题$primaryColor: props.theme.color.$primaryColor,$secondaryColor: props.theme.color.$secondaryColor
}))`flex: 1;display: flex;align-items: center;/* 2. 使用,这里是用一个回调函数 */color: ${({ $primaryColor }) => $primaryColor};.log {cursor: pointer;}
`;
5. 路由配置
npm install react-router-dom
router/index.js
import React, { lazy } from 'react';
import { Navigate } from 'react-router-dom';const Home = lazy(() => import('view/home'));
const Entire = lazy(() => import('view/entire'));
const Detail = lazy(() => import('view/detail'));const routes = [{path: '/',element: <Navigate to='/home' />},{path: '/home',element: <Home />},{path: '/entire',element: <Entire />},{path: '/detail',element: <Detail />}
];export default routes;
index.js
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom/client';
import { HashRouter } from 'react-router-dom';import App from './App';
import 'normalize.css';
import 'assets/css/index.less';const root = ReactDOM.createRoot(document.getElementById('root'));root.render(<React.StrictMode><HashRouter><Suspense fallback={<div>Loading...</div>}><App /></Suspense></HashRouter></React.StrictMode>
);
App.jsx
import React, { memo } from 'react';
import { useRoutes } from 'react-router-dom';import routes from 'router';const App = memo(() => {return (<><div className='header'>header</div><div className='main-contain'>{useRoutes(routes)}</div><div className='footer'>footer</div></>);
});export default App;
6. redux状态管理配置
npm install @reduxjs/toolkit react-redux
store
modules
home.js
home.js => 使用rtk模式
import { createSlice } from '@reduxjs/toolkit';const homeSlice = createSlice({name: 'home',initialState: {a: [1, 2, 3, 4]},reducers: {}
});export default homeSlice.reducer;
entire文件夹
entire => 使用原生模式,所以有四个文件
reducer.js
const initialState = {b: [1, 2, 3, 4]
};const reducer = (state = initialState, action) => {switch (action.type) {// case 'ADD_USER':// return {// ...state,// [action.payload.id]: action.payload// };default:return state;}
};export default reducer;
index.js
import reducer from './reducer';export default reducer;
index.js
import { configureStore } from '@reduxjs/toolkit';
import homeReducer from './modules/home';
// 直接使用原生的entire,也是一样的,因为createSlice就是对原生的一种封装而已
import entireReducer from './modules/entire';const store = configureStore({reducer: {home: homeReducer,entire: entireReducer}
});export default store;
index.js
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom/client';
import { HashRouter } from 'react-router-dom';import { Provider } from 'react-redux';
import App from './App';
import store from './store';
import 'normalize.css';
import 'assets/css/index.less';const root = ReactDOM.createRoot(document.getElementById('root'));root.render(<React.StrictMode><Provider store={store}><HashRouter><Suspense fallback={<div>Loading...</div>}><App /></Suspense></HashRouter></Provider></React.StrictMode>
);
7. 网络请求 - axios配置
npm install axios
requset
config.js
export const BASE_URL = 'http://xxxxxx';
export const TIME_OUT = 20000;
index.js
import axios from 'axios';
import { BASE_URL, TIME_OUT } from './config';class StarRequest {constructor(baseURL, timeout) {this.instance = axios.create({baseURL,timeout});this.instance.interceptors.response.use((res) => {return res.data;},(err) => {return err;});}request(config) {return this.instance(config);}get(config) {return this.request({ ...config, method: 'get' });}post(config) {return this.request({ ...config, method: 'post' });}
}const starRequest = new StarRequest(BASE_URL, TIME_OUT);
export default starRequest;
index.js
import starRequest from './request';export default starRequest;
简单使用
import React, { memo, useEffect, useState } from 'react';
import starRequest from '@/services';const Home = memo(() => {// 定义状态const [highscore, sethighscore] = useState({});// 请求useEffect(() => {starRequest.get({ url: '/home/highscore' }).then((res) => {console.log(res);sethighscore(res);});}, []);return (<><div>Home</div><div>{highscore.title}</div></>);
});export default Home;
二、注意事项
图片问题
导入需使用import | require 导入方可使用
不论是背景图片还是img使用图片
import导入
import styled from 'styled-components';
import coverPic from '@/assets/img/cover_01.jpeg';export const BannerWrapper = styled.div`height: 529px;background: url(${coverPic}) center center/cover;
`;
require导入
import styled from 'styled-components';export const BannerWrapper = styled.div`height: 529px;background: url(${require('@/assets/img/cover_01.jpeg')}) center center/cover;/* 根据webpack版本不同,可能需要加default *//* background: url(${require('@/assets/img/cover_01.jpeg').default}) center center/cover; */
`;
三、引入组件库
Material-Ui
安装
npm install @mui/material @mui/styled-engine-sc
配置
const path = require('path');
const resolve = (pathName) => path.resolve(__dirname, pathName);const CracoLessPlugin = require('craco-less');module.exports = {// lessplugins: [{plugin: CracoLessPlugin,options: {lessLoaderOptions: {lessOptions: {// modifyVars: { '@primary-color': '#1DA57A' },javascriptEnabled: true}}}}],// webpackwebpack: {alias: {'@': resolve('src'),assets: resolve('src/assets'),components: resolve('src/components'),view: resolve('src/view'),store: resolve('src/store'),utils: resolve('src/utils'),router: resolve('src/router'),services: resolve('src/services'),baseUi: resolve('src/base-ui'),// ++++++++++++++++'@mui/styled-engine': '@mui/styled-engine-sc'}}
};
Ant-Design
安装
npm install antd
使用
// 直接组件中使用即可import { Button } from 'antd';<Button type='primary'>Button</Button>
四、项目效果
小视频