当前位置:   article > 正文

react18+antd5从0到1的后台管理系统(三)_react-antd 创建管理后台教程

react-antd 创建管理后台教程

前面两章把基础简单介绍了,这一章开始就要正式搭建了,若有不正确的地方虚心接收大家的指正。

一、项目目录的介绍

思考了一下还是把自己的目录习惯介绍一下吧,这样大家看起来应该更容易理解一点,因为我自己经常也是看到别人文章没看到目录介绍,跟着写就发现了对不上的情况!

在第一章就介绍了初始化的文件目录,这里就不介绍当时介绍过的目录了,要是忘记了可以去第一章节回顾;

components:与vue一样放置组件使用

layout:顾名思义,这是一个布局文件夹

router:因为这是属于单页面应用,局部刷新就少不了这个文件夹里面的东西

store:这是redux的全局状态管理仓库文件夹

store/actions:封装操作状态的方法的文件夹

store/reducers:放置模块化

store/connect.js:封装统一的装饰器使用

store/index.js:状态管理器的主入口文件

 utils:放置一些工具函数

views:放置页面模块

二、封装状态管理器

关于这个我不做过多的赘述了,这个地方不知道的可以去参考我的另一个文章,传送门

就说下持久化保存吧,因为这里毕竟要用到

首先安装持久化的依赖

yarn add redux-persist

在store/index.js中使用

代码

  1. import {createStore, combineReducers} from 'redux'
  2. // redux的持久化保存
  3. import {persistReducer, persistStore} from "redux-persist";
  4. import storage from "redux-persist/lib/storage";
  5. //创建reducer以及初始化状态
  6. const reducer = (state = {
  7. count: 1
  8. }, action) => {
  9. // action中type代表动作的标识,用于触发行为,payload代表传递的参数
  10. switch (action.type) {
  11. case 'ADD':
  12. return {...state, count: state.count + action.payload}
  13. case 'REDUCE':
  14. return {...state, count: state.count - action.payload}
  15. default:
  16. return state
  17. }
  18. }
  19. //定义配置的信息
  20. const persistConfig = {
  21. key: "root",
  22. storage: storage,
  23. // 如果不想将部分state持久化,可以将其放入黑名单(blacklist)中.黑名单是设置
  24. // blacklist: ['ll']
  25. }
  26. //创建持久化的配置persist的信息
  27. const persist_reducers = persistReducer(persistConfig, reducer);
  28. //创建状态管理器
  29. const store = createStore(persist_reducers)
  30. const persistor = persistStore(store);
  31. export {store, persistor}

这地方是还未做拆分的,后面会做reducer的拆分,方便管理;

在入口文件处需要设置

注:如果不知道这里的Provider是什么意思的可以去看我的《React-Redux使用connect,并封装装饰器》这个文章,里面是有写的

三、路由模块

这里的路由就可以采用router6.x的特性,有一个useRouter的HOOK,这个写法就相当于vue里面的路由,单独拆成一个json文件,这样就更加易于维护管理了;

但是不局限于这个方式,喜欢router5.x的也可以采用循环方式注册路由,这里就看个人的习惯;

在layout文件夹下面创建Home.jsx文件、在views下创建404.jsx和login.jsx;

然后在router下创建index.jsx文件,创建路由;

router/index.jsx

  1. import React, {lazy ,Suspense} from "react";
  2. const routes = [
  3. {
  4. path:'/',
  5. component:lazy(()=>import('@/layout/Home'))
  6. },
  7. {
  8. path:'/login',
  9. title:'登录',
  10. component:lazy(()=>import('@/views/login'))
  11. },
  12. {
  13. path:'*',
  14. title:'404',
  15. component:lazy(()=>import('@/views/404'))
  16. }
  17. ]
  18. // 懒加载
  19. const syncRouter = (table)=>{
  20. let mRouteTable=[]
  21. table.forEach((route)=>{
  22. mRouteTable.push({
  23. path:route.path,
  24. element:(
  25. <Suspense fallback={<div>路由加载中...</div>}>
  26. <route.component />
  27. </Suspense>
  28. ),
  29. children:route.children&&syncRouter(route.children)
  30. })
  31. })
  32. return mRouteTable
  33. }
  34. export const newRoutes = syncRouter(routes)

然后在App.jsx文件中引入使用

最后在主入口文件main.jsx中引入注册

在网页上验证是否生效

输入错误的路由,进入了404的页面去了

到这里说明你的路由成功了

四、首页布局

 前面已经导入了antd5.x版本的组件了,所以这里可以直接按需引入使用antd的组件

这里采用的是这种布局方式

可以根据antd文档上的代码,写自己的业务需求

layout/Home.jsx

按照文档的代码复制进去,打开页面

现在已经把局布好了,但是这个点击左边右边并不会更新;那是因为路由并没有与这个页面关联起来,所以点击左边右边是不会切换刷新的;

五、路由与布局相关联

根据布局我们能看出,内容模块处于的不是一级路由,所以我们要创建子路由文件了;

在views文件夹下面创建测试的模块以及对应的jsx文件

在这里我创建了一个中间页面layout/LayoutPage.jsx;若熟悉vue的 朋友就可以看出这个的用处,多层嵌套使用这个占位;

接下来我们就需要把这个路由文件在redux中引入,做全局使用,并且把这个在封装一个在antd的Menus组件使用的数据,方便在布局页面直接使用,而且不会出现还未初始化成功的同步问题;

上图这个是我处理的菜单栏的数据,也可以直接根据需求把这个写成菜单json数据,我这里根据路由文件处理的是为了方便做动态路由,简单说说我这里怎么来处理的吧;

第一步:路由文件里面去调取redux的actions 

第二步:处理菜单栏

第三步:在布局组件里使用

这样就已经把菜单栏目配置好了,但是你会发现无论怎么切换嵌套路由地址依然不会变化,那是因为缺少占位的组件Outlet;

        今天看到一段话是这样描述outlet的。说的是嵌套路由,可以保证子路由共享父路由的界面而不会覆盖。为此React提供了Outlet组件,将其用于父组件中可以为子路由的元素占位,并最终渲染子路由的元素。

  这句话的意思大概就是说outlet是应用于嵌套路由的占位的。PS:如果是一级路由的话,我个人的理解还是要用Routes跟Route搭配的;

忘记说了,前面创建了一个占位组件LayoutPage.jsx  内部写法如下

到这一步的话就恭喜你已经可以通过地址栏更改路由了 

 到这里还没满足我们的需求,就是点击左边切换内容数据,那么该怎么做呢?

这里的话就要用到我们的路由跳转功能了,这里因为我们用的路由文件方式,那么就采用useNavigate这个方式跳转;

按照教程引入并使用: 

 

 点击菜单栏出现了下方的错

这是因为用的类组件方式,并不支持这种方式,那就要采用其他方式了,这里就需要包裹一层才能使用这个方式了;

layout/Home.jsx的修改成包裹方式导出

代码

  1. const widthUseNavigate = (WrapCompontent)=>{
  2. // 设置别名
  3. WrapCompontent.displayName = `widthUseNavigate${getDisplayName(WrapCompontent)}`
  4. return function NavigateCompont() {
  5. const navigate = useNavigate()
  6. const location = useLocation()
  7. // 给传入的组件新增一个to方法,传给原始组件的props,在原始组件中通过this.props.to(参数)使用
  8. return <WrapCompontent to={navigate} location={location}></WrapCompontent>
  9. }
  10. }
  11. const getDisplayName = (WrapCompontent)=>{
  12. return WrapCompontent.displayname || WrapCompontent.name || 'Component'
  13. }
  14. // 使用高阶组件包裹当前类组件
  15. const NavigateCompont = widthUseNavigate(Home);

然后再打印一下Home组件的props你就会发现,这里面又多出来很多东西

这样你就可以直接使用to方式跳转组件了;

 这里点击菜单栏获取到的参数里面有两个参数key、keyPath,根据这两个就可以组装跳转路由地址了

 这里只是做演示,具体的嵌套需要自己去处理

做到这步就可以点击左边然后右边跟随变化了,但是这里有一个需要自己去处理,就是通过this.props里面的location这个参数去获取当前的路由去做初次进来渲染左边默认选中的路由;

 

到这里就差不多结束了联动的操作了,这个章节的内容到这里就结束了,到这个章节的代码链接放在下面,需要的可以自行去看看,

传送门

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/138942
推荐阅读
相关标签
  

闽ICP备14008679号