1. 创建脚手架
npm install -g create-react-app //全局安装create-react-app
npx create-react-app hello-react --template typescript //创建React-typescript脚手架
2. 下载依赖
@craco/craco 环境配置
craco-less 用于语言转化
postcss-px-to-viewport-8-plugin 页面vw适配
postcss-pxtorem 页面rem适配
react-router-dom 路由
@reduxjs/toolkit 公共状态管理工具(新版)
react-redux 公共状态管理工具辅助包
antd 一款热门的UI组件
@ant-design/icons 图标
3. craco环境配置
在根目录下创建craco.config.js文件,文件内容如下
const CracoLessPlugin = require("craco-less");
module.exports = {
//配置Less语言转化
plugins: [{ plugin: CracoLessPlugin }],
//打包
webpack: {
alias: {
"@": resolve("src"),
},
configure: (webpackConfig, { env, paths }) => {
webpackConfig.output.path = path.resolve(__dirname, "dist");
paths.appBuild = path.resolve(__dirname, "dist");
webpackConfig.output = {
...webpackConfig.output,
publicPath: process.env.NODE_ENV === "production" ? "./" : "",
};
return webpackConfig;
},
},
//配置跨域
devServer: {
//自动启动
open: false,
//端口号
port: 8888,
//配置跨域
proxy: {
"/api": {
target: "https://m.douyu.com/api",
changeOrigin: true,
pathRewrite: {
"^/api": "",
},
},
},
},
//页面适配
style: {
postcss: {
mode: "extends",
loaderOptions: {
postcssOptions: {
ident: "postcss",
plugins: [
//vw适配
require("postcss-px-to-viewport-8-plugin")({
unitToConvert: "px", //需要转换的单位,默认为"px"
viewportWidth: 375, // 设计稿宽度
unitPrecision: 2, // 转化后的小数位
propList: ["*"], // * 表示所有px都要转化
viewportUnit: "vw", // 希望使用的视口单位
fontViewportUnit: "vw", //字体使用的视口单位
selectorBlackList: [], // 需要忽略的CSS选择器,不会转为视口单位,使用原有的px等单位。
minPixelValue: 1, // 设置最小的转换数值,如果为1的话,只有大于1的值会被转换
mediaQuery: false, // 媒体查询里的单位是否需要转换单位
replace: true, // 是否直接更换属性值,而不添加备用属性
exclude: [], // 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
include: undefined, // 如果设置了include,那将只有匹配到的文件才会被转换
landscape: false, // 是否添加根据 landscapeWidth 生成的媒体查询条件 @media (orientation: landscape)
landscapeUnit: "vw", // 横屏时使用的单位
landscapeWidth: 375, // 横屏时使用的视口宽度
}),
//rem适配
require("postcss-pxtorem")({
rootValue: 375 / 10, // 将设计稿尺寸按10等分划分,和adapt.js中的份数保持一致。rootValue是写设计稿尺寸,来算fontsize。
unitPrecision: 2, // 只转换到两位小数
propList: ["*"],// * 表示所有px都要转化
exclude: /node_modules/i, // 过滤掉node_modules 文件夹下面的样式
}),
],
},
},
},
},
};
在根目录下创建tsconfig.base.json文件 配置路径别名
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}
修改package.json文件
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test",
"eject": "react-scripts eject"
}
在tsconfig.json文件中添加
"extends": "./tsconfig.base.json"
4. 路由配置
首先在src目录下创建router.tsx文件,文件内容如下
import { createHashRouter } from "react-router-dom";
import App from "@/App";
import Home from "@/pages/Home";
const router = [
{
path: "/",
element: <App />,
children: [
{ path: "/home", element: <Home /> },
],
},
];
export default createHashRouter(router);
将路由注入到根目录下的index.jsx文件
import ReactDOM from "react-dom/client";
import { RouterProvider } from "react-router-dom";
import router from "./router";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(<RouterProvider router={router} />);
在App.jsx文件,引入Outlet标签
import { Outlet } from "react-router-dom";
function App() {
return (
<ProLayout title="后台管理系统">
<PageContainer>
<Outlet />
</PageContainer>
</ProLayout>
);
}
export default App;
5. 配置请求
在utils文件夹中创建fetch.ts文件
import { fetch } from "@dow/common";
import { message } from "antd";
import { Cookies } from "react-cookie";
var baseURL
if(process.env.NODE_ENV==='development'){
baseURL='http://development.dzj.com'
} else if(process.env.NODE_ENV==='test'){
baseURL='http://test.dzj.com'
} else if(process.env.NODE_ENV==='production'){
baseURL='http://production.dzj.com'
}
//在请求之前将本地cookies注入请求头中
const cookies = new Cookies();
fetch.interceptors.request.use(
(config) => {
config.headers.token = cookies.get('cookies')
return config
}
)
//请求之后将数据转化一下
fetch.interceptors.response.use(
async (res) => {
const { data } = await res.json();
return data
},
(err) => {
message.error('err')
return new Promise(() => { });
}
);
export default fetch;
使用的时候需要通过 import fetch from "@/utils/fetch" 引入处理好的fetch函数
6. redux公共状态管理
创建reducers.ts文件
import { createSlice } from "@reduxjs/toolkit";
const reducers = createSlice({
name: "cartSlick",
initialState: {
num: 0,
proct: 0,
},
reducers: {
//提供两个方法actions和reducer
setnum(state, action) {
state.num = action.payload;
},
setproct(state, action) {
state.proct = action.payload;
},
},
});
export const { setnum, setproct } = reducers.actions;
export default reducers.reducer;
创建store.ts文件
import { configureStore } from "@reduxjs/toolkit";
import reducers from "./reducers";
export default configureStore({
reducer: {
cartSlick: reducers,
},
});
修改根目录下的index文件
import ReactDOM from "react-dom/client";
import { RouterProvider } from "react-router-dom";
import router from "./router";
import { Provider } from "react-redux";
import store from "./redux/store";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(<Provider store={store}>
<RouterProvider router={router} />
</Provider>);
在组件中使用
import { useSelector , useDispatch } from "react-redux"
import { setnum } from "@/utils/reducers"
export default const Home=()=>{
//获取redux数据
const state = useSelector((state) => state);
//获取修改数据的方法
const dispath = useDispatch();
const clickid=()=>{
dispath(setnum(10))
}
return <button onClick={clickid}></button>
}
7. 环境变量
create-react-app 创建的项目有内置的环境变量NODE_ENV,该变量是自动赋值的,不可更改。
在js代码中可通过 process.env.NODE_ENV 读取;在html文件中通过%NODE_ENV%读取。
NODE_ENV 默认有三个可能的值,分别是:
development:开发环境,运行 npm start, NODE_ENV 的值为 development;
test:测试环境,运行npm run test 则是 test;
production:生产环境,运行npm run build 则对应 prodution.
设置多环境变量:
npm i dotenv-cli
创建.env.development文件
REACT_APP_BASE_URL="开发环境地址"
创建.env.production文件
REACT_APP_BASE_URL="生产环境地址"
创建.env.test文件
REACT_APP_BASE_URL="测试环境地址"
修改package.json文件
"scripts": {
"start": "dotenv -e .env.development craco start",//本地运行
"start:test": "dotenv -e .env.test craco start", //本地跑测试
"build": "dotenv -e .env.production craco build", //生产环境打包部署
"build:test": "dotenv -e .env.test craco build", //测试环境打包部署
"test": "cross-env craco test",
"eject": "react-scripts eject"
},