react + react-router + redux + ant-Desgin 搭建管理后台 -- 处理登录及默认选中侧边栏(六)

Posted huangtao5921

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了react + react-router + redux + ant-Desgin 搭建管理后台 -- 处理登录及默认选中侧边栏(六)相关的知识,希望对你有一定的参考价值。

  上一篇文章中 react + react-router + redux + ant-Desgin 搭建管理后台 -- 页面布局(五)我们已经将整个首页的布局呈现了出来,并且点击不同的侧边栏能跳转到不同的页面,移入头部的用户头像,有退出登录的下拉选项,但是功能并没有实现,并且我们随便输入一个路由,比如用户列表的,侧边栏默认选中的一直是首页,我们接下来处理这2个问题。

  首先,浏览器输入http://localhost:3000/login,跳转到登录页,我们来进行页面布局,并书写基本的逻辑,由于我们是本地模拟登录,所以登录验证成功之后,我在本地缓存了一个登录成功的信息 loggedIn:true。为 true 代表登录成功,false或不存在代表未登录,其实就相当于我们真实项目中的token。思路是:每次进入登录页的时候,我们获取一下本地缓存的loggedIn,如果是登录的状态,直接跳转到首页。样式写在src/pages/login/login.css中,接下来,将src/pages/login/Login.js代码改写如下:

import React from ‘react‘;
import  Form, Icon, Input, Button, message  from ‘antd‘;
import  Redirect  from ‘react-router-dom‘;
import ‘./login.css‘;
class Login extends React.Component 
  handleSubmit = e => 
    e.preventDefault();
    this.props.form.validateFields((err, values) => 
      if (!err) 
        if (values.username === ‘admin‘ && values.password === ‘123‘) 
          window.localStorage.setItem(‘loggedIn‘, true);
          this.props.history.push(‘/‘);
         else 
          message.error(‘账号或密码错误‘, 1);
        
      
    );
  ;
  render() 
    const  getFieldDecorator  = this.props.form;
    const loggedIn = window.localStorage.getItem(‘loggedIn‘);
    const LoginForm = (
      <div className="login-container">
        <Form onSubmit=this.handleSubmit className="login-form">
          <div className="sub-title">登 录</div>
          <Form.Item>
             getFieldDecorator(‘username‘, 
              rules: [ required: true, message: ‘请输入用户名!‘ ],
            )(
              <Input prefix=<Icon type="user" className=‘login-icon‘ /> placeholder="用户名admin"/>,
            )
          </Form.Item>
          <Form.Item>
             getFieldDecorator(‘password‘, 
              rules: [ required: true, message: ‘请输入密码!‘ ],
            )(
              <Input prefix=<Icon type="lock" className=‘login-icon‘/> type="password" placeholder="密码123"/>,
            )
          </Form.Item>
          <Form.Item>
            <Button type="primary" htmlType="submit" className="login-form-button">登录</Button>
          </Form.Item>
        </Form>
      </div>
    );
    return (
      loggedIn ? (
        <Redirect to="/"/>
      ) : LoginForm
    );
  

const WrappedNormalLoginForm = Form.create( name: ‘normal_login‘ )(Login);
export default WrappedNormalLoginForm;

  此时,访问http://localhost:3000/login如果我们没有登录,会展示如下,如果我们登录过了一次之后,在浏览器输入http://localhost:3000/login,会直接跳转到首页,除非清除掉缓存的loggedIn,这样说明我们的登录已经简单的实现了。

技术图片

  接下来我们再处理一下退出登录,还记得退出登录按钮在哪里吗?打开我们的src/component/layout/HeaderBar.js,找到退出登录按钮,加上退出登录的逻辑。被<Route>引入的组件才能读取到this.props.history,所以我们需要把this.props.history或者将事件传递到子组件中。基于此,我们需要改变以下文件的代码:

  routes/index.js中将history对象传递到子组件中:

 
<HeaderBar></HeaderBar>  
改为
<HeaderBar history=this.props.history></HeaderBar>

  src/component/layout/HeaderBar.js组件中改变以下代码:

HeaderBar中的
<UserInfo/>
改为
<UserInfo history= props.history />

UserInfo组件中加处理函数
handleMenuClick = e => 
  if (e.key === ‘outLogin‘) 
    this.setState(
      visible: false
    );
    window.localStorage.removeItem(‘loggedIn‘);
    this.props.history.push(‘/login‘);
  
;

<Menu>
  <Menu.Item key="outLogin">退出登录</Menu.Item>
</Menu>
改为
<Menu onClick= this.handleMenuClick >
  <Menu.Item key="outLogin">退出登录</Menu.Item>
</Menu>

  最后HeaderBar.js的代码呈现为:

import React from ‘react‘;
import  Layout, Menu, Dropdown, Icon, Breadcrumb  from ‘antd‘;
import customUrl from ‘../../images/custom.jpeg‘;
const  Header  = Layout;

class UserInfo extends React.Component 
  state = 
    visible: false,   // 菜单是否显示
  ;
  handleMenuClick = e => 
    if (e.key === ‘outLogin‘) 
      this.setState(
        visible: false
      );
      window.localStorage.removeItem(‘loggedIn‘);
      this.props.history.push(‘/login‘);
    
  ;
  handleVisibleChange = flag => 
    this.setState( visible: flag );
  ;
  render() 
    const menu = (
      <Menu onClick= this.handleMenuClick >
        <Menu.Item key="outLogin">退出登录</Menu.Item>
      </Menu>
    );
    return (
      <Dropdown overlay= menu  onVisibleChange= this.handleVisibleChange  visible= this.state.visible >
        <div className="ant-dropdown-link">
          <img className="custom-img" src= customUrl  />
          <Icon type="caret-down" />
        </div>
      </Dropdown>
    );
  

const HeaderBar = (props) => 
  return (
    <Header>
      <Breadcrumb>
        <Breadcrumb.Item>首页</Breadcrumb.Item>
      </Breadcrumb>
      <UserInfo history= props.history />
    </Header>
  );
;
export default HeaderBar;

  现在我们点退出登录,可以回到登录页,从登录点登录可以跳转到首页,但是在么有登录的情况下我们在浏览器中输入http://localhost:3000/还是可以访问到首页,这是不正常的,只有登录成功之后才有权限查看首页,没有登录直接输入地址,我们应该重置到登录页,这里类似在登录页处理逻辑。所以我们改变一下routes/index.js中的代码,引入Redirect:

// 引入Redirect
import  Route, Switch, Redirect  from ‘react-router-dom‘;

// render函数改成如下:
render() 
    const loggedIn = window.localStorage.getItem(‘loggedIn‘);
    const mainPage = (
      <Layout>
        <SiderBar></SiderBar>
        <Layout>
          <HeaderBar history=this.props.history></HeaderBar>
          <div className="layout-content">
            <Switch>
              <Route exact path="/" component= Home />
              <Route path="/user/connect" component= Connect />
              <Route path="/user/list" component= List />
              <Route path="/tool/rich" component= Rich />
              <Route component= NotFind />
            </Switch>
          </div>
        </Layout>
      </Layout>
    );
    return (
      loggedIn ? (
        mainPage
      ) : (
        <Redirect to="/login"/>
      )
    );
  

  此时,在没有登录的情况下,在浏览器中输入首页或者其他页面的url时,会被重置到登录页,登录的情况下进入到正确的页面。

  接下来处理另外一个问题,当我们在浏览器中输入http://localhost:3000/user/list时,侧边栏默认选中的还是首页,这是因为我们在侧边栏组件里面将默认选中和默认展开写死了。这里我们处理一下,思路是根据每次打开的url的pathname来找到我们目前访问页面的对应的侧边栏。

defaultOpenKeys: [],       // 默认展开
defaultSelectedKeys: [‘/‘],   // 默认选中

  接下来,改写src/component/layout/SiderBar.js代码,这里处理的比较死板,只能处理2级的路由,有好的方法可以改写。

  // 新增handleDefaultSelect,每次刷新执行一遍
  componentWillMount() 
    this.handleDefaultSelect();
    const menuList = this.setMenu(menuConfig);
    this.setState(
      menuList
    );
  

  // 刷新页面,处理默认选中
  handleDefaultSelect = () => 
    let menuConfigKeys = [];
    menuConfig.forEach((item) => 
      menuConfigKeys.push(item.key);
    );
    const pathname = window.location.pathname;
    const currentKey = ‘/‘ + pathname.split(‘/‘)[1];
    if (menuConfigKeys.indexOf(currentKey) === 1) 
      this.setState(
        defaultOpenKeys: [currentKey],
        defaultSelectedKeys: [pathname],
      );
    
  

  此时,在页面输入http://localhost:3000/user/list,会发现用户那一栏被打开,用户列表被选中了。

技术图片

  目前为止,首页里面处理面包屑部分不会随着路由改变,其他的地方包括登录以及退出登录均已经正常了。

 

以上是关于react + react-router + redux + ant-Desgin 搭建管理后台 -- 处理登录及默认选中侧边栏(六)的主要内容,如果未能解决你的问题,请参考以下文章

[Preact] Integrate react-router with Preact

十react-router 4.x的基本配置

如何使用 react-router 在组件中保存表单的状态

尝试使用router.history.goBack与react-router时获得警告

[react-router] React-Router怎么获取历史对象?

React-Router面试题汇总