前言
各大社区中关于react的后台管理系统已经应有尽有,大部分都是react+antd,偶尔一次看到material-ui这个react UI组件,感觉很特别,于是尝试使用搞一个demo体验一下,经过不断细化转化到目前一个比较完整的项目,特发此文以作记录,希望可以帮助更多的开发者。
本文不太适合react初学者,需要对react有一定基础,大量使用了react-hooks。
简介
一个使用React全家桶(react-router-dom,redux,redux-actions,redux-saga,reselect)+Material-ui构建的后来管理中心。选择Material-ui的理由:1、默认四大颜色主题随意切换,主题可继续扩展,定制;2、内置Grid(栅格)系统,完全兼容mobile,ipad,pc三端浏览器;3、内置icon,可使用icon-font或者直接svg;4、强大的Table(表格组件)内置搜索功能,可直接导出(下载)表格到本地。5、柔和的动画体系,增强用户体验。放个截图-_-
附录
-
- 在线体验:账号:
admin
密码:123456
- 在线体验:账号:
-
- 源码地址:https://github.com/SimpleRoom/walker-admin,觉得有用请戳:star~ 会不断更新......
-
- 默认使用: create-react-app
-
- 目前分5个页面:图表数据,个人资料,员工管理,会员管理,线路设计,酒店预订
-
- 难点在于redux、redux-actions、redux-saga、reselect这4者如何串联衔接,来注入管理store。
-
- 目前已经部署上线,后台相关功能会陆续添加更新!线上地址就不公布了~~()
工具概括
- 1、redux:管理组件state的容器
- 2、react-redux:React官方控制React组件与Redux的连接容器
- 3、redux-actions:简化Redux写法的工具
- 4、redux-saga:Redux处理异步数据的中间件
- 5、reselect:Redux的选择器工具,精确获取指定state,减少不必要的渲染
- 6、plop:快速开发工具,自动生成指定模板文件的工具(与react无关,可配置提高开发效率)
功能概况
- 1、路由权限:登录时接口返回该账号权限级别,匹配对应的路由routerList注入store
- 2、数据图表:热门景点排名,公司营收图表状况
- 3、个人资料:个人信息编辑更新
- 4、员工管理:员工资料增删改查,导出
- 5、会员管理:每月入会会员统计,即将过期会员统计,会员资料增删改查,导出
- 6、线路设计:已有线路的编辑更新,删除,添加,可随时更新至对应的app或者小程序
- 7、酒店预订:根据线路参团来预订合适的酒店
部分代码示例
- 1、如何串联redux,redux-actions,redux-saga,reselect,如:
//异步获取github开放的个人信息接口,对应目录(src/store/modules/common)
// 1.redux-actions
import { createActions } from 'redux-actions'
export const {
// 获取github个人信息
fetchGitInfo,
setGithubInfo,
} = createActions(
{
// 获取github个人信息
FETCH_GIT_INFO: (username) => ({ username }),
SET_GITHUB_INFO: (githubData) => ({ githubData}),
},
)
export default {}
//2.redux-saga
import axios from 'axios'
import { fork, put, takeEvery } from 'redux-saga/effects'
import {
// github 个人信息
fetchGitInfo,
setGithubInfo,
} from './action'
// 请求github
function* getGithubInfo(action) {
const { username } = action.payload
// username为你的github 用户名
const result = yield axios.get(`https://api.github.com/users/${username}`)
// console.log(action, result, 'saga.....')
yield put(setGithubInfo(result.data))
}
//
function* watchCommon() {
// 请求接口
yield takeEvery(fetchGitInfo, getGithubInfo)
}
export default [fork(watchCommon)]
//3.reducer
import { handleActions } from 'redux-actions'
import {
// 暂存github信息
setGithubInfo,
} from './action'
// 该store的命名空间,可创建多个把store分开管理
export const namespace = 'common'
export const defaultState = {
// github个人信息
githubInfo: {},
}
export const commonReducer = handleActions(
{
[setGithubInfo]: (state, action) => {
const { githubData } = action.payload
return { ...state, githubData }
}
},
defaultState
)
// 4.reselect
// 从store单独获取githubInfo,实际中可能有N多个接口的不同数据
export const getGithubData = state => state[namespace].githubData || {}
// 5、组件内部使用
import React, { useEffect } from 'react'
import { connect } from 'react-redux'
import { fetchGitInfo } from '../../store/modules/common/action'
import { getGithubData } from '../../store/modules/common/selector'
const mapStateToProps = state => ({
myGithubInfo: getGithubData(state),
})
const mapDispatchToProps = {
fetchGitInfo,
}
const MyInfo = (props) => {
const { myGithubInfo, fetchGitInfo } = props
// react-hooks新增:可代替componentDidMount和componentDidUpdate
useEffect(() => {
if (myGithubInfo && !Object.keys(myGithubInfo).length) {
// 触发action,开始请求接口
fetchGitInfo('wjf444128852')
}
}, [myGithubInfo, fetchGitInfo])
return (
{myGithubInfo.name}
{myGithubInfo.flowers}
)
}
export default connect(mapStateToProps, mapDispatchToProps)(MyInfo)
- 3、Material-table,定制thead,配置中文显示,配置参考(componenst/MaterialTable),支持数据导出功能。
// 一、materialTableConfig.js,可静态配置共用,可动态通过props根据需展示的数据格式定制
// 1.table-thbody-td的样式
const bodyCellStyle = {
fontSize: '0.82rem',
color: 'rgba(0, 0, 0, 0.87)',
fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
fontWeight: 300,
}
// 2.table-thead列数配置,与异步数据格式需一致
export const columnsArr = [
{ title: 'ID', field: 'id', cellStyle: bodyCellStyle },
{ title: '姓名', field: 'name', cellStyle: bodyCellStyle },
{ title: '年龄', field: 'age', cellStyle: bodyCellStyle },
{ title: '加入时间', field: 'joinTime', cellStyle: bodyCellStyle },
{ title: '到期时间', field: 'expiredTime', cellStyle: bodyCellStyle },
{ title: '生日', field: 'birthday', type: 'string', cellStyle: bodyCellStyle },
{
title: '出生地',
field: 'birthCity',
// birthCity id
lookup: { 1: '安徽', 2: '北京', 3: '上海', 4: '深圳', 5: '广州', 6: '杭州' },
cellStyle: bodyCellStyle,
},
]
// 3. 其他配置,
export const optionsSetting = {
// thead style
headerStyle: {
// backgroundColor: '#66bb6a',
...bodyCellStyle,
fontSize: '1rem',
color: '#66bb6a',
},
rowStyle: {
backgroundColor: '#EEE',
},
//是否需要导出报表CSV文件,按钮
exportButton: true,
//导出报表的名字
exportFileName: '报表信息',
// 操作按钮的位置,定位操作的位置,-1是末尾,默认开头
actionsColumnIndex: -1,
//是否需要开启分页
paging: true,
// 分页中每页数量,异步数据还需要配置total
pageSize: 10,
}
// 4. table表格语言本地化配置,默认都是英文
export const localizationConfig = {
header: {
actions: '操作',
},
toolbar: {
searchTooltip: '搜索',
searchPlaceholder: '查找指定用户',
exportTitle: '导出',
exportName: '导出到CVS文件',
},
body: {
emptyDataSourceMessage: '当前列表为空',
addTooltip: '增加',
editTooltip: '编辑',
deleteTooltip: '删除',
// 编辑选项提示设置
editRow: {
deleteText: '您确定要删除该选项吗?请您三思...',
saveTooltip: '确定',
cancelTooltip: '取消',
}
},
pagination: {
labelRowsSelect: '条',
labelDisplayedRows: '{from}-{to} of {count}',
// labelDisplayedRows: '{count}条',
firstTooltip: '首页',
previousTooltip: '上一页',
nextTooltip: '下一页',
lastTooltip: '尾页'
}
}
//二、组件内使用
import {
// columnsArr,
optionsSetting,
localizationConfig,
} from './materialTableConfig'
目录结构
plop── 快速创建components和store的模板
┌── assets 资源文件
├── components 页面组件
├── router 路由配置
├── store state模块管理中心
src──├── styles 页面样式
├
├── utils 插件和工具
├
├── views 与路由对应的页面
└── index.js 页面配置入口
┌── Card 面板组件
├── CustomButtons 按钮组件
├── CustomInput 输入框组件
├── CustomTabs 公用Tab切换组件
components ──├── Dialog 弹框组件
├── Footer 底部footer
├── Grid 栅格组件
├── HeadNavBar 头部导航组件
├── HotelCard 酒店页面UI面板
├── HotelList 酒店页面列表UI组件
├── Login 登录组件
├── MaterialTable 定制可编辑Table组件
├── MuiDatepicker 日期选择器组件
├── MuiTimepicker 时间选择器组件
├── Notifications 自定义提示消息组件
├── Snackbar Material-ui官方消息提示组件
├── Table 定制不可编辑的Table组件
├── Loading loading组件
├── NotFound 404组件
├── ScrollToTopMount 路由切换缓动到顶部组件
├── SideBar 侧边栏路由导航
└── SideTool 右边工具栏组件
┌── modules 不同的state模块
├ ├── account 登录验证state
├ ├── common 全局公用的state
├ └── theme 主题控制state
store──├
└── indexStore.js state入口
结语
本人目前求职看机会中,欢迎来撩:[email protected]
- 1、上述中redux的工具使用相对复杂繁琐,且不适合react初学者!!!!
- 2、实际中遇到的几个问题,A:react-loadable不在维护更新,已替换为@loadable/component;B:react-chartist官方图表使用的react版本是16.0,已向作者发PR,把componentWillReceiveProps替换为getDerivedStateFromProps
C:打包部署到CDN二级目录的话,需要针针对路由添加配置,router basename
3 、以上只是实际开发中遇到的笔记总结,若有误请指出,如有用记得start~