携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情
验证码弹窗
首先在components创建Login文件夹,在Login文件夹创建index.tsx文件和index.modules.scss
cd components
mkdir Login
cd Login
touch index.tsx
touch index.module.scss
在Navbar组件中的 登录按钮 添加点击事件
<Button type="primary" onClick={handleLogin}>
登录
</Button>
定义一个state来控制 登录弹窗 是否显示
将isShowLogin 当做 props 传入 登录组件
const [isShowLogin, setIsShowLogin] = useState(false);
当点击登录按钮时,显示 登录弹窗
const handleLogin = () => {
setIsShowLogin(true);
};
接下来 开始编写 登录弹窗
最终效果如下图:
代码如下:
return isShow ? (
<div className={styles.loginArea}>
<div className={styles.loginBox}>
<div className={styles.loginTitle}>
<div>手机号登录</div>
<div className={styles.close} onClick={handleClose}>
x
</div>
</div>
<input
name="phone"
type="text"
placeholder="请输入手机号"
value={form.phone}
onChange={handleFormChange}
/>
<div className={styles.verifyCodeArea}>
<input
name="verify"
type="text"
placeholder="请输入验证码"
value={form.verify}
onChange={handleFormChange}
/>
<span className={styles.verifyCode} onClick={handleGetVerifyCode}>
{isShowVerifyCode ? (
<CountDown time={10} onEnd={handleCountDownEnd} />
) : (
'获取验证码'
)}
</span>
</div>
<div className={styles.loginBtn} onClick={handleLogin}>
登录
</div>
<div className={styles.otherLogin} onClick={handleOAuthGithub}>
使用 Github 登录
</div>
<div className={styles.loginPrivacy}>
注册登录即表示同意
<a
href="https://moco.imooc.com/privacy.html"
target="_blank"
rel="noreferrer"
>
隐私政策
</a>
</div>
</div>
</div>
) : null;
css代码如下:
.loginArea {
position: fixed;
top: 0;
left: 0;
z-index: 1000;
width: 100vw;
height: 100vh;
background-color: rgb(0 0 0 / 30%);
.loginBox {
width: 320px;
height: 320px;
background-color: #fff;
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 20px;
input {
width: 100%;
height: 37px;
margin-bottom: 10px;
padding: 10px;
border-radius: 5px;
border: 1px solid #888;
outline: none;
}
input:focus {
border: 1px solid #1e80ff;
}
.verifyCodeArea {
position: relative;
cursor: pointer;
.verifyCode {
color: #1e80ff;
position: absolute;
right: 20px;
top: 8px;
font-size: 14px;
}
}
}
.loginTitle {
font-size: 20px;
font-weight: bold;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
.close {
color: #888;
cursor: pointer;
}
}
.loginBtn {
height: 40px;
line-height: 40px;
border-radius: 5px;
margin-top: 15px;
background-color: #007fff;
color: #fff;
text-align: center;
cursor: pointer;
}
.otherLogin {
margin-top: 15px;
font-size: 14px;
color: #1e80ff;
cursor: pointer;
}
.loginPrivacy {
margin-top: 10px;
color: #333;
font-size: 14px;
a {
color: #1e80ff;
}
}
}
接下来 编写 点击逻辑
首先 当点击关闭的时候,把弹窗关闭
使用 props 中的 onClose 方法,onClose方法在父组件 Navbar 通过isShowLogin控制隐藏
// Login/index.tsx
const { onClose } = props;
const handleClose = () => {
onClose && onClose();
};
<Login isShow={isShowLogin} onClose={handleClose} />
const handleClose = () => {
setIsShowLogin(false);
};
接下来开始编写 获取验证码的 逻辑
获取验证码 需要提前编写一个倒计时的组件
接下来开始编写 倒计时组件
cd components
mkdir CountDown
cd CountDown
touch index.tsx
touch index.module.scss
在index.tsx中编写如下代码:
思路是 提供一个 time,表示倒计时的时间。提供一个onEnd回调函数,表示当倒计时结束的时候,进行一些回调处理。
这里需要注意下, 当 time时间为0的时候,需要主动 调 一些 onEnd,表示结束。
import { useState, useEffect } from 'react';
import styles from './index.module.scss';
interface IProps {
time: number;
onEnd: Function;
}
const CountDown = (props: IProps) => {
const { time, onEnd } = props;
const [count, setCount] = useState(time || 60);
useEffect(() => {
const id = setInterval(() => {
setCount((count) => {
if (count === 0) {
clearInterval(id);
onEnd && onEnd();
return count;
}
return count - 1;
});
}, 1000);
return () => {
clearInterval(id);
};
}, [time, onEnd]);
return <div className={styles.countDown}>{count}</div>;
};
export default CountDown;
首先 通过 isShowVerifyCode 控制 显示 验证码文字 还是倒计时
<span className={styles.verifyCode} onClick={handleGetVerifyCode}>
{isShowVerifyCode ? (
<CountDown time={10} onEnd={handleCountDownEnd} />
) : (
'获取验证码'
)}
</span>
接着当点击 获取验证码的时候,校验一下 手机号是否输入, 如果手机号没有输入,提示用户输入手机号
<span className={styles.verifyCode} onClick={handleGetVerifyCode}>获取验证码</span>
const handleGetVerifyCode = () => {
if (!form?.phone) {
message.warning('请输入手机号');
return;
}
}
如果 手机号输入,则开始 调 获取验证码的接口
const handleGetVerifyCode = () => {
if (!form?.phone) {
message.warning('请输入手机号');
return;
}
request
.post('/api/user/sendVerifyCode', {
to: form?.phone,
templateId: 1,
})
.then((res: any) => {
if (res?.code === 0) {
setIsShowVerifyCode(true);
} else {
message.error(res?.msg || '未知错误');
}
});
};