詳解對(duì)于React結(jié)合Antd的Form組件實(shí)現(xiàn)登錄功能
一、React 結(jié)合 Antd 實(shí)現(xiàn)登錄功能
引入所需的 Antd 組件,代碼如下所示:
import { Form, Icon, Input, Button, message } from 'antd'
在 Login.jsx 中,創(chuàng)建一個(gè) Login 組件。當(dāng)對(duì)外暴露組件時(shí),需要使用 Form 組件進(jìn)行包裝,包裝 Form 組件生成一個(gè)新的組件 Form(Login),同時(shí)新組件會(huì)向 Form 組件傳遞一個(gè)強(qiáng)大的對(duì)象屬性 form,這樣就可以取到 Form 表單的值,這也是高階組件和高階函數(shù)的體現(xiàn),代碼如下所示:
class Login extends Component {} const WrapLogin = Form.create()(Login) export default WrapLogin
在 render 內(nèi)部去渲染表單時(shí),可以先通過(guò) this.props 去拿到 form 表單,在 form 中取得 getFieldDecorator,用于和表單進(jìn)行雙向綁定。在 getFieldDecorator 中,第一項(xiàng)是表單項(xiàng)對(duì)應(yīng)的 value 值,第二項(xiàng)是配置對(duì)象,屬性名是特定的一些名稱(chēng)。比如,rules 是驗(yàn)證規(guī)則,在 rules 中,可以設(shè)置 required 為是否必選,message 為校驗(yàn)文案,pattern 為正則表達(dá)式校驗(yàn),max 為最大長(zhǎng)度,min 為最小長(zhǎng)度。還比如 initialValue 是表單項(xiàng)的初始值。對(duì)于 rules 校驗(yàn),可以使用聲明式驗(yàn)證, 也就是直接使用別人定義好的驗(yàn)證規(guī)則進(jìn)行驗(yàn)證,還可以自定義驗(yàn)證 validator,function(rule, value, callback),必須有 callback 回調(diào)函數(shù),代碼如下所示:
class Login extends Component { validPwd = (rule, value, callback) => { if (!value) { callback('密碼必須輸入') } else if (value.length < 4) { callback('密碼長(zhǎng)度不能小于4位') } else if (value.length > 12) { callback('密碼長(zhǎng)度不能大于12位') } else if (!/^[a-zA-Z0-9_]+$/.test(value)) { callback('密碼必須是英文、數(shù)字或下劃線組成') } else { callback() } } render () { const form = this.props.form const { getFieldDecorator } = form return ( <div className="login"> <header className="login-header"> <img src={logo} alt="logo"></img> <h1>React 后臺(tái)管理系統(tǒng)</h1> </header> <section className="login-content"> <h2>用戶登錄</h2> <Form> <Form.Item> { getFieldDecorator('username', { rules: [ { required: true, whitespace: true, message: '用戶名必須輸入'}, { min: 4, message: '用戶名至少是4位'}, { max: 12, message: '用戶名至少是12位'}, { pattern: /^[a-zA-Z0-9_]+$/, message: '用戶名必須是英文、數(shù)字或下劃線組成'} ], // initialValue: 'admin', })( <Input prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="用戶名" /> ) } </Form.Item> <Form.Item> { getFieldDecorator('password', { rules: [ { validator: this.validPwd } ] })( <Input prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />} type="password" placeholder="密碼" /> ) } </Form.Item> <Form.Item> <Button type="primary" htmlType="submit" className="login-form-button"> 登陸 </Button> </Form.Item> </Form> </section> </div> ) } } const WrapLogin = Form.create()(Login) export default WrapLogin
我們可以定義兩個(gè)工具類(lèi),用來(lái)操作登錄對(duì)象,memoryUtils 是用來(lái)在內(nèi)存保存一些數(shù)據(jù)的工具模塊,storageUtils 是進(jìn)行 local 數(shù)據(jù)存儲(chǔ)管理的工具模塊,如下所示:
memoryUtils.js,代碼如下所示:
export default { user: {}, product: {} }
storageUtils.js,代碼如下所示:
import store from 'store' const USER_KEY = 'user_key' export default { // 保存 user saveUser (user) { store.set(USER_KEY, user) }, // 讀取 user getUser () { return store.get(USER_KEY) || {} }, // 刪除 user removeUser () { store.remove(USER_KEY) } }
定義登錄的接口請(qǐng)求函數(shù),使用 axios 可以先進(jìn)行封裝,得到 response.data,如下所示:
ajax.js,代碼如下所示:
import axios from 'axios' import {message} from 'antd' export default function ajax(url, data={}, type='GET') { return new Promise((resolve, reject) => { let promise if(type==='GET') { promise = axios.get(url, { params: data }) } else { promise = axios.post(url, data) } promise.then(response => { resolve(response.data) }).catch(error => { message.error('請(qǐng)求出錯(cuò)了: ' + error.message) }) }) }
index.js,代碼如下所示:
import jsonp from 'jsonp' import ajax from './ajax' import { message } from 'antd' const BASE = '' export const reqLogin = (username, password) => ajax(BASE + '/login', { username, password}, 'POST') export const reqCategories = (parentId) => ajax(BASE + '/manage/category/list', {parentId}) export const reqAddCategories = ({parentId, categoryName}) => ajax(BASE + '/manage/category/add', {parentId, categoryName}, 'POST') export const reqUpdateCategories = ({categoryId, categoryName}) => ajax(BASE + '/manage/category/update', {categoryId, categoryName}, 'POST') export const reqCategory = (categoryId) => ajax(BASE + '/manage/category/info', { categoryId }) export const reqProducts = ({pageNum, pageSize}) => ajax(BASE + '/manage/product/list', { pageNum, pageSize}) export const reqUpdateStatus = ({productId, status}) => ajax(BASE + '/manage/product/updateStatus', {productId, status}, 'POST') export const reqSearchProducts = ({ pageNum, pageSize, searchName, searchType}) => ajax(BASE + '/manage/product/search', { pageNum, pageSize, [searchType]: searchName }) export const reqDeleteImg = (name) => ajax(BASE + '/manage/img/delete', {name}, 'POST') export const reqAddUpdateProduct = (product) => ajax(BASE + '/manage/product/' + (product._id ? 'update' : 'add'), product, 'POST') export const reqRoles = () => ajax(BASE + '/manage/role/list') export const reqAddRole = (roleName) => ajax(BASE + '/manage/role/add', {roleName}, 'POST') export const reqUpdateRole = (role) => ajax(BASE + '/manage/role/update', role, 'POST') export const reqUsers = () => ajax(BASE + '/manage/user/list') export const reqDeleteUser = (userId) => ajax(BASE + '/manage/user/delete', {userId}, 'POST') export const reqAddOrUpdateUser = (user) => ajax(BASE + '/manage/user/'+(user._id ? 'update': 'add'), user, 'POST') export const reqWeather = (city) => { return new Promise((resolve, reject) => { const url = `http://api.map.baidu.com/telematics/v3/weather?location=${city}&output=json&ak=IOXimfoqOUVq2KcYCiQU9cMF7hyN5kFB` jsonp(url, {}, (err, data) => { console.log('jsonp()', err, data) if (!err && data.status==='success') { const {dayPictureUrl, weather} = data.results[0].weather_data[0] resolve({dayPictureUrl, weather}) } else { message.error('獲取天氣信息失敗!') } }) }) }
引入這些工具類(lèi)和接口,代碼如下所示:
import { reqLogin } from '../../api' import memoryUtils from '../../utils/memoryUtils' import storageUtils from '../../utils/storageUtils'
給 Form 表單綁定 onSubmit 事件,handleSubmit。在這個(gè)事件中,需要先使用 event.preventDefault() 阻止事件的默認(rèn)行為。如果想要獲取表單項(xiàng)的輸入數(shù)據(jù),可以使用 form.getFieldsValue()。但是,在提交表單前需要對(duì)表單數(shù)據(jù)進(jìn)行預(yù)校驗(yàn),使用 this.props.form.validateFields 進(jìn)行預(yù)校驗(yàn),validateFields 可以獲取所有表單字段的值,并且可以判斷表單數(shù)據(jù)是否有錯(cuò)。如有 沒(méi)錯(cuò),說(shuō)明預(yù)校驗(yàn)通過(guò),從 values 中獲取 username 和 password 的值,然后通過(guò) reqLogin 這個(gè)接口結(jié)合 async 和 await 發(fā)起登錄請(qǐng)求。如果響應(yīng)的狀態(tài)碼正確,說(shuō)明登錄成功,保存 user,保存在內(nèi)存和本地中,然后使用 this.props.history.replace 跳轉(zhuǎn)到主管理界面中,反之則登錄失敗。在 render 中,如果用戶已經(jīng)登陸, 需要使用 Redirect 自動(dòng)跳轉(zhuǎn)到主管理界面中,代碼如下所示:
handleSubmit = (event) => { event.preventDefault() this.props.form.validateFields(async (err, values) => { if (!err) { const { username, password } = values const result = await reqLogin(username, password) if (result.status === 0) { message.success('登錄成功') const user = result.data memoryUtils.user = user storageUtils.saveUser(user) this.props.history.replace('/') } else { message.error(result.msg) } } else { console.log(err) } })
二、React 結(jié)合 Antd 實(shí)現(xiàn)登錄功能的實(shí)現(xiàn)
React 結(jié)合 Antd 實(shí)現(xiàn)登錄功能的實(shí)現(xiàn),完整代碼如下所示:
login.jsx,代碼如下所示:
import React, { Component } from 'react' import { Form, Icon, Input, Button, message } from 'antd' import { Redirect } from 'react-router-dom' import './login.less' import logo from '../../assets/images/logo.png' import { reqLogin } from '../../api' import memoryUtils from '../../utils/memoryUtils' import storageUtils from '../../utils/storageUtils' class Login extends Component { handleSubmit = (event) => { event.preventDefault() this.props.form.validateFields(async (err, values) => { if (!err) { const { username, password } = values const result = await reqLogin(username, password) if (result.status === 0) { message.success('登錄成功') const user = result.data memoryUtils.user = user storageUtils.saveUser(user) this.props.history.replace('/') } else { message.error(result.msg) } } else { console.log(err) } }) } validPwd = (rule, value, callback) => { if (!value) { callback('密碼必須輸入') } else if (value.length < 4) { callback('密碼長(zhǎng)度不能小于4位') } else if (value.length > 12) { callback('密碼長(zhǎng)度不能大于12位') } else if (!/^[a-zA-Z0-9_]+$/.test(value)) { callback('密碼必須是英文、數(shù)字或下劃線組成') } else { callback() } } render () { const user = memoryUtils.user if (user && user._id) { return <Redirect to="/"></Redirect> } const form = this.props.form const { getFieldDecorator } = form return ( <div className="login"> <header className="login-header"> <img src={logo} alt="logo"></img> <h1>React 后臺(tái)管理系統(tǒng)</h1> </header> <section className="login-content"> <h2>用戶登錄</h2> <Form onSubmit={this.handleSubmit}> <Form.Item> { getFieldDecorator('username', { rules: [ { required: true, whitespace: true, message: '用戶名必須輸入'}, { min: 4, message: '用戶名至少是4位'}, { max: 12, message: '用戶名至少是12位'}, { pattern: /^[a-zA-Z0-9_]+$/, message: '用戶名必須是英文、數(shù)字或下劃線組成'} ], // initialValue: 'admin', })( <Input prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="用戶名" /> ) } </Form.Item> <Form.Item> { getFieldDecorator('password', { rules: [ { validator: this.validPwd } ] })( <Input prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />} type="password" placeholder="密碼" /> ) } </Form.Item> <Form.Item> <Button type="primary" htmlType="submit" className="login-form-button"> 登陸 </Button> </Form.Item> </Form> </section> </div> ) } } const WrapLogin = Form.create()(Login) export default WrapLogin
login.less,代碼如下所示:
.login { width: 100%; height: 100%; background-image: url('./images/bg.jpg'); background-size: 100% 100%; .login-header { display: flex; align-items: center; height: 80px; background-color: rgba(21, 20, 13, 0.5); img { width: 40px; height: 40px; margin: 0 15px 0 50px; } h1 { font-size: 30px; color: white; } } .login-content { width: 400px; height: 300px; background-color: #fff; margin: 50px auto; padding: 20px 40px; h2 { text-align: center; font-size: 30px; font-weight:bold; margin-bottom: 20px; } .login-form { .login-form-button { width: 100%; } } } }
到此這篇關(guān)于詳解對(duì)于React結(jié)合Antd的Form組件實(shí)現(xiàn)登錄功能的文章就介紹到這了,更多相關(guān)React Antd Form登錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解React setState數(shù)據(jù)更新機(jī)制
這篇文章主要介紹了React setState數(shù)據(jù)更新機(jī)制的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用React框架,感興趣的朋友可以了解下2021-04-04快速創(chuàng)建React項(xiàng)目并配置webpack
這篇文章主要介紹了創(chuàng)建React項(xiàng)目并配置webpack,在這里需要注意,Create?React?App?requires?Node?14?or?higher.需要安裝高版本的node,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧2022-01-01React在組件中如何監(jiān)聽(tīng)redux中state狀態(tài)的改變
這篇文章主要介紹了React在組件中如何監(jiān)聽(tīng)redux中state狀態(tài)的改變,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08Redux?Toolkit的基本使用示例詳解(Redux工具包)
這篇文章主要介紹了Redux?Toolkit的基本使用,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12使用React?Router?v6?添加身份驗(yàn)證的方法
這篇文章主要介紹了使用React?Router?v6?進(jìn)行身份驗(yàn)證完全指南,本文將演示如何使用React?Router?v6創(chuàng)建受保護(hù)的路由以及如何添加身份驗(yàn)證,需要的朋友可以參考下2022-05-05React18?useState何時(shí)執(zhí)行更新及微任務(wù)理解
這篇文章主要為大家介紹了React18?useState何時(shí)執(zhí)行更新及微任務(wù)理解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11解決react中useState狀態(tài)異步更新的問(wèn)題
本文主要介紹了react中useState狀態(tài)異步更新的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07Redux DevTools不能顯示數(shù)據(jù)問(wèn)題
這篇文章主要介紹了Redux DevTools不能顯示數(shù)據(jù)問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01