react + react-router + redux + ant-Desgin 搭建react管理后台 -- 處理登錄及默認選中側邊欄(六)


前言

  學習總結使用,博客如中有錯誤的地方,請指正。改系列文章主要記錄了搭建一個管后台的步驟,主要實現的功能有:使用路由模擬登錄、退出、以及切換不同的頁面;使用redux實現面包屑;引入使用其他常用的組件,比如highchart、富文本等,后續會繼續完善。

  github地址:https://github.com/huangtao5921/react-antDesgin-admin (歡迎Star)

  項目展示地址:https://huangtao5921.github.io/react-admin/ 

 

一、處理登錄

  上一篇文章中 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 } alt=""/>
          <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,會發現用戶那一欄被打開,用戶列表被選中了。

  目前為止,首頁里面處理面包屑部分不會隨着路由改變,其他的地方包括登錄以及退出登錄均已經正常了。

  注:交流問題的可以加QQ群:531947619

    

 下一篇:react + react-router + redux + ant-Desgin 搭建react管理后台 -- 引入rudex並處理面包屑(七)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM