前言
目录
- 前言
- 一、房屋详情模块
- 二、登录模块
- 2.1 登录模块效果图
- 2.2 基础布局
- 2.3 调用接口实现登录
- 2.4 实现表单验证功能
- 2.4.1 formik介绍
- 2.4.2 formik基本使用
- 2.4.3 添加表单验证
- 2.5 代码优化
- 总结
一、房屋详情模块
房屋详情模块主要是展示之前获取到的房源信息,由于功能比较简单,这里不做过多赘述
二、登录模块
2.1 登录模块效果图
2.2 基础布局
在src/pages/Login/index.js中添加如下代码:
<div className={styles.root}>
{/* 顶部导航 */}
<NavHeader className={styles.navHeader}>账号登录</NavHeader>
<WhiteSpace size="xl" />
{/* 登录表单 */}
<WingBlank>
<form>
<div className={styles.formItem}>
<input
className={styles.input}
name="username"
placeholder="请输入账号"
/>
</div>
<div className={styles.formItem}>
<input
className={styles.input}
name="password"
type="password"
placeholder="请输入密码"
/>
</div>
<div className={styles.formSubmit}>
<button className={styles.submit} type="submit">
登 录
</button>
</div>
</form>
<Flex className={styles.backHome}>
<Flex.Item>
<Link to="/registe">还没有账号,去注册~</Link>
</Flex.Item>
</Flex>
</WingBlank>
</div>
2.3 调用接口实现登录
实现步骤:
1、添加状态:username和password
2、使用受控组件方式获取表单元素值
3、给form表单添加onSubmit
4、创建方法 handleSubmit,实现表单提交
5、在方法中,通过username和password获取到账号和密码
6、使用API调用登录接口,将username和password作为参数
7、判断返回值status为200时候,表示登录成功
8、登录成功后,将token保存到本地存储中(hkzf_token)
9、返回登录前的页面
代码示例:
在src/pages/Login/index.js中添加如下代码:
state = {
username: '',
password: ''
}
getUserName = e => {
this.setState({
username: e.target.value
})
}
getPassword = e => {
this.setState({
password: e.target.value
})
}
// 表单提交事件的事件处理程序
handleSubmit = async e => {
// 阻止表单提交时的默认行为
e.preventDefault()
// 获取账号和密码
const { username, password } = this.state
// 发送请求
const res = await API.post('/user/login', {
username,
password
})
const { status, body, description } = res.data
if (status === 200) {
// 登录成功
localStorage.setItem('hkzf_token', body.token)
this.props.history.go(-1)
} else {
// 登录失败
Toast.info(description, 2, null, false)
}
}
render() {
const { username, password } = this.state
return (
<div className={styles.root}>
...
{/* 登录表单 */}
<WingBlank>
<form onSubmit={this.handleSubmit}>
<div className={styles.formItem}>
<input
className={styles.input}
value={username}
onChange={this.getUserName}
name="username"
placeholder="请输入账号"
/>
</div>
<div className={styles.formItem}>
<input
className={styles.input}
value={password}
onChange={this.getPassword}
name="password"
type="password"
placeholder="请输入密码"
/>
</div>
...
</div>
)
}
}
2.4 实现表单验证功能
2.4.1 formik介绍
1、使用场景:表单处理,表单验证
2、优势:轻松处理React中的复杂表单,包括:获取表单元素的值,表单验证和错误信息,处理表单提交,并且将这些内容放在一起统一处理,有利于代码阅读,重构,测试等
3、使用方式:1. 高阶组件(withFormik) 2. render-props(<Formik render={() => {}} />)
2.4.2 formik基本使用
使用步骤:
1、安装: yarn add formik
2、导入 withFormik,使用withFormit 高阶组件包裹Login组件
3、为withFormit提供配置对象: mapPropsToValues / handleSubmit
4、在Login组件中,通过props获取到values(表单元素值对象),handleSubmit,handleChange
5、使用values提供的值,设置为表单元素的value,使用handleChange设置为表单元素的onChange
6、使用handleSubmit设置为表单的onSubmit
7、在handleSubmit中,通过values获取到表单元素值
8、在handleSubmit中,完成登录逻辑
代码示例:
在src/pages/Login/index.js中添加如下代码:
class Login extends Component {
render() {
// 通过 props 获取高阶组件传递进来的属性
const { values, handleSubmit, handleChange } = this.props
return (
<div className={styles.root}>
{/* 顶部导航 */}
<NavHeader className={styles.navHeader}>账号登录</NavHeader>
<WhiteSpace size="xl" />
{/* 登录表单 */}
<WingBlank>
<form onSubmit={handleSubmit}>
<div className={styles.formItem}>
<input
className={styles.input}
value={values.username}
onChange={handleChange}
name="username"
placeholder="请输入账号"
/>
</div>
<div className={styles.formItem}>
<input
className={styles.input}
value={values.password}
onChange={handleChange}
name="password"
type="password"
placeholder="请输入密码"
/>
</div>
<div className={styles.formSubmit}>
<button className={styles.submit} type="submit">
登 录
</button>
</div>
</form>
<Flex className={styles.backHome}>
<Flex.Item>
<Link to="/registe">还没有账号,去注册~</Link>
</Flex.Item>
</Flex>
</WingBlank>
</div>
)
}
}
// 使用 withFormik 高阶组件包装 Login 组件,为 Login 组件提供属性和方法
Login = withFormik({
// 提供状态:
mapPropsToValues: () => ({ username: '', password: '' }),
// 表单的提交事件
handleSubmit: async (values, { props }) => {
// 获取账号和密码
const { username, password } = values
// 发送请求
const res = await API.post('/user/login', {
username,
password
})
const { status, body, description } = res.data
if (status === 200) {
// 登录成功
localStorage.setItem('hkzf_token', body.token)
// 注意:无法在该方法中,通过 this 来获取到路由信息
// 所以,需要通过 第二个对象参数中获取到 props 来使用 props
props.history.go(-1)
} else {
// 登录失败
Toast.info(description, 2, null, false)
}
}
})(Login)
// 注意:此处返回的是 高阶组件 包装后的组件
export default Login
2.4.3 添加表单验证
实现步骤:
1、安装Yup: yarn add yup
2、在项目中导入Yup
3、在 withFormik 中添加配置项 validationSchema,使用 Yup 添加表单校验规则
4、在 Login 组件中,通过 props 获取到 errors(错误信息)和 touched(是否访问过,注意:需要给表单元素添加 handleBlur 处理失焦点事件才生效!)
5、在表单元素中通过这两个对象展示表单校验错误信
代码示例:
在src/pages/Login/index.js中添加如下代码:
{/* 登录表单 */}
<WingBlank>
<form onSubmit={handleSubmit}>
... 用户名的错误提示
{errors.username && touched.username && (
<div className={styles.error}>{errors.username}</div>
)}
... 密码框的错误提示
{errors.password && touched.password && (
<div className={styles.error}>{errors.password}</div>
)}
...
</WingBlank>
// 使用 withFormik 高阶组件包装 Login 组件,为 Login 组件提供属性和方法
Login = withFormik({
...
// 添加表单校验规则
validationSchema: Yup.object().shape({
username: Yup.string()
.required('账号为必填项')
.matches(REG_UNAME, '长度为5到8位,只能出现数字、字母、下划线'),
password: Yup.string()
.required('密码为必填项')
.matches(REG_PWD, '长度为5到12位,只能出现数字、字母、下划线')
}),
...
})(Login)
2.5 代码优化
优化步骤:
1、导入 Form组件,替换form元素,去掉onSubmit
2、导入Field组件,替换input表单元素,去掉onChange,onBlur,value
3、导入 ErrorMessage 组件,替换原来的错误消息逻辑代码
4、去掉所有 props
代码示例:
在src/pages/Login/index.js中修改如下代码:
// 导入withFormik
import { withFormik, Form, Field, ErrorMessage } from 'formik'
<Form>
{/* 账号 */}
<div className={styles.formItem}>
<Field
className={styles.input}
name="username"
placeholder="请输入账号"
/>
</div>
<ErrorMessage
className={styles.error}
name="username"
component="div"
/>
{/* 密码 */}
<div className={styles.formItem}>
<Field
className={styles.input}
name="password"
type="password"
placeholder="请输入密码"
/>
</div>
<ErrorMessage
className={styles.error}
name="password"
component="div"
/>
<div className={styles.formSubmit}>
<button className={styles.submit} type="submit">
登 录
</button>
</div>
</Form>