先创建项目:create-react-app 项目名
,然后换个图标,换个标题
配置jsconfig.json
:这个文件在Vue通过脚手架创建项目时自动生成, React是没有自动生成, jsconfig.json
是为了让vs code的代码提示更友好, 按需求决定是否配置;
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*"
]
},
"jsx": "preserve",
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
}
}
对src
文件夹的目录进行初始化:
assets: 存放静态资源 (如css, img等等)
baseUI: 存放一些通用的组件, 不只是本项目, 其他项目也会使用的组件
components: 存放本项目中通用的组件
hooks: 自定义的hook函数
router: 路由相关
services: 网络请求相关
stores: 状态管理, redux相关
utils: 封装的工具函数
views: 页面相关
1、安装craco:npm install craco
修改package.json:
/* package.json */
"scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test",
+ "start": "craco start",
+ "build": "craco build",
+ "test": "craco test",
}
在项目中层级嵌套会很深, 我们导入文件通常会有../../../
甚至更多的上一级目录; 因此我们配置别名解决这个问题, 我的配置是使用@
符号表示根目录
在项目根目录创建一个 craco.config.js
用于修改默认配置,该文件中的一些配置(如webpack)会和脚手架中的配置合并。修改别名的操作如下:
const path = require('path');
module.exports = {
webpack: {
alias: {
"@": path.resolve(__dirname, 'src'),
'components': path.resolve(__dirname, 'src/components'),
'store':path.resolve(__dirname,'src/store'),
......
}
}
}
先安装:npm i craco-less
按照如下方式去craco.config.js中去配置一下:
const path = require('path');
const CracoLessPlugin = require('craco-less');
module.exports = {
//下面的配置和脚手架webpack合并
webpack: {
alias: {
"@": path.resolve(__dirname, 'src'),
'components': path.resolve(__dirname, 'src/components'),
'store':path.resolve(__dirname,'src/store'),
}
},
//配置less
plugins: [
{
plugin: CracoLessPlugin
}
]
}
,应该可以用了
下载normalize.css
, 再在src中的index.js
文件引入normalize.css
,这是给我们提供好的初始样式的一个模板吧。
npm i normalize.css
然后如果我们想自己自定义一些baseCSS
,可以再新建一个文件
并且在normalize.css
之后引入:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import 'normalize.css'; //先引入模板
import '@/assets/css/reset.css' //引入自定义样式
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<App />
);
安装
npm install react-router-dom
index.js配置:
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/reset.css' //引入自定义样式
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<HashRouter>
<App />
</HashRouter>
);
新建几个路由组件,并配置他们的路由信息
最后去App.jsx
中通过useRoutes
这个hook,引入路由配置。
import React, { memo } from 'react';
import { useRoutes } from 'react-router-dom';
import routes from '@/router';
const App = memo(() => {
return (
<div>
<div className="app">
<div className="header">Header</div>
<div className="content">
{useRoutes(routes)}
</div>
<div className="footer">Footer</div>
</div>
</div>
)
})
export default App
如果要用路由懒加载,则再加两步操作:
import React from "react";
// import Home from "@/views/Home";
// import Detail from "@/views/Detail";
// import Entire from "@/views/Entire";
import { Navigate } from "react-router-dom";
const Home = React.lazy(() => import('@/views/Home'));
const Detail = React.lazy(() => import('@/views/Detail'));
const Entire = React.lazy(() => import('@/views/Entire'));
let routes = [
{
//重定向
path:'/',
element:<Navigate to='/home' />
},
{
path: '/home',
element: <Home/>
},
{
path:'/detail',
element: <Detail/>
},
{
path:'/entire',
element:<Entire/>
}
]
export default routes;
安装:这里安装RTK同时也会安装redux的,除此之外我们还要一起安装react-redux
npm install react-redux @reduxjs/toolkit
使用RTK的方式创建大store:
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;
创建完了别忘了去入口文件包个标签
为了复习之前的知识,这里我们用两种方式创建reducer函数:
import { createSlice } from "@reduxjs/toolkit";
const homeSlice = createSlice({
name: 'home',
initialState: {
userName: 'zzy'
},
reducers: {
changeUserName(state, action) {
state.userName = action.payload;
}
}
})
export default homeSlice.reducer;
entire/constants.js
const CHANGECOUNTER = 'changecounter';
export {CHANGECOUNTER};
entire/reducer.js
import * as actionTypes from './constants';
let initialState = {
counter: 0
}
function reducer(state = initialState, action) {
switch(action.type) {
case actionTypes.CHANGECOUNTER:
return {...state, counter: action.num}
default:
return state;
}
}
export default reducer;
entire/actionCreators.js
import * as actionTypes from './constants';
export const changeCounter = (num) => {
return {
type: actionTypes.CHANGECOUNTER,
num
}
}
entire/index.js
import reducer from "./reducer";
export default reducer;
首先安装axios:npm i axios
二次封装axios:
api/request/index.js
import axios from 'axios';
import { BASEURL, TIMEOUT } from './config';
class HYRequest {
constructor(baseURL, timeout) {
this.instance = axios.create({
baseURL,
timeout,
})
this.instance.interceptors.response.use(res => {
return res.data;
})
}
request(config) {
return this.instance.request(config);
}
get(config) {
return this.request({...config, method: 'get'});
}
post(config) {
return this.request({...config, method: 'post'});
}
}
//用变量存储baseURL的话,如果有其他的url,只需要导出其他的实例就可以了
export default new HYRequest(BASEURL, TIMEOUT);
api/request/config.js
const BASEURL = 'http://codercba.com:1888/airbnb/api';
const TIMEOUT = 6000;
export {BASEURL, TIMEOUT}
说实话这里的封装还挺巧妙的,和之前做vue项目的封装不一样,这里面用类来存储axios的实例,发请求都会调用类的实例的方法,然后该方法再调用axios实例上的方法。不过目前好像还没get到这样封装的好处。。
找个组件测试一下:
import React, { memo, useEffect } from 'react';
import hyRequest from '@/api';
const Home = memo(() => {
useEffect(() => {
hyRequest.get({url:'/home/highscore'}).then(res => {
console.log(res);
})
},[])
return (
<div>
<h1>Home</h1>
</div>
)
})
export default Home
,现在项目搭建的就差不多了,接下来就开始写里面的东西,放到下一篇文章中吧