一步步搭建react后臺(tái)系統(tǒng)4

一步一步構(gòu)件react后臺(tái)系統(tǒng)4 之注冊(cè)頁面

添加注冊(cè)頁面

  1. 添加頁面
  • views/register/index
    這里依然采用ant里面的Form注冊(cè)組件
    其他新增的或修改的會(huì)打上標(biāo)記, 沒打標(biāo)記的梢褐, 都是ant的form注冊(cè)組件
import React from 'react'   // +
import { Form, Input, Tooltip, Icon, Cascader, Select, Row, Col, Checkbox, Button, AutoComplete } from 'antd';
import { validatorPhone } from '@/utils/index'  // +
import './index.css'  // +
const FormItem = Form.Item;
const Option = Select.Option;
const AutoCompleteOption = AutoComplete.Option;

class RegistrationForm extends React.Component {
    state = {
        confirmDirty: false,
        autoCompleteResult: []
    };

    handleSubmit = (e) => {
        e.preventDefault();
        this.props.form.validateFieldsAndScroll((err, values) => {
            if (!err) {
                console.log('Received values of form: ', values);
            }
        });
    }

    handleConfirmBlur = (e) => {
        const value = e.target.value;
        this.setState({ confirmDirty: this.state.confirmDirty || !!value });
    }

    compareToFirstPassword = (rule, value, callback) => {
        const form = this.props.form;
        if (value && value !== form.getFieldValue('password')) {
            callback('Two passwords that you enter is inconsistent!');
        } else {
            callback();
        }
    }

    validateToNextPassword = (rule, value, callback) => {
        const form = this.props.form;
        if (value && this.state.confirmDirty) {
            form.validateFields(['confirm'], { force: true });
        }
        callback();
    }

    handleWebsiteChange = (value) => {
        let autoCompleteResult;
        if (!value) {
            autoCompleteResult = [];
        } else {
            autoCompleteResult = ['.com', '.org', '.net'].map(domain => `${value}${domain}`);
        }
        this.setState({ autoCompleteResult });
    }
    // 獲取驗(yàn)證碼, 傳遞給父組件
    getCaptcha = (e) => {  // +
        var num = Math.floor(Math.random()*10000)
        this.props.handleCaptcha(num)
    }

    render() {
        const { getFieldDecorator } = this.props.form;
        const { autoCompleteResult } = this.state;
        const formItemLayout = {
            labelCol: {
                xs: { span: 24 },
                sm: { span: 8 },
            },
            wrapperCol: {
                xs: { span: 24 },
                sm: { span: 16 },
            },
        };
        const tailFormItemLayout = {
            wrapperCol: {
                xs: {
                    span: 24,
                    offset: 0,
                },
                sm: {
                    span: 16,
                    offset: 8,
                },
            },
        };
        const prefixSelector = getFieldDecorator('prefix', {
            initialValue: '86',
        })(
            <Select style={{ width: 70 }}>
                <Option value="86">+86</Option>
                <Option value="87">+87</Option>
            </Select>
        );

        const websiteOptions = autoCompleteResult.map(website => (
            <AutoCompleteOption key={website}>{website}</AutoCompleteOption>
        ));
        // +- 里面的組件都修改了。
        return (
            <div className="register">
                <div className="register-form">
                <Form onSubmit={this.handleSubmit} >
                    <FormItem
                        {...formItemLayout}
                        label="用戶別名"
                    >
                        {getFieldDecorator('username', {
                            rules: [{
                                message: '請(qǐng)輸入用戶名稱',
                            }, {
                                required: true, message: '用戶名稱必填',
                            }],
                        })(
                            <Input />
                        )}
                    </FormItem>
                    <FormItem
                        {...formItemLayout}
                        label="用戶密碼"
                    >
                        {getFieldDecorator('password', {
                            rules: [{
                                required: true, message: '請(qǐng)輸入用戶密碼!',
                            }, {
                                validator: this.validateToNextPassword,
                            }],
                        })(
                            <Input type="password" />
                        )}
                    </FormItem>
                    <FormItem
                        {...formItemLayout}
                        label="確認(rèn)密碼"
                    >
                        {getFieldDecorator('confirm', {
                            rules: [{
                                required: true, message: '請(qǐng)驗(yàn)證密碼',
                            }, {
                                validator: this.compareToFirstPassword,
                            }],
                        })(
                            <Input type="password" onBlur={this.handleConfirmBlur} />
                        )}
                    </FormItem>
                    <FormItem
                        {...formItemLayout}
                        label="手機(jī)號(hào)碼"
                    >
                        {getFieldDecorator('phone', {
                            rules: [{ required: true, message: '請(qǐng)輸入正確的手機(jī)號(hào)碼' },
                                {validator: validatorPhone.bind(this)()} //  + 添加了驗(yàn)證手機(jī)正則
                            ],
                        })(
                            <Input addonBefore={prefixSelector} style={{ width: '100%' }} />
                        )}
                    </FormItem>
                    <FormItem
                        {...formItemLayout}
                        label="驗(yàn)證碼"
                        extra="點(diǎn)擊獲取驗(yàn)證碼级历, 驗(yàn)證碼將會(huì)自動(dòng)填寫"
                    >
                        <Row gutter={8}>
                            <Col span={12}>
                                {getFieldDecorator('captcha', {
                                    rules: [{ required: true, message: '請(qǐng)輸入正確的驗(yàn)證碼' }],
                                })(
                                    <Input disabled/>  // +  只讀
                                )}
                            </Col>
                            <Col span={12}>
                                <Button onClick={this.getCaptcha}>獲取驗(yàn)證碼</Button>   // +- 添加驗(yàn)證碼事件
                            </Col>
                        </Row>
                    </FormItem>
                    <FormItem
                        {...formItemLayout}
                        label={(
                            <span> 電子郵箱</span>
                        )}
                    >
                        {getFieldDecorator('email', {
                            rules: [{ required: false, message: '請(qǐng)輸入電子郵箱', whitespace: true }],
                        })(
                            <Input />
                        )}
                    </FormItem>
                    <FormItem {...tailFormItemLayout}>
                        <Button type="primary" htmlType="submit">注冊(cè)</Button>
                    </FormItem>
                </Form>
                </div>
            </div>
        );
    }
}

// 當(dāng)input發(fā)生改變時(shí)诗舰, 調(diào)用父?jìng)鬟f過來的事件。
const onFieldsChange = (props, changeFields) => {
    props.onChange(changeFields)
}
// 接受到值, 并注入Form組件內(nèi)
const mapPropsToFields = props => {
    let captcha = props.captcha
    captcha && captcha.value && captcha.errors && delete captcha.errors  // 當(dāng)存在值的時(shí)候语卤, 刪除errors
    return {
        username: Form.createFormField({
            ...props.username,
        }),
        password: Form.createFormField({
            ...props.password
        }),
        confirm: Form.createFormField({
            ...props.confirm
        }),
        phone: Form.createFormField({
            ...props.phone
        }),
        captcha: Form.createFormField({
            ...props.captcha
        }),
        email: Form.createFormField({
            ...props.email
        })
    }
}
// value改變事件
const onValuesChange = (_, values) => {
}

const WrappedRegistrationForm = Form.create({onFieldsChange, mapPropsToFields, onValuesChange})(RegistrationForm);

// 傳遞參數(shù)給form組件
class Register extends React.Component {
    state = {
        fields: {
            username: {
                value: '我是useranme默認(rèn)值'
            }
        }
    }
    // 當(dāng)input的value發(fā)生改變, 就改變值,
    handleFormChange = (changedFields) => {
        this.setState(({fields}) => {
            return {
                fields: {...fields, ...changedFields}
            }
        })
    }
    // 點(diǎn)擊獲取驗(yàn)證碼事件粹舵。
    handleCaptcha = (captchaValue) => {
        this.setState(({fields}) => {
            let captcha = { // 合并captcha對(duì)象钮孵, 修改value
                ...((typeof fields.captcha === 'object') ? fields.captcha : {}),
                value: captchaValue
            }
            return {
                fields: {...fields, captcha}
            }
        })
    }
    render () {
        let fields = this.state.fields
        return (
            <div>
                <WrappedRegistrationForm {...fields} onChange={this.handleFormChange} handleCaptcha={this.handleCaptcha}></WrappedRegistrationForm>
            </div>
        )
    }
}

export default Register
  • views/register/index.css
.register {
    display: -ms-flexbox;
    display: flex;
    -ms-flex-pack: center;
    justify-content: center;
    -ms-flex-align: center;
    align-items: center;
    height: 100%;
    background: #f3f3f3;
}
.register>.register-form {
    width: 60%;
    height: auto;
    padding: 36px;
    -webkit-box-shadow: 0 0 100px rgba(0, 0, 0, 0.08);
    box-shadow: 0 0 100px rgba(0, 0, 0, 0.08);
    background: #fff;
}

#root{
    height: 100%;
}
.App{
    height: 100%;
}

  • utils/index
export const validatorPhone = function () {
    return (rule, value, callback) => {
        const form = this.props.form;
        if (value && !(/^1[3|4|5|8][0-9]\d{4,8}$/.test(form.getFieldValue('phone'))) ) {
            callback('請(qǐng)輸入正確的手機(jī)號(hào)碼');  <Link to="/register">還沒有賬號(hào)? 去注冊(cè)</Link>
        } else {
            callback();
        }
    }
}
  • views/login/index.js

添加一個(gè)注冊(cè)入口

  <Link to="/register">還沒有賬號(hào)眼滤? 去注冊(cè)</Link>
  • router/index.js

別忘了巴席, 添加到路由配置里面
注意: 這里添加了一個(gè)meta對(duì)象, 用來自定義一些參數(shù)诅需。
@params: isAuth<boolean> 是否不需要驗(yàn)證(是否登錄)

import React from 'react'
import Login from '@/views/login/index'
import Index from '@/views/index/index'
import Register from '@/views/register/index' // +
import { RenderRoutes } from '@/router/utils'
const Ui = ({routes}) => (<div>
    <h3>Ui
    </h3>
    <RenderRoutes routes={routes}></RenderRoutes>
</div>)
const Button = () => <h3>Button</h3>
const Icon = () => <h3>Icon</h3>
const Animation = () => <h3>Animation</h3>
const From = () => <h3>From</h3>


export const menus = [    // 菜單相關(guān)路由
    { path: '/index/UI', name: 'UI', icon:'video-camera', component: Ui , routes: [
            {path: '/index/UI/button', name: '按鈕', icon: 'video-camera', component: Button },
            {path: '/index/UI/Icon', name: '圖標(biāo)', icon: 'video-camera', component: Icon }
        ]
    },
    { path: '/index/animation', name: '動(dòng)畫', icon: 'video-camera', component: Animation },
    { path: '/index/form', name: '表格', icon: 'video-camera', component: From },
]
// isAuth 表示不用驗(yàn)證是否登錄
export const main = [
    { path: '/login', exact: true, name: '登錄', component: Login, meta: { // +-
            isAuth: true
        } },
    { path: '/register', exact: true, name: '注冊(cè)', component: Register, meta: { // +
            isAuth: true
        }  },
    { path: '/', exact: true,  name: '首頁', Redirect: '/index'},
    {
        path: '/index', name: '首頁', component: Index,
        routes: menus
    }
]

export const routerConfig =  {
    main, menus
}
  • router/utils.js

修改渲染組件情妖,
當(dāng)路徑是 不需要驗(yàn)證是否登錄的頁面 的時(shí)候, 就不進(jìn)行判斷是否重定向到登錄頁面了诱担。

// 渲染當(dāng)前組件
export const RouteWithSubRoutes = route => (<Route
        path={route.path}
        exact={route.exact}
        render={props =>{
           var isAuthenticated  = sessionStorage.getItem('isAuthenticated')
            if ( !(typeof route.meta === 'object' && route.meta.isAuth) && !isAuthenticated ) {  // +-
                return <Redirect
                    to={{
                        pathname: "/login",
                        state: { from: props.location }
                    }}
                />
            }
            return (
                route &&( route.Redirect ? (<Redirect to={route.Redirect}></Redirect>) :
                (<route.component {...props} routes={route.routes} />))
            )
        }}
    />
);

就這樣毡证, 頁面做好了。

查看github代碼
切換Log 到
添加注冊(cè)頁面蔫仙, 修改路由配置料睛, 修改路由渲染組件, 修改重定向登錄規(guī)則
即可看到當(dāng)前代碼摇邦。

  1. 添加后臺(tái)接口

注冊(cè)頁面做好了恤煞, 但是需要后臺(tái)接口, 這里添加后臺(tái)接口施籍。
先打開后臺(tái)項(xiàng)目居扒。

修改package.json 添加打開項(xiàng)目快捷方式

"nodemon": "nodemon bin/www"  // +

然后運(yùn)行項(xiàng)目

npm run nodemon
  • 修改routes/index.js

// 添加接口

const utils = require ('../utils/index')
let { isEmpty }  = utils

router.post('/register', async (ctx, next) => {
    let body = ctx.request.body
    let username = body.username;
    let password = body.password;
    let captcha = body.captcha;
    let phone = body.phone;
    console.log(body)
    if (isEmpty(username)) {
        ctx.body = {
            code: 0,
            message: "用戶名不能為空",
        }
    }
    else if (isEmpty(password)) {
        ctx.body = {
            code: 0,
            message: "密碼不能為空",
        }
    }
    else if (isEmpty(captcha)) {
        ctx.body = {
            code: 0,
            message: "驗(yàn)證碼不能為空",
        }
    }
    else if (isEmpty(phone)) {
        ctx.body = {
            code: 0,
            message: "手機(jī)號(hào)碼不能為空",
        }
    } else {
        ctx.body = {
            code: 200,
            message: "注冊(cè)成功",
        }
    }
})
  • /utils/index.js

新增工具

const isEmpty = (text) => {
    if (text) {
        return false
    }
    return true
}
module.exports = {
    isEmpty
}

好了 后臺(tái)接口做好了。

  1. 添加接口請(qǐng)求
  • views/register/index
    這里把 connect 的參數(shù)都放到connect里面丑慎, 因?yàn)椋看味夹枰胊ction 喜喂,太過繁瑣,放到一個(gè)頁面統(tǒng)一管理也很方便)
    this.props.hanleRegister(values) 執(zhí)行傳遞過來的接口事件
import {connect} from "react-redux";  // +
import { mapReigster } from '@/reducer/connect.js' // +
handleSubmit = (e) => {
        e.preventDefault();
        this.props.form.validateFieldsAndScroll((err, values) => {
            if (!err) {
                console.log('Received values of form: ', values);
                this.props.hanleRegister(values)  // +
            }
        });
    }


const WrappedRegistrationForm = connect( mapReigster.mapStateToProps, mapReigster.mapDispatchToProps )(Form.create({onFieldsChange, mapPropsToFields, onValuesChange})(RegistrationForm));  // +-
  • reducer/connect.js

這里把創(chuàng)建action創(chuàng)建函數(shù)都封裝起來import { receive } from '@/reducer/actionCreate.js'
封裝一個(gè)fetchPosts事件竿裂, 用來請(qǐng)求數(shù)據(jù)并切換數(shù)據(jù)玉吁。
添加 mapReigster
添加 mapLogin (這里順便把登錄里面的connect參數(shù)也提取出來了)

import { action_slidecollapsed, routerConfig, action_login } from '@/reducer/action.js'
import http from '@/api/http.js'  // +
import { receive } from '@/reducer/actionCreate.js' // +
import { ACTION_LOGIN, ACTION_REGISTER } from '@/reducer/action.js' // +

export const mapStateToProps = (state) => {
    console.log(state)
    return {slidecollapsed:  state.slidecollapsed,
        isSlide: false,
    }
}
export const mapDispatchToProps = (dispatch) => {
    return {onSlidecollapsed: () => dispatch(action_slidecollapsed), getRouterConfig: () => {
            return dispatch(routerConfig)
        }, toggleSlide: () => {
        dispatch({type: action_slidecollapsed.type})
    }}
}

export const crumbsMap = {
    mapStateToProps (state) {
        return { routerConfig: state.routerConfig }
    },
    mapDispatchToProps (dispatch) {
        return {getRouterConfig: () => {
                return dispatch(routerConfig)
            }}
    }
}
@params: url<string> 接口路徑
@params: actionType<string> action.type
@params: subreddit<string> 數(shù)據(jù)名稱
@params: data<object> 數(shù)據(jù)

function fetchPosts(url, actionType, subreddit, data) { // +
    return dispatch => {
        dispatch(receive(actionType, subreddit, '暫無數(shù)據(jù)'))
        return http.post(url, data)
            .then(res => {
                dispatch(receive(actionType, subreddit, res))
            })
    }
}
// 注冊(cè)
export const mapReigster = {
    mapStateToProps (state) {
        return state.getReigster || state
    },
    mapDispatchToProps (dispatch) {
        return {hanleRegister: (data) => {
                return dispatch(fetchPosts('/register', ACTION_REGISTER,'reigsterData', data))
            }}
    }
}
// 登錄
export const mapLogin = {
    mapStateToProps (state) {
        return state.getLogin
    },
    mapDispatchToProps (dispatch) {
        return {handleLogin: (data) => {
                return dispatch(fetchPosts('/login', ACTION_LOGIN, 'loginData', data))
            }}
    }
}


  • reducer/actionCreate.js
import { ACTION_LOGIN, ACTION_REGISTER } from '@/reducer/action.js'

export const receiveLogin = (dataName, data) => {
    return {
        type: ACTION_LOGIN,
        [dataName]: data
    }
}
// 封裝個(gè)通用的 actionCreate
export const receive = ( typeName, dataName, data) => {
    return {
        type: typeName,
        [dataName]: data
    }
}
  • reducer/action.js

添加action

export const SLIDECOLLAPSED = 'slidecollapsed'
export const ROUTERCONFIG = 'routerConfig'
export const ACTION_LOGIN = 'getLogin'
export const ACTION_REGISTER = 'ACTION_REGISTER'  // +
export const action_slidecollapsed = {type: SLIDECOLLAPSED}
export const routerConfig = { type: ROUTERCONFIG }
export const action_login = { type: ACTION_LOGIN }
export const action_register = { type: ACTION_REGISTER } // +
  • api/http.js

修改http.js, 添加響應(yīng)提示

import axios from 'axios'
import { message } from 'antd';
let loadingInstance = {
    close: () =>{}
}
// process.env.NODE_ENV === 'production' ? 'http://123.207.49.214:8028' : 'http://123.207.49.214:8028'
// 創(chuàng)建axios實(shí)例
const service = axios.create({
    baseURL: "http://localhost:4000", // api的base_url
    timeout: 5000, // 請(qǐng)求超時(shí)時(shí)間
    //設(shè)置默認(rèn)請(qǐng)求頭腻异,使post請(qǐng)求發(fā)送的是formdata格式數(shù)據(jù)// axios的header默認(rèn)的Content-Type好像是'application/json;charset=UTF-8',我的項(xiàng)目都是用json格式傳輸进副,如果需要更改的話,可以用這種方式修改
    // headers: {
    // "Content-Type": "application/x-www-form-urlencoded"
    // },
    // withCredentials: true, // 允許攜帶cookie
})
function cloneLoading () {
    loadingInstance.close()
}

// request攔截器
service.interceptors.request.use(config => {
    return config
}, error => {
    cloneLoading()
    // Do something with request error
    Promise.reject(error)
})

// respone攔截器
service.interceptors.response.use(
    response => {
        cloneLoading()
        if (response.data && response.data.code === 0) {
            message.error(response.data.message, 1.5)
        } else if (response.data && response.data.code === 200) {
            message.success(response.data.message, 1.5)
        }
        return response.data
    }, error => {
        console.log('err' + error)// for debug
        cloneLoading()
        if (error && error.response) {
            switch (error.response.status) {
                case 400:
                    error.desc = '請(qǐng)求錯(cuò)誤'
                    break;
                case 401:
                    error.desc = '未授權(quán)悔常,請(qǐng)登錄'
                    break;
                case 403:
                    error.desc = '拒絕訪問'
                    break;
                case 404:
                    error.desc = `請(qǐng)求地址出錯(cuò): ${error.response.config.url}`
                    break;
                case 408:
                    error.desc = '請(qǐng)求超時(shí)'
                    break;
                case 500:
                    error.desc = '服務(wù)器內(nèi)部錯(cuò)誤'
                    break;
                case 501:
                    error.desc = '服務(wù)未實(shí)現(xiàn)'
                    break;
                case 502:
                    error.desc = '網(wǎng)關(guān)錯(cuò)誤'
                    break;
                case 503:
                    error.desc = '服務(wù)不可用'
                    break;
                case 504:
                    error.desc = '網(wǎng)關(guān)超時(shí)'
                    break;
                case 505:
                    error.desc = 'HTTP版本不受支持'
                    break;
            }
            message.error(error.desc)
        }
        return Promise.reject(error)
    })

export default service


  • views/login/index.js
    既然提取了login的 connect參數(shù)影斑, 這里就要修改 login頁面
    刪除 fetchPosts, loginMap
import { mapLogin } from '@/reducer/connect.js'


export default connect(mapLogin.mapStateToProps, mapLogin.mapDispatchToProps)(Form.create()(Login)); // +
function fetchPosts(subreddit, data) { // -
    return dispatch => {
        dispatch(receiveLogin(subreddit, '暫無數(shù)據(jù)'))
        return http.post(`/login`, data)
            .then(res => {
                dispatch(receiveLogin(subreddit, res))
            })
    }
}
export const loginMap = { // -
    mapStateToProps (state) {
        return state.getLogin
    },
    mapDispatchToProps (dispatch) {
        return {handleLogin: (data) => {
            return dispatch(fetchPosts('loginData', data))
        }}
    }
}
  • reducer/reduxs.js
    新增 ACTION_REGISTER机打, getReigster與導(dǎo)出 新的allReducer
import {SLIDECOLLAPSED, ROUTERCONFIG, ACTION_LOGIN, ACTION_REGISTER} from '@/reducer/action.js'
const getReigster = (state = {}, action) => {
    switch (action.type) {
        case ACTION_REGISTER:
            return {...state, ...action}
        default :
            return state
    }
}

export const allReducer = combineReducers({
    slidecollapsed: slidecollapsedFuc, routerConfig: getRouterConfig, getLogin: getLoginFun, getReigster
})

這樣矫户, 就修改完成了。

  1. 驗(yàn)證接口是否成功

之前在http.js修改了提示姐帚, 不管請(qǐng)求成功或是失敗吏垮, 都會(huì)有彈框出來提示障涯。
當(dāng)然罐旗, 也可以查看內(nèi)容是否注入到組件內(nèi)
在register組件內(nèi)膳汪, 在render內(nèi)打印出 this.pros出來,
還記得我們?cè)?connect.js內(nèi)添加的內(nèi)容么九秀?

    mapDispatchToProps (dispatch) {
        return {hanleRegister: (data) => {
                return dispatch(fetchPosts('/register', ACTION_REGISTER,'reigsterData', data))
            }}
    }

這里的reigsterData就是注入到組件內(nèi)的內(nèi)容遗嗽。 查看是否有該內(nèi)容, 如果有鼓蜒, 查看是否是請(qǐng)求后的返回值痹换。
里面包含這個(gè)參數(shù), 表示注冊(cè)成功都弹。

{
    regsterData: {
        code : 200
        message : "注冊(cè)成功"
    }
}
  1. 注冊(cè)完畢后娇豫, 自動(dòng)登錄
  • 修改 reducer/connect.js

添加 handleLogin 登錄事件

export const mapReigster = {
    mapStateToProps (state) {
        return state.getReigster || state
    },
    mapDispatchToProps (dispatch) {
        return {hanleRegister: (data) => {
                return dispatch(fetchPosts('/register', ACTION_REGISTER,'reigsterData', data))
            },
            handleLogin: (data) => {
                return dispatch(fetchPosts('/login', ACTION_REGISTER, 'loginData', data))
            }
        }
    }
}
  • views/register/index.js
    state = {
        confirmDirty: false,
        autoCompleteResult: [],
        formValue: [],  // 添加保存內(nèi)容
        isLoginLoading: false // 添加是否已經(jīng)請(qǐng)求
    };

        handleSubmit = (e) => {
            e.preventDefault();
            this.props.form.validateFieldsAndScroll((err, values) => {
                if (!err) {
                    console.log('Received values of form: ', values);
                    this.props.hanleRegister(values)
                    this.setState({  // 注冊(cè)完畢, 保存內(nèi)容畅厢,并修改狀態(tài)冯痢。
                        formValue: values,
                        isLoginLoading: false
                    })
                }
            });
        }
        // render內(nèi)
        let { reigsterData, loginData } = this.props  // 新增注入的數(shù)據(jù)
        // 注冊(cè)成功, 自動(dòng)登錄
        if (typeof reigsterData === 'object' && reigsterData.code === 200) {
            if (!this.state.isLoginLoading) { // 判斷是否已經(jīng)請(qǐng)求過框杜,
                this.props.handleLogin(this.state.formValue) // 請(qǐng)求登錄浦楣。
                this.setState({
                    isLoginLoading: true
                })
            }
            if (typeof loginData === 'object' && loginData.code === 200) { // 登錄成功, 跳轉(zhuǎn)頁面咪辱。
                sessionStorage.setItem('isAuthenticated', true)
                let from = {}
                from.pathname = '/';
                return <Redirect to={from} />;
            }
        }

這樣振劳, 注冊(cè)與注冊(cè)完畢后自動(dòng)登錄就已經(jīng)完成。

需要注意的是油狂, 這里是自己寫的一個(gè)后臺(tái)历恐, 登錄賬號(hào)與密碼已經(jīng)寫死, admin 123456专筷, 所以夹供, 這里注冊(cè)的時(shí)候, 雖然隨便輸入什么都能夠注冊(cè)成功仁堪, 但是登陸的時(shí)候哮洽, 只有admin 123456才能夠登錄成功。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末弦聂,一起剝皮案震驚了整個(gè)濱河市鸟辅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌莺葫,老刑警劉巖匪凉,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異捺檬,居然都是意外死亡再层,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來聂受,“玉大人蒿秦,你說我怎么就攤上這事〉凹茫” “怎么了棍鳖?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)碗旅。 經(jīng)常有香客問我渡处,道長(zhǎng),這世上最難降的妖魔是什么祟辟? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任医瘫,我火速辦了婚禮,結(jié)果婚禮上旧困,老公的妹妹穿的比我還像新娘醇份。我一直安慰自己,他們只是感情好叮喳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布被芳。 她就那樣靜靜地躺著,像睡著了一般馍悟。 火紅的嫁衣襯著肌膚如雪畔濒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天锣咒,我揣著相機(jī)與錄音侵状,去河邊找鬼。 笑死毅整,一個(gè)胖子當(dāng)著我的面吹牛趣兄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播悼嫉,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼艇潭,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了戏蔑?” 一聲冷哼從身側(cè)響起蹋凝,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎总棵,沒想到半個(gè)月后鳍寂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡情龄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年迄汛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了捍壤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鞍爱,死狀恐怖鹃觉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情硬霍,我是刑警寧澤帜慢,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布笼裳,位于F島的核電站唯卖,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏躬柬。R本人自食惡果不足惜拜轨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望允青。 院中可真熱鬧橄碾,春花似錦、人聲如沸颠锉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽琼掠。三九已至拒垃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瓷蛙,已是汗流浹背悼瓮。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國打工亚再, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留垫卤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓谴返,卻偏偏與公主長(zhǎng)得像冠桃,于是被迫代替她去往敵國和親命贴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容