<div className={styles.psw} style={{ height: '540px' }}>
<div className={styles.pswTitle}>找回密码</div>
<div className={styles.line1}></div>
<div className={styles.line2}></div>
<div>
<Form layout="inline">
<div className={styles.inputW}>
<div>
<div className={styles.iconPosition}>
<img
src={usericon}
alt=""
style={{ width: '15px', height: '20px' }}
/>
<span className={styles.inputText}>
<span style={{ color: 'red' }}>*</span>用户名
</span>
</div>
<FormItem>
{getFieldDecorator('userName', {
rules: [
{
required: true,
message: '请输入用户名'
}
]
})(<Input placeholder="请输入用户名" />)}
</FormItem>
</div>
</div>
<div className={styles.inputW}>
<div>
<div className={styles.iconPosition}>
<img
src={phoneIcon}
alt=""
style={{ width: '15px', height: '20px' }}
/>
<span className={styles.inputText}>
<span style={{ color: 'red' }}>*</span>手机号
</span>
</div>
<FormItem>
{getFieldDecorator('mobile', {
rules: [
{
required: true,
pattern: /^1[34578]\d{9}$/,
message: '请输入正确的手机号码'
}
]
})(<Input placeholder="请输入手机号" />)}
</FormItem>
</div>
</div>
<div className={styles.inputW}>
<div>
<div className={styles.iconPosition}>
<img
src={passwordIcon}
alt=""
style={{ width: '15px', height: '20px' }}
/>
<span
className={styles.inputText}
style={{ width: '70px' }}
>
<span style={{ color: 'red' }}>*</span>设置密码
</span>
</div>
<FormItem>
{getFieldDecorator('password', {
rules: [
{
required: true,
message: '请输入6-16位字符和数字组合,字符区分大小写',
// eslint-disable-next-line
pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$/
},
{ validator: validateToNextPassword }
]
})(<Input.Password placeholder="请输入密码" />)}
</FormItem>
</div>
</div>
<div className={styles.inputW}>
<div>
<div className={styles.iconPosition}>
<img
src={passwordIcon}
alt=""
style={{ width: '15px', height: '20px' }}
/>
<span
className={styles.inputText}
style={{ width: '70px' }}
>
<span style={{ color: 'red' }}>*</span>确认密码
</span>
</div>
<FormItem>
{getFieldDecorator('comfirm', {
rules: [
{ required: true, message: '请输入确认密码' },
{ validator: compareToFirstPassword }
]
})(
<Input.Password
onBlur={handleConfirmBlur}
placeholder="请再次输入密码"
/>
)}
</FormItem>
</div>
</div>
<div className={styles.inputW1} style={{ position: 'relative' }}>
<div>
<div className={styles.iconPosition}>
<img
src={check}
alt=""
style={{ width: '15px', height: '20px' }}
/>
<span
className={styles.inputText}
style={{ width: '70px' }}
>
<span style={{ color: 'red' }}>*</span>短信验证
</span>
</div>
<YZMButton
onClick={onclick}
time={time}
className={styles.yzmc}
/>
<FormItem>
{getFieldDecorator('smsCode', {
rules: [
{
required: true,
message: '请输入'
}
]
})(<Input placeholder="请输入验证码" />)}
</FormItem>
</div>
</div>
<div className={styles.button} style={{ margin: '30px 50px' }}>
<Button
onClick={() => {
window.history.back()
}}
className={styles.backButton}
>
返回
</Button>
<Button onClick={handlOnsave} className={styles.findButton}>
找回密码
</Button>
</div>
</Form>
</div>
</div>
(2)使用验证码组件YZMButton
import React, { useCallback, useState, useRef } from 'react'
import styles from './index.less'
import classnames from 'classnames'
import { Button } from 'antd'
interface YZMButtonProps {
onClick: (e: any) => any
time: number
text?: string
className: any
}
export default function YZMButton({
onClick,
time,
text,
className
}: YZMButtonProps) {
const [yzime, setYzime] = useState(time)
const _yzime = useRef(yzime)
_yzime.current = yzime
const flag = yzime === time
const handleClick = useCallback(
(e: any) => {
if (flag) {
if (!onClick(e)) {
return
}
let timer = setInterval(() => {
if (_yzime.current === 0) {
clearInterval(timer)
setYzime(time)
} else {
setYzime(value => value - 1)
}
}, 1000)
}
},
[flag, onClick, time]
)
return (
<Button
className={classnames(styles.content, className)}
onClick={handleClick}
disabled={!flag}
>
{flag ? text || '获取验证码' : `还剩${yzime}s`}
</Button>
)
}
点击按钮之后,按钮变成不可用状态,与此同时60秒倒计时开始。
(3)调接口获取验证码
在click方法中,调用后端提供的方法获取短信验证码
const onclick = useCallback(() => {
let callbackRes = true
validateFields(['mobile'], (err: any, fieldsValue: any) => {
if (err) {
callbackRes = false
}
let { mobile } = fieldsValue
let res = {
mobile: mobile,
type: 'forget-password'
}
dispatch({
type: 'login/getyzm',
params: [res]
}).then((v: any) => {
if (v.code === -1) {
message.error(v.message)
callbackRes = false
} else if (v.code === 500) {
message.error(v.message)
callbackRes = false
} else {
callbackRes = true
}
})
})
return callbackRes
}, [dispatch, validateFields])
(4)提交表单 找回密码
const handlOnsave = useCallback(() => {
validateFields((err: any, fieldsValue: any) => {
if (err) return
let res = {
userName: fieldsValue.userName,
mobile: fieldsValue.mobile,
// password: btoa(fieldsValue.password),
newPassword: fieldsValue.password,
code: fieldsValue.smsCode
}
dispatch({
type: 'login/getback',
params: [res]
}).then((v: any) => {
if (v.code === 200) {
message.info(v.message)
window.location.href = '/#/login/password'
} else {
message.info(v.message)
}
})
})
}, [dispatch, validateFields])
二、图片验证码功能
=========
1. 实现思路
进入页面,前端向后端发送请求(需要UUID),获取一张二维码,之后提交表单的同时提交uuid和验证码,后端请求验证。后端使用到阿里的获取短信验证码的服务。
2. 后端接口
后端需要拿到uuid借助阿里的生成图片验证码的工具进行生成,并将图片验证码返回给前端。最后,需要借助前端提交的uuid和验证码信息进行比对,即可实现提交功能。
3. 前端实现
(1)使用uuid
UUID 是 通用唯一识别码.
安装依赖:npm install uuid
引入依赖:import { v4 as uuidv4 } from "uuid
生成uuid使用方法:const id =uuidv4()
console.log(id)
e6a2f201-f720-4e98-8fea-7f473101acd3
(2)进入页面获取验证码图片
const getCode = useCallback(() => {
let id = uuidv4()
setUuid(id)
let result = dispatch({
type: 'global/get1',
params: ['/uaa/captcha.jpg', { uuid: id }]
})
console.log(result)
return result
}, [dispatch, setUuid])
useEffect(() => {
getCode().then((v: any) => {
let a = window.URL.createObjectURL(v)
setCode(a)
})
}, [getCode])
生成图片的请求需要向后端提供一个uuid.
注意 这里的请求就是/uaa/captcha.jpg 你没有看错。
(3)处理后端返回的图片并显示
请求之后后端返回的是一张图片,注意是一张图片,而不是图片的url.
文末
逆水行舟不进则退,所以大家要有危机意识。
同样是干到35岁,普通人写业务代码划水,榜样们深度学习拓宽视野晋升管理。
这也是为什么大家都说35岁是程序员的门槛,很多人迈不过去,其实各行各业都是这样都会有个坎,公司永远都缺的高级人才,只用这样才能在大风大浪过后,依然闪耀不被公司淘汰不被社会淘汰。
为了帮助大家更好温习重点知识、更高效的准备面试,特别整理了《前端工程师核心知识笔记》电子稿文件。
内容包括html,css,JavaScript,ES6,计算机网络,浏览器,工程化,模块化,Node.js,框架,数据结构,性能优化,项目等等。
269页《前端大厂面试宝典》
包含了腾讯、字节跳动、小米、阿里、滴滴、美团、58、拼多多、360、新浪、搜狐等一线互联网公司面试被问到的题目,涵盖了初中级前端技术点。
前端面试题汇总