美文网首页技术干货React.js
react技术栈构建后台管理系统模版

react技术栈构建后台管理系统模版

作者: Evtion | 来源:发表于2019-06-04 00:33 被阅读2次

    之前一直开发的技术栈主要是VueJS相关,平时也有阅读React文档,但是没有把React相关技术栈串联起来,形成一个后台系统的模板。在学习的过程之中,基于React开发推荐的create-react-app脚手架搭建管理系统模板。

    开发依赖

    antd: "^3.19.1",
    axios: "^0.19.0",
    bizcharts: "^3.5.3",
    react: "^16.8.6",
    react-dom: "^16.8.6",
    react-redux: "^7.0.3",
    react-router-dom: "^5.0.0",
    react-transition-group: "^4.1.0",
    redux: "^4.0.1"   
    

    git仓库地址

    React-admin-system

    运行效果

    开发这个管理系统主要目的是理清React-Router v4React-ReduxRedux等常用类库的布置和使用。在掘金浏览许多关于React技术开发的文章。关于管理系统对于用户登录权限认证和系统路由布置使用以及对ajax第三方类库二次封装等文章比较少。所以下面会比较着重描述一下个人开发过程中这部分的实现。

    login
    DataCount
    progress

    目录分析

    开发对于请求使用的是第三方请求库axios,对于axios的封装主要在平时Vuejs开发时候对请求封装实践。开发主要部分是util/fakeAuth.jsrouter/PrivateRoute.js,这部分是对用户登录状态验证。而components/ContentMain是登录后的主要路由设置。

    ├─public(静态资源目录)
    ├─screenShot(开发现阶段运行截图)
    ├─service(service服务Koa)
    │  ├─bin
    │  ├─config
    │  ├─controller
    │  ├─model
    │  ├─routes
    │  └─util
    └─src
        ├─api(请求二次封装)
        ├─assets(开发静态资源目录)
        │  └─images
        ├─components(图标类组件)
        │  ├─AreaMap
        │  ├─Chart
        │  ├─ContentMain
        │  ├─Diagram
        │  ├─Line
        │  ├─Map
        │  └─SiderNav(sider侧边导航栏)
        ├─redux(store组件)
        ├─router(路由组件)
        ├─util(权限验证函数)
        └─views(主要开发组件)
            ├─Alert
            ├─Avatar
            ├─Basic
            ├─Cascader
            ├─Checkbox
            ├─DataChart
            ├─Form
            ├─Index
            ├─Login
            ├─Message
            ├─NoMatch
            ├─Progress
            └─Spin
    

    login用户登录状态验证

    包装PrivateRoute权限路由

    React-Router的路由组件Route,包装路由组件使需要登录获取权限的路由,需要自动认证再进行渲染。渲染组件需要通过权限认证函数fakeAuth.authenticate()进行验证,该函数会判别是否存在后端接口返回的token值,分别渲染不同组件。

    import React from 'react';
    import {Route,Redirect} from 'react-router-dom';
    import {fakeAuth} from '../util/fakeAuth';
    const PrivateRoute = ({component:Component,...rest})=>{
        return (
            <Route
                {...rest}
                render = {props => (fakeAuth.authenticate())?(<Component {...props}/>):(
                    <Redirect to={{
                        pathname:"/login",
                        state:{from:props.location}
                    }}/>
                )}
            ></Route>
        )
    }
    export default PrivateRoute;
    
    fakeAuth验证函数

    fakeAuth文件包含三个函数authenticatesetTokensignout,以上分别对应验证登录权限、设置登录token、清除登录token。

    export const fakeAuth = {
        authenticate() {
            const token = sessionStorage.getItem("loginToken");
            return !!token ? true : false;
        },
        setToken(token) {
            sessionStorage.setItem("loginToken", token);
            return true;
        },
        signout() {
            sessionStorage.removeItem('loginToken');
    
        }
    };
    
    login登录验证详细

    login.js通过fakeAuth.authenticate()验证,然后分别渲染不同组件。<Redirect>组件在这里主要有两个作用:

    • 用户登录获取权限路由权限后,在浏览器地址栏重新输入/login路由会自动返回权限路由路由首页。
    • 对于未登录用户,自动跳转到登录页。
    import React,{Component} from 'react';
    import {Redirect} from 'react-router-dom';
    import {fakeAuth} from '../../util/fakeAuth';
    import LoginForm from './index';
    export default class Login extends Component{
        render(){
            return (
                fakeAuth.authenticate()?<Redirect to="/"></Redirect>:<LoginForm />
            )
        }
    }
    
    登录请求代码

    登录认证请求代码在views/login/loginForm中,handleSubmit是登录事件函数,主要对获取用户权限接口获取token,然后进行路由跳转.this.props.history.pushReact-Router v4版本特有的写法,其他版本可以参考官方文档。要获取到this.props.history需要withRouter对组件传入location,match,history等信息。

        handleSubmit = e => {
            e.preventDefault();
            this.props.form.validateFields((err, values) => {
              if (!err) {
                //这里需要对后端接口请求,调试中
                fakeAuth.setToken("zxcvbnmasdfghjkl");
                this.props.history.push('/dataCount');
                message.success('登陆成功',1);
                return;
              }
            });
        }
    

    App.js入口文件

    login是公开的路由,其他需要权限的路由包含在PrivateRoute组件中,最后一个如果没有组件匹配,最后匹配的是我们自定义的404页面

    import React from 'react';
    import {BrowserRouter as Router,Route,Switch} from 'react-router-dom';
    import {Provider} from 'react-redux';
    import {store} from './redux/index.js';
    import {CSSTransition} from "react-transition-group";
    import Login from './views/Login/login';
    import Index from './views/Index';
    import PrivateRoute from './router/PrivateRoute';
    import NoMatch from './views/NoMatch';
    import history from './api/history';
    import './App.css';
    function App() {
      return (
        <Provider store={store}>
          <Router basename="/echo" history={history}>
              <div className="entryWrap">
                  <CSSTransition
                    classNames="fade"
                    timeout={1000}
                  >
                    <Switch>
                      <Route path="/login" component={Login} exact/>
                      <PrivateRoute path="/" component={Index}/>
                      <Route component={NoMatch}/>
                    </Switch>
                  </CSSTransition>
              </div>
          </Router>
        </Provider>
      );
    }
    export default App;
    

    ContentMain权限路由路由配置页面

    ContentMain主要是配置了权限路由的配置。使用PrivateRoute包装路由,方便性由此可见。配置路由没有比较难逻辑,如下所示:

    import React,{Component} from 'react';
    import {Switch,withRouter} from 'react-router-dom';
    import PrivateRoute from '../../router/PrivateRoute';
    import DataChart from '../../views/DataChart';
    import Basic from '../../views/Basic';
    import Form from '../../views/Form';
    import Message from '../../views/Message';
    import Alert from '../../views/Alert';
    import Spin from '../../views/Spin';
    import Progress from '../../views/Progress';
    import Checkbox from '../../views/Checkbox';
    import Cascader from '../../views/Cascader';
    import NoMatch from '../../views/NoMatch';
    import './index.css';
    class ContentMain extends Component{
        render(){
            return(
                <div className="routeWrap">
                    <Switch>
                        <PrivateRoute path="/dataCount" exact component = {DataChart}/>
                        <PrivateRoute path="/basic" exact component = {Basic}/>
                        <PrivateRoute path="/form" exact component = {Form}/>
                        <PrivateRoute path="/alert" exact component = {Alert}/>
                        <PrivateRoute path="/message" exact component = {Message}/>
                        <PrivateRoute path="/spin" exact component = {Spin}/>
                        <PrivateRoute path="/progress" exact component = {Progress}/>
                        <PrivateRoute path="/checkbox" exact component = {Checkbox}/>
                        <PrivateRoute path="/cascader" exact component = {Cascader}/>
                        <Route component={NoMatch}/>
                    </Switch>
                </div>
            )
        }
    }
    export default withRouter(ContentMain);
    

    axios二次封装统一请求处理

    api/index.js主要包含了对axios第三方请求库的二次封装,包含错误统一处理以及不同请求方法GET、POST、DELETE、PUT等统一风格的api。关于对token请求权限过期,返回请求状态码401,清除token,重定向到/logn处理逻辑也会在这里。在这一部分,Vuejs的处理逻辑也很类似,但是比较熟悉可以直接通过以下方式进行重定向:

    import router from "../router/index.js";
    router.replace({
        path: "/login",
        query: {
            redirect: router.currentRoute.path
        }
    });
    
    

    但是对于React-Router,网上浏览比较多的文章,尝试多比较多遍,都没有找到一个不是强制刷新的路由方案,使用window.location.href可以强制跳转,但是这里使用了createBrowserHistory方法进行重定向。如果有其他的方案可以给我留言。菜鸡的我才能茁壮成长。下面是关于封装的代码部分:

    import axios from "axios"; 
    import {fakeAuth} from '../util/fakeAuth';
    import {message as Message} from 'antd';
    import {timeout,baseURL} from "./config.js";
    import history from './history';
    axios.defaults.timeout = timeout;
    axios.defaults.baseURL = baseURL;
    axios.interceptors.request.use(
        config => {
            if (fakeAuth.authenticate()) {
                config.headers.Authorization = `Bearer ${sessionStorage.getItem('loginToken')}`;
            }
            return config;
        },
        error => {
            return Promise.reject(error);
        }
    );
    axios.interceptors.response.use(
        response => {
            return response;
        },
        error => {
            if (error.response) {
                switch (error.response.status) {
                    case 401:
                        fakeAuth.signout();
                        history.push('/login');
                        break;
                    default:
                }
                const message = error.response.data.message ?error.response.data.message :"服务器异常";
                Message.error(message);
            }
            return Promise.reject(error);
        }
    );
    const gl_ajax = params => {
        return axios({
                method: params.method.toLowerCase(),
                url: `${axios.defaults.baseURL}${params.url}`,
                data: params.method !== "get" ? params.data : "",
                params: params.method === "get" ? params.data : "",
                responseType: params.file ? "blob" : ""
            })
            .then(res => {
                params.success && params.success(res);
            })
            .catch(err => {
                params.error && params.error(err);
            });
    };
    export default gl_ajax;
    

    history文件部分是参考了网友给的技术方案,利用了createBrowserHistory({forceRefresh:true}),这里show出来给大家参考一下:

    // history.js
    import { createBrowserHistory } from "history";
    export default createBrowserHistory({forceRefresh:true}); 
    
    // config.js
    export const timeout = 5000;
    export const baseURL =
      process.env.NODE_ENV === "production"
        ? "https://echo/api/v1"
        : "http://localhost:8080/api/v1";
    

    如果觉得喜欢可以给个小星星(star)吗?

    React-admin-system

    参考文章

    [译] 2019 React Redux 完全指南

    [译]React中的用户认证(登录态管理)

    React Router 4.x开发,这些雷区我们都帮你踩过了

    相关文章

      网友评论

        本文标题:react技术栈构建后台管理系统模版

        本文链接:https://www.haomeiwen.com/subject/tzjkxctx.html