React案例实操(二)

记账本

环境准备

步骤

创建项目

复制代码
npx-create-react-app react-bill-test

切换到此文件夹内

复制代码
npm i @reduxjs/toolkit react-redux react-router-dom dayjs classnames antd-mobile axios

删除没必要的文件,删除不需要的代码

启动项目

复制代码
npm run start

成功

提交本地git仓库

配置别名路径@

路径解析配置

安装craco
复制代码
npm i -D @craco/craco
根目录创建craco.config.js
复制代码
const path = require('path');

module.exports={
    webpack: {
        alias: {
            '@': path.resolve(__dirname, 'src')
        },
    }
}
更改启动命令

联想路径配置

根目录创建jsconfig.json文件
复制代码
{
    "compilerOptions": {
        "baseUrl": "./",
        "paths": {
        "@/*": [
            "src/*"
        ]
        }
    }
}

测试一下

启动一下没问题

数据Mock实现

步骤

安装依赖

复制代码
npm i -D json-server

创建data.json文件

复制代码
{
   "ka":[
     {
        "type": "pay",
        "money": -100,
        "date": "2022-01-01 10:00:00",
        "useFor": "drinks",
        "id": 1
    },
    {
        "type": "pay",
        "money": 80,
        "date": "2022-01-01 10:30:00",
        "useFor": "iong",
        "id": 1
    },
    {
        "type": "pay",
        "money": -9,
        "date": "2022-01-31 8:00:00",
        "useFor": "desserts",
        "id": 1
    },
    {
        "type": "income",
        "money": -10,
        "date": "2022-01-31 8:30:00",
        "useFor": "drinks",
        "id": 1
    }
   ]
}

添加启动命令

复制代码
"server": "json-server ./server/data.json --port 8888"

启动服务

提交本地git

整体路由设计

创建页面

都为

复制代码
const xxx = () => {
    return <div>xxx</div>;
}
export default xxx;
//xxx更换为每个文件对应页面名字

创建router.js文件

复制代码
import Layout from "@/pages/Layout";
import Month from "@/pages/Month";
import New from "@/pages/New";
import Year from "@/pages/Year";
import { createBrowserRouter } from "react-router-dom";

const router = createBrowserRouter([
    {
        path: "/",
        element: <Layout />,
        children: [
            {
                path: "/",
                element: <Month />
            },
            {
                path: "/year",
                element: <Year />
            }
        ]
    },
    {
        path: "/new",
        element: <New />
    },

])
export default router;

引入路由文件

复制代码
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import { RouterProvider } from 'react-router-dom';
import router from './router';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <RouterProvider router={router} />

);

添加子路由出口

运行,路由正常切换

git提交

antD-mobile主题定制

官网路径https://mobile.ant.design/zh/

主题https://mobile.ant.design/zh/guide/theming

因为我前面已经下载过依赖了,所以这里不需要下载了

创建css文件配置全局主题

复制代码
:root:root {
  --adm-color-primary: #a062d4;
}

引入主题文件

应用

复制代码
import { Outlet } from "react-router-dom";
import { Button } from "antd-mobile";
const Layout = () => {
    return (
    <div>
        <Outlet />
            {/* 测试 */}
            <Button color="primary">
            测试全局样式
            </Button>
            我是layout页面
    </div>
        
    );
}
export default Layout;

补充:局部样式这样引用

我们的主题色是

换一下主题色完成

Redux管理账目列表

创建store文件

在billSore.js文件内配置action
复制代码
//账单相关store
import { createSlice } from "@reduxjs/toolkit";
import axios from "axios";
const billStore = createSlice({
  name: "billStore",
  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/ka");
        dispatch(setBillList(res.data));
    }
}
export { getBillList };
const reducer = billStore.reducer;
export default reducer;
在store主文件里引入
复制代码
//组合子模块 导出store实例
import { configureStore } from "@reduxjs/toolkit";
import billReducer from "@/store/modules/billStore";
const store = configureStore({
  reducer: {
    billStore: billReducer,
  },
});
export default store;
在主引入文件引入store
复制代码
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import { RouterProvider } from 'react-router-dom';
import router from './router';
import store from './store';
import { Provider } from 'react-redux';
//导入定制主题文件
import '@/theme.css';


const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <Provider store={store}>
        <RouterProvider router={router} />
    </Provider>
);

通过action获取数据

复制代码
import { Outlet } from "react-router-dom";
import { Button } from "antd-mobile";
import { useEffect } from "react";
import { useDispatch } from "react-redux";
import { getBillList } from "@/store/modules/billStore";

const Layout = () => {
    const dispatch = useDispatch();
    useEffect(() => {
        dispatch(getBillList());
    }, [dispatch]);
    return (
    <div>
        <Outlet />
            {/* 测试 */}
            <Button color="primary">
            测试全局样式
            </Button>
            我是layout页面
    </div>
       

}
export default Layout;

获取成功

TabBar功能实现

静态引入

复制代码
import { TabBar } from "antd-mobile"
import { useEffect } from "react"
import { Outlet } from "react-router-dom"
import { useDispatch } from 'react-redux'
import { getBillList } from "@/store/modules/billStore"
import './index.scss'
import {
  BillOutline,
  CalculatorOutline,
  AddCircleOutline
} from 'antd-mobile-icons'

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])
  return (
    <div className="layout">
      <div className="container">
        <Outlet />
      </div>
      <div className="footer">
        <TabBar>
          {tabs.map(item => (
            <TabBar.Item key={item.key} icon={item.icon} title={item.title} />
          ))}
        </TabBar>
      </div>
    </div>
  )
}

export default Layout

引入scss依赖和样式

复制代码
npm i -D sass
复制代码
.layout {
  .container {
    position: fixed;
    top: 0;
    bottom: 50px;
  }
  .footer {
    position: fixed;
    bottom: 0;
    width: 100%;
  }
}

切换路由实现

layout文件

复制代码
const Layout = () => {
  const dispatch = useDispatch()
  useEffect(() => {
    dispatch(getBillList())
  }, [dispatch])
  const navigate = useNavigate();
  const switchRoute=(path)=>{
    navigate(path)
  }
  return (
    <div className="layout">
      <div className="container">
        <Outlet />
      </div>
      <div className="footer">
        <TabBar onChange={switchRoute}>
          {tabs.map(item => (
            <TabBar.Item key={item.key} icon={item.icon} title={item.title} />
          ))}
        </TabBar>
      </div>
    </div>
  )
}

全部代码

复制代码
import { TabBar } from "antd-mobile"
import { useEffect } from "react"
import { Outlet, useNavigate } from "react-router-dom"
import { useDispatch } from 'react-redux'
import { getBillList } from "@/store/modules/billStore"
import './index.scss'
import {
  BillOutline,
  CalculatorOutline,
  AddCircleOutline
} from 'antd-mobile-icons'

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();
  const switchRoute=(path)=>{
    navigate(path)
  }
  return (
    <div className="layout">
      <div className="container">
        <Outlet />
      </div>
      <div className="footer">
        <TabBar onChange={switchRoute}>
          {tabs.map(item => (
            <TabBar.Item key={item.key} icon={item.icon} title={item.title} />
          ))}
        </TabBar>
      </div>
    </div>
  )
}

export default Layout

完成

相关推荐
weixin_427771612 小时前
Vite 与 Webpack 模块解析差异
前端·webpack·node.js
永远是我的最爱2 小时前
基于ASP.NET的图书管理系统的设计与实现
前端·后端·sql·visual studio
广州华水科技2 小时前
单北斗GNSS技术在变形监测中的应用及其位移监测优势解析
前端
刘晓倩2 小时前
Python内置函数-hasattr()
前端·javascript·python
C_心欲无痕3 小时前
不点击鼠标也能通过MouseEvent实现点击事件
前端·javascript
鲨莎分不晴3 小时前
【实战】老项目焕发新生:从 Webpack 平滑迁移到 Vite 避坑全记录
前端·webpack·node.js
web小白成长日记3 小时前
从零起步,用TypeScript写一个Todo App:踩坑与收获分享
前端·javascript·typescript
圣心4 小时前
Gemini 模型 介绍
前端
huangyiyi666664 小时前
前端-远程多选搜索框不能反显的问题解决
前端·javascript·vue.js·笔记·学习