【开发篇】10分钟快速搭建React后台管理系统模板

mind_programmonkey 2020-11-13 04:19:14
快速 开发 react 搭建 分钟


React后台管理系统模板

github

我又回来了!!!学完前端react,再学spring,这周或者下周写spring有关的!!!
在这里插入图片描述

一、准备React

1.建立react应用

npx create-react-app react_management_system_template
cd react_management_system_template

并对react应用进行整理,整理成如下图所示

在terminal中输入yarn start,在游览器中输入http://localhost:3000即可得到如下图:

2.基础插件安装

本次所需的插件

  • react-router-dom
  • less less-loader
  • axios
  • jsonp
  • antd

yarn add react-router-dom axios less less-loader@4.0.1 antd

3.暴露webpack

  • yarn eject

4.项目使用Less

在上述暴露出webpack的基础上,找到config/webpack.config.js文件。

加上这两句

之后找到getStyleLoaders方法,添加代码如图所示

最后找到如下代码处,添加less支持

// 添加less
{

test: lessRegex,
exclude: lessModuleRegex,
use: getStyleLoaders(
{

importLoaders: 3,
sourceMap: isEnvProduction && shouldUseSourceMap,
},
'less-loader'
),
sideEffects: true,
},
{

test: lessModuleRegex,
use: getStyleLoaders(
{

importLoaders: 3,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: {

getLocalIdent: getCSSModuleLocalIdent,
},
},
'less-loader'
),
},

之后在项目中新建App.less文件测试less文件是否可用正常使用。

并在App.js中引入App.less之后yarn start启动项目,可用看到背景正常设置为红色,设置成功!

来到主页开发这里了,让我们一起愉快的进入学习之旅吧。
在这里插入图片描述

二、项目主页开发

1.项目主页设置

本次以博客管理系统为例。下面对管理系统页面结构定义:

  • 页面结构定义
    • 左侧 列表模块
    • 右侧
      • 头部模块
      • 内容页面
      • 尾部模块

2.主页简约配置

主页采用AntdGrid栅格(https://ant.design/components/grid-cn/)

记得在index.js中引入antd.css,否则不起作用,即import 'antd/dist/antd.css';

  • 新建Admin.js,并搭建简约框架
import React from 'react';
import {
Col,Row} from 'antd';
class Admin extends React.Component {

constructor(props) {

super(props);
this.state = {

};
}
render() {

return (
<Row className="container">
<Col span={
4} className="nav-left">
侧边栏
</Col>
<Col span={
20} className="Main">
<Row>
头部区域
</Row>
<Row>
内容区域
</Row>
<Row>
尾部区域
</Row>
</Col>
</Row>
);
}
}
export default Admin;

3.搭建侧边栏

参考Antd的Menu导航菜单(https://ant.design/components/menu-cn/#header)

src/componets/Navleft/index.js

import React from 'react';
import {
 Menu } from 'antd';
import './index.less';
const {
 SubMenu } = Menu;
class index extends React.Component {

constructor(props) {

super(props);
this.state = {

};
}
render() {

return (
<div>
<div className="logo">
<img src="/assets/logo-ant.svg" alt=""/>
<h1>博客后台管理系统</h1>
</div>
<Menu theme="dark" defaultOpenKeys={
['sub3']} mode="inline">
<Menu.Item key="1">首页</Menu.Item>
<Menu.Item key="1">文章发布</Menu.Item>
<SubMenu key="sub3" title={
"博客管理"}>
<Menu.Item key="1">文章管理</Menu.Item>
<Menu.Item key="2">评论管理</Menu.Item>
<Menu.Item key="3">分类专栏</Menu.Item>
<Menu.Item key="4">订阅专栏</Menu.Item>
<Menu.Item key="5">博客搬家</Menu.Item>
<Menu.Item key="6">博客打赏</Menu.Item>
<Menu.Item key="7">博客设置</Menu.Item>
<Menu.Item key="8">博主名片</Menu.Item>
</SubMenu>
<Menu.Item key="1">数据统计</Menu.Item>
<Menu.Item key="1">下载管理</Menu.Item>
<Menu.Item key="1">创造活动</Menu.Item>
<Menu.Item key="1">用户中心</Menu.Item>
</Menu>
</div>
);
}
}
export default index;

src/componets/Navleft/index.less

.logo{

line-height: 100px;
padding-left: 20px;
background-color: #002140;
img{

height: 45px;
}
h1{

color: #ffffff;
font-size: 25px;
display: inline-block;
vertical-align: center;
margin: 0 0 0 10px;
}
}

其效果为:

之后再对此修改,用config文件的方式来加载侧边栏

src/config/menuConfig.js文件

const menuList = [
{

title: "首页",
key: '/admin/home'
},
{

title:"文章发布",
key: "/admin/publish_articles"
},
{

title:"博客管理",
key: "/admin/manage_blog",
children:[
{

title:"文章管理",
key:"/admin/manage_articles"
},
{

title:"评论管理",
key:"/admin/manage_comment"
},
{

title:"分类专栏",
key:"/admin/manage_column"
},
{

title:"订阅专栏",
key:"/admin/subscribe_column"
},
{

title:"博客搬家",
key:"/admin/move_blog"
},
{

title:"博客打赏",
key:"/admin/reward_blog"
},
{

title:"博客设置",
key:"/admin/setting_blog"
},
{

title:"博客名片",
key:"/admin/card"
}
]
},
{

title:"数据统计",
key:"/admin/statistics"
},
{

title:"下载管理",
key:"/admin/manage_download"
},
{

title:"创作活动",
key:"/admin/activities"
},
{

title:"用户中心",
key:"/admin/user_info"
},
];
export default menuList;

对之前的NavLeft/index.js

import React from 'react';
import {
 Menu } from 'antd';
import './index.less';
// 引入侧边栏配置
import MenuConfig from '../../config/menuConfig';
const {
 SubMenu } = Menu;
class index extends React.Component {

constructor(props) {

super(props);
this.state = {

};
}
// 刷新挂载组件
componentDidMount(){

const menuTreeNode = this.renderMenu(MenuConfig);
this.setState({

menuTreeNode
})
}
// 菜单渲染
renderMenu=(data)=>{

return data.map((item)=>{

if(item.children){

return(
<SubMenu title={
item.title} key={
item.key}>
{
this.renderMenu(item.children)}
</SubMenu>
)
}
return <Menu.Item title={
item.title} key={
item.key}>
{
item.title}
</Menu.Item>
})
}
render() {

return (
<div>
<div className="logo">
<img src="/assets/logo-ant.svg" alt=""/>
<h1>博客后台管理系统</h1>
</div>
<Menu theme="dark" defaultOpenKeys={
['/admin/manage_blog']} mode="inline">
{
this.state.menuTreeNode}
</Menu>
</div>
);
}
}
export default index;

4.头部区域

头部区域分为两个部分,一部分分为用户名;另外一部分为时间和天气情况。

对时间进行格式化在src/utils/utils.js

export default{

formateDate(time){

if(!time)
return '';
let date = new Date(time);
return date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate() + " " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
}
}

对百度天气api请求的封装在src/axios/index.js

import JsonP from 'jsonp';
export default class Axios{

static jsonp(options){

return new Promise((resolve,reject)=>{

JsonP(options.url,{

param:'callback'
},function(err,response){

if(response.status=='success'){

resolve(response);
}else{

reject(response.message);
}
})
})
}
}

其头部为src/components/Header/index.js

import React from 'react';
import {
Col,Row} from 'antd';
import './index.less'
import Util from '../../utils/utils';
import axios from '../../axios';
class index extends React.Component {

constructor(props) {

super(props);
this.state = {

userName:"吕厂长"
};
}
// 获取时间
componentDidMount(){

setInterval(()=>{

let sysTime = Util.formateDate(new Date().getTime());
this.setState({

sysTime
})
},1000)
this.getWeatherApiData();
}
// 获取天气
getWeatherApiData(){

let city = "天津";
axios.jsonp({

url:"http://api.map.baidu.com/telematics/v3/weather?location="+encodeURIComponent(city)+"&output=json&ak=3p49MVra6urFRGOT9s8UBWr2"
}).then((res)=>{

if(res.status=='success'){

let data = res.results[0].weather_data[0];
this.setState({

dayPictureUrl:data.dayPictureUrl,
weather:data.weather
})
}
})
}
render() {

return (
<div className="header">
<Row className="header-top">
<Col span="24">
<span>欢迎,{
this.state.userName}</span>
<a href="#">退出</a>
</Col>
</Row>
<Row className="breadcrumb">
<Col span="4" className="breadcrumb-title">
首页
</Col>
<Col span="20" className="breadcrumb-detail">
<span className="date">{
this.state.sysTime}</span>
<span className="weather-img">
<img src={
this.state.dayPictureUrl} alt=""/>
</span>
<span className="weather-detail">{
this.state.weather}</span>
</Col>
</Row>
</div>
);
}
}
export default index;

其目前的效果展示为:

5.尾部区域

尾部区域在src/components/Footer/index.js

import React from 'react';
import './index.less';
class index extends React.Component {

constructor(props) {

super(props);
this.state = {

};
}
render() {

return (
<div className="fonter">
(推荐使用谷歌游览器,可以获得更佳操作页面体验)
</div>
);
}
}
export default index;

样式文件在src/componets/Footer/index.less

.fonter{

padding:40px 0;
text-align: center;
columns: #d7d7d7;
height: 50px;
position: absolute;
bottom: 10px;
left: 40%;
}

6.首页区域

src/pages/home/index.js

import React from 'react';
import './index.less';
import {
Row} from 'antd';
class index extends React.Component {

constructor(props) {

super(props);
this.state = {

};
}
render() {

return (
<Row className="home-wrap" justify="center">
欢迎来到后台管理系统!!!
</Row>
);
}
}
export default index;

src/pages/home/index.less

.home-wrap{

height: calc(72vh);
width: 95%;
position: absolute;
margin-top: 25px;
background-color: white;
align-items: center;
justify-content: center;
font-size: 20px;
}

三、项目添加路由

src/IRouter.js

import React from 'react';
import {
BrowserRouter,Switch,Route} from 'react-router-dom';
import App from './App';
import Admin from './Admin';
import Home from './pages/home';
import NotMatch from './pages/NotMatch';
class IRouter extends React.Component {

constructor(props) {

super(props);
this.state = {

};
}
render() {

return (
<BrowserRouter>
<App>
<Route path="/admin" render={
()=>
<Admin>
<Switch>
<Route path="/admin/home">
<Home/>
</Route>
<Route >
<NotMatch/>
</Route>
</Switch>
</Admin>
}>
</Route>
</App>
</BrowserRouter>
);
}
}
export default IRouter;

具体路由配置可看React-Router5路由使用教程

四、项目添加用户登录 退出功能

首先参考Antd中表单中的登录框来绘制本次后台管理系统的登录界面。

src/pages/login/index.js中绘制登录框,并对提交信息进行简单的表单验证,并将信息存入localstorage中。

import React from 'react';
import './index.less';
import {
 UserOutlined, LockOutlined } from '@ant-design/icons';
import {
 Row,Col,Form, Input, Button, Checkbox } from 'antd';
import util from '../../utils/utils';
import {
withRouter} from 'react-router-dom';
class index extends React.Component {

constructor(props) {

super(props);
this.state = {

username:'',
password:'',
redirect:'/admin/home'
};
}
// 获取输入框的信息
onInputChange=(e)=>{

let inputname = e.target.name;
let inputvalue = e.target.value;
this.setState({

[inputname]:inputvalue
})
}
onSubmit=()=>{

// 登录信息
let logInfo={

username:this.state.username,
password:this.state.password
};
// 表单验证
let checkResult = util.checkInfo(logInfo);
// 判断表单验证结果
if(checkResult === 'success'){

// localstorage存取
util.setStorage('userInfo',logInfo);
// 推往主页
this.props.history.push(this.state.redirect);
}else{

alert("账户和密码输入有误!请重新输入!");
}
}
render() {

return (
<Row className="login" justify="center" align="middle" >
<Col span={
8}>
<h1>欢迎登录后台管理系统</h1>
<Form className="login-form" initialValues={
{
 remember: true }}>
<Form.Item name="username" rules={
[{
 required: true, message: '请输入用户名!!!' }]}>
<Input name="username" prefix={
<UserOutlined className="site-form-item-icon" />} placeholder="请输入用户名" onChange={
this.onInputChange} />
</Form.Item>
<Form.Item name="password" rules={
[{
 required: true, message: '请输入密码!!!' }]}>
<Input name="password" prefix={
<LockOutlined className="site-form-item-icon" />}type="password" placeholder="请输入密码" onChange={
this.onInputChange} />
</Form.Item>
<Form.Item>
<Form.Item name="remember" valuePropName="checked" noStyle>
<Checkbox>记住用户和密码</Checkbox>
</Form.Item>
<a className="login-form-forgot" >
忘记密码
</a>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" className="login-form-button" onClick={
this.onSubmit} >
登录
</Button>
</Form.Item>
</Form>
</Col>
</Row>
);
}
}
export default withRouter(index);

具体的有关localstorage的存取的操作见src/utils/utils

export default{

// 规范化时间格式
formateDate(time){

if(!time)
return '';
let date = new Date(time);
return date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate() + " " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
},
// 简单的检查表单登录
checkInfo(data){

if(data.username=='admin'&data.password=='admin')
return 'success'
return 'faild'
},
// localstorage读取数据
setStorage(name,data){

let dataType = typeof data;
if (dataType == 'object'){

window.localStorage.setItem(name,JSON.stringify(data));
}else if(['number','string','boolean'].indexOf(dataType)>=0){

window.localStorage.setItem(name,data);
}else{

alert("该类型不能用于本地存储");
}
},
// localstorage取数据
getStorage(name){

let data = window.localStorage.getItem(name)
if(data){

return JSON.parse(data);
}else{

return '';
}
},
// localstorage移除数据
removeStorage(name){

window.localStorage.removeItem(name);
}
}


最后给出github地址:github

那么,这次要结束了!!!
马上就要到10月份了,今年过的是真的很快!!! 10月份之后就要开始好好准备基础和刷题了!!!
在这里插入图片描述

版权声明
本文为[mind_programmonkey]所创,转载请带上原文链接,感谢
https://codingchaozhang.blog.csdn.net/article/details/108615870

  1. [front end -- JavaScript] knowledge point (IV) -- memory leakage in the project (I)
  2. This mechanism in JS
  3. Vue 3.0 source code learning 1 --- rendering process of components
  4. Learning the realization of canvas and simple drawing
  5. gin里获取http请求过来的参数
  6. vue3的新特性
  7. Get the parameters from HTTP request in gin
  8. New features of vue3
  9. vue-cli 引入腾讯地图(最新 api,rocketmq原理面试
  10. Vue 学习笔记(3,免费Java高级工程师学习资源
  11. Vue 学习笔记(2,Java编程视频教程
  12. Vue cli introduces Tencent maps (the latest API, rocketmq)
  13. Vue learning notes (3, free Java senior engineer learning resources)
  14. Vue learning notes (2, Java programming video tutorial)
  15. 【Vue】—props属性
  16. 【Vue】—创建组件
  17. [Vue] - props attribute
  18. [Vue] - create component
  19. 浅谈vue响应式原理及发布订阅模式和观察者模式
  20. On Vue responsive principle, publish subscribe mode and observer mode
  21. 浅谈vue响应式原理及发布订阅模式和观察者模式
  22. On Vue responsive principle, publish subscribe mode and observer mode
  23. Xiaobai can understand it. It only takes 4 steps to solve the problem of Vue keep alive cache component
  24. Publish, subscribe and observer of design patterns
  25. Summary of common content added in ES6 + (II)
  26. No.8 Vue element admin learning (III) vuex learning and login method analysis
  27. Write a mini webpack project construction tool
  28. Shopping cart (front-end static page preparation)
  29. Introduction to the fluent platform
  30. Webpack5 cache
  31. The difference between drop-down box select option and datalist
  32. CSS review (III)
  33. Node.js学习笔记【七】
  34. Node.js learning notes [VII]
  35. Vue Router根据后台数据加载不同的组件(思考-&gt;实现-&gt;不止于实现)
  36. Vue router loads different components according to background data (thinking - & gt; Implementation - & gt; (more than implementation)
  37. 【JQuery框架,Java编程教程视频下载
  38. [jQuery framework, Java programming tutorial video download
  39. Vue Router根据后台数据加载不同的组件(思考-&gt;实现-&gt;不止于实现)
  40. Vue router loads different components according to background data (thinking - & gt; Implementation - & gt; (more than implementation)
  41. 【Vue,阿里P8大佬亲自教你
  42. 【Vue基础知识总结 5,字节跳动算法工程师面试经验
  43. [Vue, Ali P8 teaches you personally
  44. [Vue basic knowledge summary 5. Interview experience of byte beating Algorithm Engineer
  45. 【问题记录】- 谷歌浏览器 Html生成PDF
  46. [problem record] - PDF generated by Google browser HTML
  47. 【问题记录】- 谷歌浏览器 Html生成PDF
  48. [problem record] - PDF generated by Google browser HTML
  49. 【JavaScript】查漏补缺 —数组中reduce()方法
  50. [JavaScript] leak checking and defect filling - reduce() method in array
  51. 【重识 HTML (3),350道Java面试真题分享
  52. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  53. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  54. [re recognize HTML (3) and share 350 real Java interview questions
  55. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  56. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  57. 【重识 HTML ,nginx面试题阿里
  58. 【重识 HTML (4),ELK原来这么简单
  59. [re recognize HTML, nginx interview questions]
  60. [re recognize HTML (4). Elk is so simple