前言javascript
學習總結使用,博客如中有錯誤的地方,請指正。改系列文章主要記錄了搭建一個管後臺的步驟,主要實現的功能有:使用路由模擬登陸、退出、以及切換不一樣的頁面;使用redux實現麪包屑;引入使用其餘經常使用的組件,好比highchart、富文本等,後續會繼續完善。css
github地址:https://github.com/huangtao5921/react-antDesgin-admin (歡迎Star)html
項目展現地址:https://huangtao5921.github.io/react-admin/ java
1、處理登陸react
上一篇文章中 react + react-router + redux + ant-Desgin 搭建管理後臺 -- 頁面佈局(五)咱們已經將整個首頁的佈局呈現了出來,而且點擊不一樣的側邊欄能跳轉到不一樣的頁面,移入頭部的用戶頭像,有退出登陸的下拉選項,可是功能並無實現,而且咱們隨便輸入一個路由,好比用戶列表的,側邊欄默認選中的一直是首頁,咱們接下來處理這2個問題。git
首先,瀏覽器輸入http://localhost:3000/login,跳轉到登陸頁,咱們來進行頁面佈局,並書寫基本的邏輯,因爲咱們是本地模擬登陸,因此登陸驗證成功以後,我在本地緩存了一個登陸成功的信息 loggedIn:true。爲 true 表明登陸成功,false或不存在表明未登陸,其實就至關於咱們真實項目中的token。思路是:每次進入登陸頁的時候,咱們獲取一下本地緩存的loggedIn,若是是登陸的狀態,直接跳轉到首頁。樣式寫在src/pages/login/login.css中,接下來,將src/pages/login/Login.js代碼改寫以下:github
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,這樣說明咱們的登陸已經簡單的實現了。redux
2、處理退出登陸
接下來咱們再處理一下退出登陸,還記得退出登陸按鈕在哪裏嗎?打開咱們的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時,會被重置到登陸頁,登陸的狀況下進入到正確的頁面。
2、處理默認選中側邊欄
接下來處理另一個問題,當咱們在瀏覽器中輸入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並處理麪包屑(七)