网站建设饱和了吗,wordpress编辑器换了,互联网保险新规,wordpress+最新一、项目搭建
1、创建项目 使用vite生成项目
npx create-react-app react-ts-project --template typescript 启动项目
yarn start 删除无用组件
2、设计目录结构
资源说明http网络请求assets公共资源components组件router路由配置utils工具模块store状态机App.tsx应用…一、项目搭建
1、创建项目 使用vite生成项目
npx create-react-app react-ts-project --template typescript 启动项目
yarn start 删除无用组件
2、设计目录结构
资源说明http网络请求assets公共资源components组件router路由配置utils工具模块store状态机App.tsx应用根组件index.tsx入口ts文件
3、配置sass环境 安装sass包
yarn add sass 创建全局样式文件
4、craco插件配置
如果要修改CRA的默认配置有以下几种方案 通过第三方库来修改比如craco/craco 通过执行yarn eject命令释放react-scripts中的所有配置到项目中
实现步骤 安装修改CRA的配置的包
yarn add -D craco/craco 在项目的根目录中创建craco的配置文件(craco.config.js)并在配置中配置别名
const pathrequire(path)
module.exports{webpack:{alias:{:path.resolve(__dirname,src)}}
} 修改packge.json中的脚本命令
scripts: {start: craco start,build: craco build,test: craco test,eject: react-scripts eject} 在代码中就可以通过来表示src目录的绝对路径 重启项目让配置生效
别名路径提示 在项目根目录创建tsconfig.json配置文件 在配置文件中添加如下配置
{compilerOptions: {baseUrl: ./,paths: {/*: [src/*]}}}
5、配置路由 安装路由
yarn add react-router-dom
yarn add react-loadable
yarn add types/react-loadable
下载react-loadable依赖包进行路由懒加载如果你是typescript你还需要额外安装types/react-loadable这个依赖包 建立一个loadable.ts放在src/utils/loadable.ts
import Loadable from react-loadable;
export default function withLoadable(comp:any) {return Loadable({//懒加载组件页面loader: comp,loading: () null})
} 在src下创建router目录在该目录的index.tsx编写路由配置文件
import loadable from /utils/loadable
import {RouteObject} from react-router-dom
const Loginloadable(()import(/views/Login))
const Homeloadable(()import(/views/Home))
const Mainloadable(()import(/views/Main))
const Productloadable(()import(/views/Product))
const Categoryloadable(()import(/views/Category))
const routes:ArrayRouteObject[{path:/login,element:Login/},{path:/,element:Home/,children:[{index:true,element:Main/Main},{path:product/list,element:Product/Product}, {path:product/category,element:Category/Category}]}
]
export default routes 在App.tsx中通过useRoutes钩子函数来进行集中式配置
import React,{Suspense} from react
import {useRoutes} from react-router-dom
import routes from /router
export default function App() {return (Suspense fallback{loading/}{useRoutes(routes)}/Suspense)
} 在项目根目录下的index.tsx中使用BrowserRouter包裹App
root.render(BrowserRouterApp//BrowserRouter
) 在src/Home.tsx组件中配置二级路由出口
import React from react
import {Outlet} from react-router-dom
export default function Home() {return (divHomeOutlet/Outlet/div)
}
6、安装AntD 安装AntD组件库
yarn add antd
二、用户登录
1、登录静态页面实现 首先在utils目录下创建type.ts文件这个文件里主要编写接口
export interface IUser{account:string,password:string} 在views目录下的Login.tsx文件中编写登录的静态页面
import {Button,Form,Input,message} from antd
import api from /api
import {useNavigate} from react-router-domexport default (){const navuseNavigate()const onFinishasync(values:any){console.log(values)}return (Form onFinish{onFinish} style{{ maxWidth: 600 }}Form.Item label用户名 nameusernameInput//Form.ItemForm.Item label密码 namepasswordInput.Password//Form.ItemForm.ItemButton typeprimary htmlTypesubmit登录/Button/Form.Item/Form)
}
2、axios的二次封装
import axios,{ InternalAxiosRequestConfig,AxiosResponse,AxiosError} from axios;
import {message} from antd
//设置根路径
axios.defaults.baseURLhttp://www.zhaijizhe.cn:3005
//设置请求拦截器
axios.interceptors.request.use((config: InternalAxiosRequestConfig){const tokenlocalStorage.getItem(token)if(token){config.headers.Authorizationtoken}return config
})
//设置响应拦截器
axios.interceptors.response.use((response:AxiosResponse){return response.data
},(error:AxiosError){switch(error.response?.status){case 500:message.error(服务端出现500错误)breakcase 401:message.error(服务端出现400错误)break;case 404:message.error(没有找到服务端相应资源);break;}return Promise.reject(error)
})
export default axios
3、登录功能的实现 在src/types文件夹下编写接口
export default interface IUser{username:stringpassword:string
} 编写登录的后端请求API
import request from /utils/request
import IUser from /types/IUserexport default{login:(user:IUser)request.post(/users/login,user)
} 将用户模块汇总到api.tsx中
import users from ./modules/users
export default{users
} 在登录组件中调用登录API,完成登录功能
import {Button,Form,Input,message} from antd
import api from /api
import {useNavigate} from react-router-domexport default (){const navuseNavigate()const onFinishasync(values:any){const resultawait api.users.login(values)if(result.data.code){localStorage.setItem(token,result.data.token)nav(/)}else{message.warning(登录失败)}}return (Form onFinish{onFinish} style{{ maxWidth: 600 }}Form.Item label用户名 nameusernameInput//Form.ItemForm.Item label密码 namepasswordInput.Password//Form.ItemForm.ItemButton typeprimary htmlTypesubmit登录/Button/Form.Item/Form)
}
三、路由权限
1、静态菜单
import {Outlet,NavLink,useNavigate} from react-router-dom
import React,{useState,useEffect} from react
import /assets/css/home.scss
import {Layout,Menu} from antd
import {WindowsOutlined,TrademarkCircleOutlined,UserOutlined} from ant-design/icons
const {Header,Sider,Content,Footer}Layout
export default (){const[menuList,setMenuList]useStateany([])const navuseNavigate()useEffect((){const list[{key:sub1,label:日常业务,icon:WindowsOutlined /,children:[{label:学员管理,key:/students},{label:班级管理,key:/classes}]},{key:sub2,label:校区管理,icon:TrademarkCircleOutlined /,children:[{label:教师管理,key:/teachers},{label:班主任管理,key:/directors},{label:专业管理,key:/subjects}]},{key:sub3,label:系统管理,icon:UserOutlined /,children:[{key:/users,label:用户管理}]}]setMenuList(list)},[])const go(item:any){nav(item.key)}return (LayoutHeaderdiv蜗牛BOSS管理系统/div/Header Layout style{{height:750px}}SiderMenu items{menuList} onClick{go}modeinlinethemedarkdefaultOpenKeys{[sub1,sub2]}defaultSelectedKeys{[/home/students]}/Menu/SiderContent{/* 设置子路由出口 */}Outlet/Outlet/Content/LayoutFooter style{{ textAlign: center}}Ant Design ©2023 Created by Ant UED/Footer/Layout /)
}
2、动态菜单 在api/modules/users下编写获取权限菜单的接口
import request from /utils/request
export default{getAuthMenus:()request.get(/menus/getAuthMenus)
} 在Home.tsx中中调用getAuthMenus接口来完成权限菜单数据的获取 useEffect(() {getAuthMenus()}, [])const getAuthMenus async () {const result await api.users.getAuthMenus()console.log(result.data.data)const rList transformDataToMenus(result.data.data)setMenuList(rList)} 将后台的权限菜单数据转成antd格式的菜单数据
/*** 将后台的权限菜单数据转成antd格式的菜单数据*/interface IMenuData {title: stringpath: stringicon: stringchildren?: ArrayIMenuData}interface IMenu {label: stringkey: stringicon: ReactElementchildren?: ArrayIMenu}const transformDataToMenus (list: ArrayIMenuData) {return list.map((item: IMenuData) {let name item.icon as stringlet iis: any icons[name as keyof typeof icons]let menuItem: IMenu { label: item.title, key: item.path, icon: React.createElement(iis) }if (item.children) {menuItem.children transformDataToMenus(item.children)}return menuItem})} 渲染导航列表
Menuitems{menuList}modeinlinethemedarkonClick{goNav}/Menu
3、动态添加路由表
1、安装和配置RTX
在终端执行
yarn add redux
yarn add react-redux
yarn add reduxjs/toolkit
在src目录下创建store文件夹目录结构如下
src|-store|-moudles|-xx.tsx|-yy.tsx|-index
2、创建slice模块
在src/store/reducers目录下创建routeReducer.tsx
import {createSlice,PayloadAction,Dispatch} from reduxjs/toolkit
import {RouteObject} from react-router-dom
import api from /api
import {withLoadable} from /utils/loadable
interface IAuthMenu{rows:Arrayany
}
const initialState:IAuthMenu{rows:[]
}
export const routesSlicecreateSlice({name:getAuthMenu,initialState,reducers:{setAuthRoutes(state,{payload}:PayloadActionany[]){state.rowspayload}}
})
export const getAuthRoutesAsync(routes:any){return async(dispath:Dispatch){console.log(----网络请求-----------);let resultawait api.users.getAuthMenus()console.log(aaaa,result.data.data)result.data.data.forEach((item:RouteObject){if(item.children){item.children.forEach((subItem:RouteObject){console.log(ss,subItem)const ModulewithLoadable(()import(/views${subItem.path}))routes[1].children.push({path:subItem.path,element:Module/})})}})dispath(setAuthRoutes(routes))}
}
export const {setAuthRoutes}routesSlice.actions
export default routesSlice.reducer
3、创建store对象
import {configureStore} from reduxjs/toolkitimport menuReducer from ./reducers/menus
const storeconfigureStore({reducer:{menuReducer}
})
export default store
// Infer the RootState and AppDispatch types from the store itself
export type RootState ReturnTypetypeof store.getState
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch typeof store.dispatch
4、创建hooks文件
在src/store目录下新建hooks文件import { useDispatch, useSelector } from react-redux
import type { TypedUseSelectorHook } from react-redux
import type { RootState, AppDispatch } from ./index// Use throughout your app instead of plain useDispatch and useSelector
export const useAppDispatch: () AppDispatch useDispatch
export const useAppSelector: TypedUseSelectorHookRootState useSelector
Usage With TypeScript | Redux 中文官网
5、全局注册store
import ReactDOM from react-dom/client;
import App from /App
import {BrowserRouter} from react-router-dom
const root ReactDOM.createRoot(document.getElementById(root) as HTMLElement
);
root.render(BrowserRouterApp //BrowserRouter
);
6、在组件中使用
import { Outlet, NavLink } from react-router-dom
import /assets/css/home.scss
import { Layout,Menu } from antd
import React,{ useEffect, useState } from react
import {WindowsOutlined,TrademarkCircleOutlined,UserOutlined} from ant-design/icons
//导入api
import api from /api
//导入接口
import IMenuData from /types/IMenuData
import IMenu from /types/IMenu
import IMenuFun from /types/IMenuFun
//导入图标
import * as icons from ant-design/icons
//导入useSelector和useDispatch
// import {useSelector,useDispatch} from react-redux
//使用ts的话hooks使用的是useAppSelector来代替useSelector,使用useAppDispatch来替换useDispatch
import {useAppSelector,useAppDispatch} from /store/hooks
//导入通知对象
import {getRoutesAsync} from /store/modules/routesReducer
//导入routes
import routes from /routerimport {useNavigate} from react-router-domconst { Header, Sider, Content, Footer } Layout
export default () {const[menuList,setMenuList]useStateArrayany([])useEffect((){getAuthMenus()},[])const dispatchuseAppDispatch()const navuseNavigate()/*** 通过token向后端服务端获取权限数据*/const getAuthMenusasync(){const resultawait api.users.getAuthMenus()//进行转换const list:ArrayIMenutransformDataToMenu(result.data.data)setMenuList(list)//向状态机发送通知操作路由表关键代码dispatch(getRoutesAsync(routes))}//代码略const transformDataToMenu:IMenuFun(list:ArrayIMenuData){}//进行路由跳转的方法const go(values:any){nav(values.key)}return (LayoutHeader style{{ color: #fff }}蜗牛BOSS系统/HeaderLayout style{{ height: 750px }}SiderMenuonClick{go}items{menuList}themedarkmodeinline/Menu/SiderContentOutlet/Outlet/Content/LayoutFootercopy;版权前端10期班所有/Footer/Layout)
}
7、App.tsx
import {useRoutes} from react-router-dom
import routes from /router
import {useAppSelector} from /store/hooks
import {useEffect,useState} from react
export default (){const rowsuseAppSelector((state){return state.routesReducer.rows})const[rout,setRout]useState(routes)useEffect((){console.log(********)console.log(rows,rows)setRout(rows)},[rows])return ({useRoutes(rows.length0?routes:rout)}/)
}