创建项目
create-react-app zm-airbnb
项目配置
- 配置jsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": ["src/*"]
},
"jsx": "preserve",
"lib": ["esnext", "dom", "dom.iterable", "scripthost"]
}
}
- 项目目录
别名
craco配置别名和less文件
npm i @craco/craco@alpha -D
创建craco.config.js文件
文件里配置:
const path = require("path");
const resolve = (pathname) => path.resolve(__dirname, pathname);
module.exports = {
// less
// webpack
webpack: {
alias: {
"@": resolve("src"),
components: resolve("src/components"),
utils: resolve("src/utils"),
},
},
};
同时修改package.json里的scripts
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test",
"eject": "react-scripts eject"
}
- 配置好后,
npm start启动项目,会和webpack打包进行合并
配置less
"@craco/craco": "^7.0.0-alpha.9"版本
安装依赖npm i craco-less@2.1.0-alpha.0
const path = require("path");
const CracoLessPlugin = require("craco-less");
const resolve = (pathname) => path.resolve(__dirname, pathname);
module.exports = {
// less
plugins: [
{
plugin: CracoLessPlugin,
},
],
// webpack
webpack: {
alias: {
"@": resolve("src"),
components: resolve("src/components"),
utils: resolve("src/utils"),
},
},
};
- 修改了项目配置文件,需重启项目
测试less
@zmColor: blue;
body {
color: @zmColor;
}
import React from "react";
import ReactDOM from "react-dom/client";
import App from "@/App";
import "./assets/css/index.less";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
没问题,🆗
css样式的重置
npm i normalize.css- reset.less
@textColor: #484848;
@textColorSecondary: #222;
@import "./variables.less";
* {
padding: 0;
margin: 0;
}
a {
color: @textColor;
text-decoration: none;
}
img {
vertical-align: top;
}
ul,
li {
list-style: none;
}
@import "./reset.less";
引入webpack依赖图里
import React from "react";
import ReactDOM from "react-dom/client";
import App from "@/App";
import "normalize.css";
import "./assets/css/index.less";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
项目路由Router的搭建和配置
npm i react-router-dom
- 使用HashRouter
import React 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>
<App />
</HashRouter>
</React.StrictMode>
);
- 使用useRoutes()配置路由,在router目录下新建index.js文件,新建项目目录(home,entire,detail)
import React from "react";
import { Navigate } from "react-router-dom";
const Home = React.lazy(() => import("@/views/home"));
const Entire = React.lazy(() => import("@/views/entire"));
const Detail = React.lazy(() => import("@/views/detail"));
const routes = [
{
path: "/",
element: <Navigate to="/home" />,
},
{
path: "/home",
element: <Home />,
},
{
path: "/entire",
element: <Entire />,
},
{
path: "/detail",
element: <Detail />,
},
];
export default routes;
在App.jsx中导入 routes
import React, { memo } from "react";
import { useRoutes } from "react-router-dom";
import routes from "./router";
const App = memo(() => {
return (
<div className="app">
<div className="header">header</div>
<div className="page">{useRoutes(routes)}</div>
<div className="footer">footer</div>
</div>
);
});
export default App;
设置Suspense,控制台不报错了
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>
<Suspense fallback="loading">
<HashRouter>
<App />
</HashRouter>
</Suspense>
</React.StrictMode>
);
redux的配置
安装依赖
npm i @reduxjs/toolkit react-redux
store目录
import { configureStore } from "@reduxjs/toolkit";
import homeReducer from "./modules/home";
const store = configureStore({
reducer: {
home: homeReducer,
},
});
export default store;
import { createSlice } from "@reduxjs/toolkit";
const homeSlice = createSlice({
name: "home",
initialState: {
ikun: [],
},
reducers: {},
});
export default homeSlice.reducer;
Provider为组件提供store,
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 "normalize.css";
import "./assets/css/index.less";
import store from "./store";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<Suspense fallback="loading">
<Provider store={store}>
<HashRouter>
<App />
</HashRouter>
</Provider>
</Suspense>
</React.StrictMode>
);
- 另外一种配置(reducer配置store) 目录:
const initialState = {
originReducerReduxIkun: [],
};
function reducer(state = initialState, action) {
switch (action.type) {
default:
return state;
}
}
export default reducer;
index.js
import reducer from "./reducer";
export default reducer;
store -> index.js
import { configureStore } from "@reduxjs/toolkit";
import homeReducer from "./modules/home";
import entireReducer from "./modules/entire";
const store = configureStore({
reducer: {
home: homeReducer,
entire: entireReducer,
},
});
export default store;
控制台查看state:
网络请求封装
npm i axios
services文件夹中写网络请求,目录如下:
config.js
export const BASE_URL = "http://codercba.com:1888/airbnb/api";
export const TIMEOUT = 10000;
request -> index.js
import axios from "axios";
import { BASE_URL, TIMEOUT } from "./config";
class ZMRequest {
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.request(config);
}
get(config) {
return this.request({ ...config, method: "get" });
}
post(config) {
return this.request({ ...config, method: "post" });
}
}
const req = new ZMRequest(BASE_URL, TIMEOUT);
export default req;
services -> index.js
import zmRequest from "./request";
export default zmRequest;
在组件中使用封装好的网络请求,从服务器获取数据
import zmRequest from "@/services";
import React, { memo, useEffect } from "react";
const Home = memo(() => {
// 网络请求的代码
useEffect(() => {
zmRequest.get({ url: "/home/highscore" }).then((res) => {
console.log(res);
});
}, []);
return <div>Home</div>;
});
export default Home;
展示数据:
import zmRequest from "@/services";
import React, { memo, useEffect, useState } from "react";
const Home = memo(() => {
// 定义状态
const [highScore, setHighScore] = useState({});
// 网络请求的代码
useEffect(() => {
zmRequest.get({ url: "/home/highscore" }).then((res) => {
console.log(res);
setHighScore(res);
});
}, []);
return (
<div>
<h2>{highScore.title}</h2>
<h4>{highScore.subtitle}</h4>
<ul>
{highScore.list?.map((item) => {
return <li key={item.id}>{item.name}</li>;
})}
</ul>
</div>
);
});
export default Home;