React18学习笔记(四) 路由案例--记账本
文章目录
- 一.准备
- 1.功能演示
- 2.创建项目
- 3.安装依赖
- 4.配置路径别名
- 对于要求一
- 对于要求二
- 5.使用json-server实现数据Mock
- 二.整体路由设计
- 1.配置路由文件router/index.js
- 2.在入口文件中导入路由实例对象
- 三.功能验证
- 1.使用antd-mobile定义主题色
- 2.使用Redux管理账户列表
- 3.使用antd-mobile的tabbar组件配置底部标签栏
一.准备
1.功能演示
2.创建项目
npx create-react-app my-react-bill-test
3.安装依赖
安装如下必要依赖:npm i +xxx
1).Redex状态管理工具:@reduxjs/toolkit和react-redux
2).路由:react-router-dom
3).时间处理js库:dayjs
4).类名处理库:classnames
5).移动端组件库:antd-mobile----重点
6).axios
4.配置路径别名
输入@即可指代src路径
要求:
- 1).
webpack
中的路径解析配置:把@解析为src - 2).在
vsCode
中,输入@时自动联想出src下的子级目录
对于要求一
下载craco插件
-为什么要下载craco插件?
-CRACO的项目本身把webpack配置包装到了黑盒中无法直接修改,需要借助插件之力
配置步骤:
a.安装craco:npm i -D @craco/craco
b.项目根目录下创建配置文件craco.config.js
c.在配置文件中添加路径解析配置如下:
const path=require('path')
module.exports={//webpack配置webpack:{//配置别名alias:{//约定:使用@表示src文件所在路径'@':path.resolve(__dirname,'src')}}
}
d.包文件中配置启动和打包命令如下:
"script":{"start":"craco start","build":"craco build"
}
对于要求二
新增jsconfig.json文件并在其中配置如下:
{"compilerOptions":{"baseUrl":"./","paths":{"@/*":["src/*"]}}
}
5.使用json-server实现数据Mock
步骤:
a.安装:npm i -D json-serverb.准备一个db.json文件c.添加启动命令如下:"server":"json-server ./server/db.json --port 8888"d.访问接口进行测试
优化:合并命令
安装concurrently:npm install concurrently --save-dev
配置package.json:
"start": "concurrently \"npm run server\" \"craco start\"",*合并结果:npm run start命令同时启动json-server服务器
二.整体路由设计
新增如下文件:
src
├─router
│ └─index.js
├─pages
│ ├─Layout
│ │ └─index.js
│ ├─Month
│ │ └─index.js
│ ├─Year
│ │ └─index.js
│ ├─Year └─index.js
1.配置路由文件router/index.js
// 导入子路由
import Layout from "@/pages/Layout"
import New from "@/pages/New"
import Month from "@/pages/Month"
import Year from "@/pages/Year";
// 导入createBrowserRouter,作用是创建路由
import { createBrowserRouter } from "react-router-dom";
import { Navigate } from "react-router-dom";
// 创建路由实例对象
const router = createBrowserRouter([// 根路径重定向配置{path: "/",element: <Navigate to="/layout/month" replace />, // 重定向到目标路径},{path: '/layout',element: <Layout />,children: [{index: true, // 默认子路由element: <Month /> // 访问/article时默认显示},{path: 'year',element: <Year />},{path: 'month',element: <Month />},{path: 'new',element: <New />}]},
])
// 导入路由实例对象
export default router;
2.在入口文件中导入路由实例对象
//src/index.js
import { RouterProvider } from 'react-router-dom';
import router from './router'
import {Provider} from 'react-redux'
import store from './store'root.render(<Provider store={store}><RouterProvider router={router} /></Provider>
);
......
三.功能验证
1.使用antd-mobile定义主题色
- 新增
src/theme.css
:root {/* 基础主题变量 */--adm-color-primary: #a062d4;--adm-color-success: #00b578;/* 按钮样式变量 */--adm-button-background-color: #a062d4;--adm-button-border-radius: 20px;/* 字体变量 */--adm-font-size-main: 16px;
}/* 局部主题示例 */
.purple-theme {--adm-color-primary: #722ed1;--adm-button-background-color: #722ed1;
}
- 导入
//src/index.jsimport "@theme.css"
- 使用
//src/pages/Layout/index.js
<Button type="primary">测试全局</Button>
<div className="purple-theme"> <Button type="primary">测试局部</Button>
</div>
结果:按钮有样式
2.使用Redux管理账户列表
思路:
- 在RTK配置state,reducer和异步action
- 在组件中dispatch异步action
步骤: - step1:新建账单列表相关store
//src/store/modules/billStore.js
import { createSlice } from '@reduxjs/toolkit'
import axios from 'axios'
const billStore = createSlice({name: 'bill',initialState: {// 账单列表billList: [],},reducers: {// 设置账单列表setBillList(state, action) {state.billList = action.payload}}
})
const { setBillList } = billStore.actions// 异步获取账单列表
const getBillList = () => {return async (dispatch) => {const res = await axios.get('http://localhost:8888/list')dispatch(setBillList(res.data))}
}
export { getBillList }const reducer = billStore.reducer
export default reducer
- step2:组合子模块,导出store实例
// src/store/index.js
import billReducer from './modules/billStore.js'
import { configureStore } from '@reduxjs/toolkit'
const store = configureStore({reducer: {bill: billReducer// 这里的key要和子模块的name一致,即:name: 'bill'}
})
export default store
- step3:在入口文件中注入
//src/index.js
import {Provider} from 'react-redux'
import store from './store'
......
root.render(<Provider store={store}><RouterProvider router={router} /></Provider>
);
- step4:组件中使用useEffect触发异步action
//Layout/index.jsconst dispatch = useDispatch()useEffect(() => {dispatch(getBillList())}, [dispatch])
结果:浏览器>网络,新增一个get请求
3.使用antd-mobile的tabbar组件配置底部标签栏
官网文档:https://mobile.ant.design/zh/components/tab-bar
安装:sass:npm i -D sass
代码:
//新建Lqyout/index.scss
.layout{.container{position:fixed;top:0;bottom:50px;}.footer{position:fixed;bottom:0;width:100%;}
}
//Layout/index.js
import { Outlet, useNavigate } from "react-router-dom";
import { TabBar } from "antd-mobile";
import { useEffect } from "react";
import { useDispatch } from 'react-redux'
import { getBillList } from "@/store/modules/billStore";
import { BillOutline, AddCircleOutline, CalculatorOutline } from 'antd-mobile-icons'
import '@/pages/Layout/index.css'
const tabs = [{key: 'month',title: '月度账单',icon: <BillOutline />,},{key: 'new',title: '记账',icon: <AddCircleOutline />,},{key: 'year',title: '年度账单',icon: <CalculatorOutline />,}
]
const Layout = () => {const dispatch = useDispatch()useEffect(() => {dispatch(getBillList())}, [dispatch])const navigate = useNavigate()//点击绑定在tabbar的onChange'事件const swithRoute = (path) => {navigate(path)}return (<div className="layout"><div className="content"><Outlet /></div><div className="footer"><TabBar onChange={swithRoute}>{tabs.map(item => (<TabBar.Item key={item.key} icon={item.icon} title={item.title} />))}</TabBar></div></div>);
}export default Layout;